单片机学习(4)——点阵LED
一、基础知识
1、LED点阵原理
一个数码管是由8段LED灯组成的,同理,一个88的点阵是由64个LED点阵组成的。88LED点阵外观图如1-1:
内部结构图如下图1-2:
若想点亮LED点阵,就要使得D端为高电平,P端为低电平。以普中科技的开发板为例,相关原理图如1-3所示,对应图1-2左侧的内部结构图。
2、74HC595芯片
(1)原理介绍
74HC595是一个8位串行输入、并行输出的位移缓存器。引脚图如下图:
其中主要用的引脚有:
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、取字模软件的使用
起始界面:
点击新建图像,选择合适的尺寸
点击,模拟动画,放大格点
点出自己需要的数字(汉字),取模方式选择C51,下方即为对应的段选的真值。
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; //输出寄存器状态保持,为下一次上升沿到来做准备
}
下一篇: CJSON源码研究笔记