????????要实现行列不同位置亮灯,需要使用动态显示的方法,也要结合扫描的方法。
????????在第一行亮灯一段时间以后灭掉,点亮第二行一段时间以后灭掉,点亮第三行一段时间以后灭掉,如此点亮,直到八行全部点亮一次。在第一行点亮到最后一行灭掉的总时间不能超过人肉眼可识别的时间,即 24 毫秒。
????????在每一行点亮的时候,给列一个新的数据,此时对应列而在该行上要点亮的灯的数据。这样就想数码管的动态显示一样,只不过数码管的 LED 灯是段值。这里使用 LED 点阵显示数字,也是多个 LED 同时点亮。
????????已知点阵的列由P0口控制,只需要令P0=0111 1111,1011 1111,……便可依次让对应的列为0,便可选中该列的LED。
????????行则由74HC595控制,下面说明如何通过使用取字模软件来获取数据。
????????新建图像,选择8x8的面积,如下:
????????参数设置如下:
????????鼠标点白色格子,选中要显示的格子。点击“C51格式”,点阵生成区便可得到对应的数据。
? ? ? ? 把数据复制进代码里面,如下。
#include"reg52.h"
#include"intrins.h"
typedef unsigned int u16;
typedef unsigned char u8;
u8 led_row[]={0x28,0x48,0xA8,0x28,0xFF,0x28,0x28,0x28};//该行数据为取字模软件得到,输入给74HC595
u8 led_line[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//列数据为0111 1111,1011 1111,1101 1111……把数据赋值给P0口,便可选中某一列,动态扫描显示
sbit SRCLK=P3^6; //移位寄存器时钟输入
sbit _RCLK=P3^5; //储存寄存器时钟输入,因为reg52头文件定义了RCLK因此只能换一个名字_RCLK
sbit SER=P3^4; //串行输入
void delay(u16 s); //延时函数
void transform(u8 num); //把数值用74HC595转化出来,因为led点阵的阳极通过74HC595连接
void LED1(u8 num_line); //把数据传递给P0口
void main()
{
int i=0;
while(1)
{
for(i=0;i<8;i++) //动态扫描显示,
{
transform(led_row[i]);//行数据 ,先选中哪几行显示
LED1(led_line[i]); //列数据 ,选中哪一列显示
delay(100); //延时
}
}
}
void delay(u16 s)
{
while(s--);
}
void transform(u8 num)
{
u8 a;
SRCLK=1;
RCLK=1;
//移位寄存器工作
for(a=0;a<8;a++) //本循环块功能为:把num的位从高到低依次传输到QH到QA
{
SER=num>>7; //8位二进制数右移7位,即把最高位的数放在最低位,其余地方补零,从而实现把最高位取出来,例如1001 0010》0000 0001
num=num<<1; //把num左移一位,把次高位的值换到最高位,最低位补0,从而更换最高位的值,为下一次SER取值做准备
SRCLK=0; //令电瓶为0
_nop_(); //延时1us
_nop_();
SRCLK=1; //令电瓶为1,实现跳转,产生上升沿,把SER的值读进储存寄存器
}
//储存寄存器工作
_RCLK=0;
_nop_();
_nop_();
_RCLK=1; //产生上升沿,把值送到QA到QH
}
void LED1(u8 num_line)
{
P0=num_line; //把数据传给P0口
}
? ? ? ? 结果如下:
|