欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

单片机学习(4)——点阵LED

程序员文章站 2022-06-08 20:57:17
...

一、基础知识

1、LED点阵原理

一个数码管是由8段LED灯组成的,同理,一个88的点阵是由64个LED点阵组成的。88LED点阵外观图如1-1:
单片机学习(4)——点阵LED
内部结构图如下图1-2:
单片机学习(4)——点阵LED若想点亮LED点阵,就要使得D端为高电平,P端为低电平。以普中科技的开发板为例,相关原理图如1-3所示,对应图1-2左侧的内部结构图。
单片机学习(4)——点阵LED

2、74HC595芯片
单片机学习(4)——点阵LED(1)原理介绍
74HC595是一个8位串行输入、并行输出的位移缓存器。引脚图如下图:
单片机学习(4)——点阵LED
其中主要用的引脚有:
SER(14) = P3 ^ 4 , 串行数据输入(0或1);
RCLK(12) = P3 ^ 5 ,存储器输入时钟,并行输出开关,脉冲宽度:接+5V电源时,大于十几纳秒即可。;
SRCLK(11)= P3 ^ 6 , 移位寄存器输入时钟,串行输入开关,脉冲宽度:接+5V电源时,大于十几纳秒即可。

其余引脚作用见下表:

符号 引脚 描述
Q0~Q7 第15脚,第1~7脚 8位并行数据输出
GND 第8脚 接地
Q7’ 第9脚 串行数据输出(级联引脚,接14脚)
MR 第10脚 主复位,低电平有效,一般接高电平
SHCP 第11脚 串行输入开关上升沿有效
STCP 第12脚 并行输出开关上升沿有效
OE 第13脚 输出有效(低电平)
DS 第14脚 串行数据输入(0或1)
VCC 第16脚 电源

(2)芯片使用过程

  • STCP(12)(RCLK)→ 0 // 输出寄存器状态保持

  • SHCP(11)(SRCLK)→ 0 // 移位寄存器状态保持

  • DS(14)→ 0/1 //存储0或1

  • SHCP(11)(SRCLK)→ 1 // 移位寄存器存储
    (而后延时,确保脉冲宽度;清零,为下一次上升沿的到来做准备)

  • STCP(12)(RCLK)→ 1 // 输出移位寄存器数据
    (而后延时清零,确保脉冲宽度;为下一次上升沿的到来做准备)

二、相关例程

1、取字模软件的使用

起始界面:
单片机学习(4)——点阵LED
点击新建图像,选择合适的尺寸
单片机学习(4)——点阵LED点击,模拟动画,放大格点
单片机学习(4)——点阵LED
点出自己需要的数字(汉字),取模方式选择C51,下方即为对应的段选的真值。
单片机学习(4)——点阵LED

2、点亮数字0

/*************************************************************										  *
实现现象:下载程序后点阵上显示数字0		
注意事项:一定要将JOE短接片短接到GND端,如果不需要595后面的小灯点亮可以拔掉JP595短接片。																				  
***************************************************************************************/

#include<reg51.h>
#include<intrins.h>

typedef unsigned int u16;
typedef unsigned char u8;

sbit DS = P3^4;      //数据输入(0或1)
sbit RCLK = P3^5;    //并行输出开关
sbit SRCLK = P3^6;   //串行输入开关

u8 ledduan[]={0x00,0x00,0x3e,0x41,0x41,0x41,0x3e,0x00}; //高电平LED亮,值不固定
u8 ledwei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,
            0xfd,0xfe};//0x01111111,0x10111111,...低电平LED灯可能亮,固定序列值

void Hc595SendByte(u8 dat);
void delay(u16 i);

void main()
{
    u8 i = 0;
    while(1)
    {
        P0 = 0x7f;
        for(i=0;i<8;i++)
        {
            P0 = ledwei[i];             //选中某一列
            Hc595SendByte(ledduan[i]);  //通过HC595发送序列i对应的段选的真值
            delay(100);                 //延时,确保肉眼可以观察到
            Hc595SendByte(0x00);        //消隐
        }
     }
}

void Hc595SendByte(u8 dat)
{
    u8 a=0;
    RCLK = 0;          //输出寄存器状态保持
    SRCLK = 0;         //移位寄存器状态保持
    for(a = 0;a<8;a++) //循环8次,存进8位进制二进制数字
    {
        DS = dat>>7;   //串行输入最高位数据化
        dat = dat<<1;  //次高位移向最高位
        SRCLK = 1;     //移位寄存器存储
        _nop_();       //延时,保证脉冲宽度足够
		_nop_();
        SRCLK = 0;     //移位寄存器状态保持,为下一次上升沿到来做准备
    }
    RCLK = 1;          //输入移位寄存器数据
    _nop_();           //延时,保证脉冲宽度足够
    _nop_();
    RCLK = 0;          //输出寄存器状态保持,为下一次上升沿到来做准备
}

void delay(u16 i)
{
	while(i--);	
}

3、点阵的图形显示(循环)

//循环显示0123456789SNOW
#include<reg51.h>
#include<intrins.h>

typedef unsigned int u16;
typedef unsigned char u8;

sbit DS = P3^4;      //数据输入(0或1)
sbit RCLK = P3^5;    //并行输出开关
sbit SRCLK = P3^6;   //串行输入开关

unsigned char code ledwei[8]  = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //列选通控制
unsigned char code ledduan[14][8]=                                         //点阵字码
{

{0x00,0x00,0x3e,0x41,0x41,0x41,0x3e,0x00}, //0

{0x00,0x00,0x00,0x00,0x21,0x7f,0x01,0x00}, //1

{0x00,0x00,0x27,0x45,0x45,0x45,0x39,0x00}, //2

{0x00,0x00,0x22,0x49,0x49,0x49,0x36,0x00}, //3

{0x00,0x00,0x0c,0x14,0x24,0x7f,0x04,0x00}, //4

{0x00,0x00,0x72,0x51,0x51,0x51,0x4e,0x00}, //5

{0x00,0x00,0x3e,0x49,0x49,0x49,0x26,0x00}, //6

{0x00,0x00,0x40,0x40,0x40,0x4f,0x70,0x00}, //7

{0x00,0x00,0x36,0x49,0x49,0x49,0x36,0x00}, //8

{0x00,0x00,0x32,0x49,0x49,0x49,0x3e,0x00}, //9

{0x00,0x00,0x24,0x52,0x4A,0x24,0x00,0x00}, //S

{0x00,0x00,0x7E,0x20,0x18,0x04,0x7E,0x00}, //N 

{0x00,0x00,0x3e,0x41,0x41,0x41,0x3e,0x00}, //O

{0x00,0x70,0x08,0x14,0x60,0x14,0x08,0x70}, //W

};
void delay(u16 time);
void Hc595SendByte(u8 dat);

void main()
{	
 	u8 tab, j = 0;
	u16 i;

	while(1)
	{	
		for(i= 0; i<50; i++ )                        //两个字之间的扫描间隔时间
		{
			for(tab=0;tab<8;tab++)                   //每一个字符对应8列
			{	
				Hc595SendByte(0x00);			     //消隐																
			    P0 = ledwei[tab];				     //位选,选通某一列
				Hc595SendByte(ledduan[j][tab]);	     //通过HC595发送序列i对应的段选的真值
				delay(2);		
			}		 
		}
		j++;
		if(j == 14)
		{
			j = 0;
		}
	}	
}

void delay(u16 time)
{
  u16 i,j;
  for(i=0;i<time;i++)
    for(j=0;j<121;j++);
}

void Hc595SendByte(u8 dat)
{
    u8 a=0;
    RCLK = 0;          //输出寄存器状态保持
    SRCLK = 0;         //移位寄存器状态保持
    for(a = 0;a<8;a++) //循环8次,存进8位进制二进制数字
    {
        DS = dat>>7;   //串行输入最高位数据化
        dat = dat<<1;  //次高位移向最高位
        SRCLK = 1;     //移位寄存器存储
        _nop_();       //延时,保证脉冲宽度足够
		_nop_();
        SRCLK = 0;     //移位寄存器状态保持,为下一次上升沿到来做准备
    }
    RCLK = 1;          //输入移位寄存器数据
    _nop_();           //延时,保证脉冲宽度足够
    _nop_();
    RCLK = 0;          //输出寄存器状态保持,为下一次上升沿到来做准备
}

4、点阵的汉字显示
由于选用的是8*8的LED点阵,所以只能显示较为简单的汉字

//代码功能:循环显示大小回中

#include<reg51.h>
#include<intrins.h>

typedef unsigned int u16;
typedef unsigned char u8;

sbit DS = P3^4;      //数据输入(0或1)
sbit RCLK = P3^5;    //并行输出开关
sbit SRCLK = P3^6;   //串行输入开关

unsigned char code ledwei[8]  = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //列选通控制
unsigned char code ledduan[4][8]=                                         //点阵字码
{

0x00,0x12,0x14,0x78,0x14,0x12,0x00,0x00,   //大
0x00,0x08,0x12,0x01,0xFF,0x00,0x10,0x08,   //小
0x7F,0x41,0x5D,0x55,0x5D,0x41,0x7F,0x00,   //回
{0x7C,0x48,0x48,0xFF,0x48,0x48,0x7C,0x00}  //中

};
void delay(u16 time);
void Hc595SendByte(u8 dat);

void main()
{	
 	u8 tab, j = 0;
	u16 i;

	while(1)
	{	
		for(i= 0; i<50; i++ )                        //两个字之间的扫描间隔时间
		{
			for(tab=0;tab<8;tab++)                   //每一个字符对应8列
			{	
				Hc595SendByte(0x00);			     //消隐																
			    P0 = ledwei[tab];				     //位选,选通某一列
				Hc595SendByte(ledduan[j][tab]);	     //通过HC595发送序列i对应的段选的真值
				delay(2);		
			}		 
		}
		j++;
		if(j == 4)
		{
			j = 0;
		}
	}	
}

void delay(u16 time)
{
  u16 i,j;
  for(i=0;i<time;i++)
    for(j=0;j<121;j++);
}

void Hc595SendByte(u8 dat)
{
    u8 a=0;
    RCLK = 0;          //输出寄存器状态保持
    SRCLK = 0;         //移位寄存器状态保持
    for(a = 0;a<8;a++) //循环8次,存进8位进制二进制数字
    {
        DS = dat>>7;   //串行输入最高位数据化
        dat = dat<<1;  //次高位移向最高位
        SRCLK = 1;     //移位寄存器存储
        _nop_();       //延时,保证脉冲宽度足够
		_nop_();
        SRCLK = 0;     //移位寄存器状态保持,为下一次上升沿到来做准备
    }
    RCLK = 1;          //输入移位寄存器数据
    _nop_();           //延时,保证脉冲宽度足够
    _nop_();
    RCLK = 0;          //输出寄存器状态保持,为下一次上升沿到来做准备
}