51单片机——74HC595、LED点阵屏 - 详解
目录
1.74HC595
1.1 回顾
前面动态数码管实验中提到 74HC138 拓展单片机 IO ,回顾:
“2个四位一体的数码管位选线有8根,但单片机IO资源有限
通常使用一种IO扩展芯片,如 74HC138,74HC164,74HC595
只需要用很少的单片机IO口就可扩展出8个控制口,通过级联方式甚至可以拓展更多IO口”
本篇介绍另外一种 IO口 拓展方式——串转并,使用的芯片是 74HC595 芯片
1.2 概述
开发板板载一个 74HC595芯片,仅单片机3个IO口即可拓展8个IO口
如果需要还可以将2个74HC595级联拓展出16个IO,即可实现用少数 IO 口资源控制多个设备
74HC595是一个 8位 串行输入,并行输出的位移缓存器
并行输出为三态输出(高电平、低电平、高阻扛)
1.3 工作原理
下图左边均是芯片管脚图,但管脚命名不同,重在关注管脚功能即可


74HC595 具有一个八位移位寄存器、存储寄存器。移位寄存器和存储寄存器是单独的时钟。数据通过 14脚 上升沿输入,当 MR 为高电平、OE为低电平时,数据在 11脚 的上升沿(高电平)进入到 移位寄存器,再通过 12脚 的上升沿(高电平)移动到 存储寄存器,若需要级联,则通过 9脚 串行输出,14 脚 串行数据输入即可;否则直接通过 15和1-7脚 并行数据输出到外围设备即可;
1.4 硬件设计
下图,中间是 74HC595 芯片,右端为 LED 点阵
OE :LED 点阵的 “驱动总开关”。低电平允许芯片驱动点阵显示,高电平切断驱动以关闭显示或隔离信号
图中左侧标注为“J24”,典型的跳线接口。黄色跳线帽连接1、2脚,OE引脚被拉低(低电平状态),黄色跳线帽连接2、3引脚,OE引脚被拉高(高电平状态);若不插跳线帽,OE 引脚悬空,可能导致输出不稳定
从图中可以看到,74HC595 需要用到的控制管脚连接单片机的 P34-P36 IO口,输出端连接LED点阵模块的行端口上,即为 LED发光二极管的阳极,单片机 P0口 控制点阵列
此外,数据是一位一位的传输到八位的移位寄存器,且从数据最高位开始移入,移位寄存器满八位之后,再一次性传输到存储寄存器
如 1001 0001 ,先将最高位 1 存入移位寄存器,再将 0 存入移位寄存器,如此类推,一直到最低位 1 也存入移位寄存器,移位寄存器满了之后,将数据一次性传输到存储寄存器。且最高位 1 对应 Dph,即 点阵屏第一行,次高位 0 对应 Dpg,即点阵屏第二行,如此类推

1.5 实验设计
通过74HC595控制LED点阵以行滚动方式循环显示
//74HC595 控制 LED点阵逐行点亮
#include
#include
//简化类型名
typedef unsigned char u8;
typedef unsigned int u16;
//定义 74HC595 关键引脚
sbit SER = P3^4; //串行数据输入
sbit RCLK_595 = P3^5; //存储寄存器输入:头文件中已经预定义了 RCLK
sbit SRCLK = P3^6; //移位寄存器输入
//74HC595 串行输入数据
u8 hc595[] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
/*延时函数:74HC595 对时钟信号的上升/下降沿有最小时间要求
如果时钟翻转太快,芯片来不及采样数据,会导致输出错误。*/
void Delay10us(u16 ms) //@11.0592MHz
{
unsigned char data i;
while(ms--)
{
i = 2;
while (--i);
}
}
//串行数据输入—>并行数据输出
void hc595_write(u8 date)//date即要写入的字节数据
{
u8 i = 0;
for(i=0;i<8;i++)//1字节=8位,逐位传输8次
{
SER = date>>7;//先把最高位传输到SER引脚
date <<= 1; //下一位左移(去掉最高位,末位补0)到最高位
//产生移位时钟脉冲
SRCLK = 0; //时钟拉低
Delay10us(1);//稳定低电平(10us)
SRCLK = 1; //时钟拉高,上升沿触发,将 SER 数据传输到移位寄存器
Delay10us(1);//稳定高电平
}
//产生存储时钟脉冲,触发数据输出
RCLK_595 = 0; //时钟拉低
Delay10us(1); //稳定低电平(10us)
RCLK_595 = 1; //时钟拉高,上升沿触发,将移位寄存器数据传输到存储寄存器
Delay10us(1); ////稳定高电平
//之后,74HC595的 QA-QH 并行输出传入的8位数据,驱动LED点阵
}
void main()
{
u8 i = 0;
while(1)
{
//LED点阵阴极为低电平
P0 = 0x00;
for(i=0;i<8;i++)
{
hc595_write(0x00); //消影:“清空旧数据”,避免LED余晖和视觉暂留导致的重影
hc595_write(hc595[i]); //输入串行数据
Delay10us(20000);
//延时作用:保持当前 LED 的点亮状态,但解决不了“切换瞬间的新旧数据叠加”
}
}
}
2. LED点阵
2.1 概述
LED点阵 是由发光二极管排列组成的显示器件,被广泛应用于汽车报站器、广告屏等
2.2 软件设计
2.2.1 点亮一个灯
要求:点亮 LED点阵 第一行第一列的灯

//点亮LED点阵一个灯
#include
#include
//简化类型名
typedef unsigned char u8;
typedef unsigned int u16;
//定义 74HC595 关键引脚
sbit SER = P3^4; //串行数据输入
sbit RCLK_595 = P3^5; //存储寄存器输入:头文件中已经预定义了 RCLK
sbit SRCLK = P3^6; //移位寄存器输入
/*延时函数:74HC595 对时钟信号的上升/下降沿有最小时间要求
如果时钟翻转太快,芯片来不及采样数据,会导致输出错误。*/
void Delay10us(u16 ms) //@11.0592MHz
{
unsigned char data i;
while(ms--)
{
i = 2;
while (--i);
}
}
//串行数据输入—>并行数据输出
void hc595_write(u8 date)//date即要写入的字节数据
{
u8 i = 0;
for(i=0;i<8;i++)//1字节=8位,逐位传输8次
{
SER = date>>7;//先把最高位传输到SER引脚
date <<= 1; //下一位左移(去掉最高位,末位补0)到最高位
//产生移位时钟脉冲
SRCLK = 0; //时钟拉低
Delay10us(1);//稳定低电平(10us)
SRCLK = 1; //时钟拉高,上升沿触发,将 SER 数据传输到移位寄存器
Delay10us(1);//稳定高电平
}
//产生存储时钟脉冲,触发数据输出
RCLK_595 = 0; //时钟拉低
Delay10us(1); //稳定低电平(10us)
RCLK_595 = 1; //时钟拉高,上升沿触发,将移位寄存器数据传输到存储寄存器
Delay10us(1); ////稳定高电平
//之后,74HC595的 QA-QH 并行输出传入的8位数据,驱动LED点阵
}
void main()
{
while(1)
{
//LED点阵阴极为低电平
P0 = 0x7f;
//输入行数据
hc595_write(0x80);
}
}
2.2.2 显示一个数字
要求:显示一个数字 0
想要在 LED点阵 上显示一个数字,需要知道哪些灯是熄灭的,哪些灯是点亮的,也就是需要获取对应的显示数据,将数字字符对应的显示数据通过 74HC595 发送到点阵的行或列就能显示数字字符
取字模软件可以方便地获取显示数据




显示图像各行对应的数据:0x00,0x00,0x3C,0x42,0x42,0x3C,0x00,0x00
第一、二列:没有灯需要点亮 ,所以行对应数据:0x00,0x00
第三列;第 3.4.5.6 行需要点亮,所以行对应数据:0011 1100: 0x3C
如此类推

实验代码与前面点亮一个灯的核心代码是一样的,重点要理解动态扫描


动态扫描:首先设置最左边第一列(P0^7)有效,即低电平,其余列为高电平,然后通过74HC595输出该列对应的行数据,延时一段时间等待显示稳定,最后清除列对应的行数据,即消影
//LED点阵显示数字
#include
#include
//简化类型名
typedef unsigned char u8;
typedef unsigned int u16;
//定义 74HC595 关键引脚
sbit SER = P3^4; //串行数据输入
sbit RCLK_595 = P3^5; //存储寄存器输入:头文件中已经预定义了 RCLK
sbit SRCLK = P3^6; //移位寄存器输入
// 共阴点阵适配:字模用原数组(高电平有效)
u8 led_row[] = {0x00,0x00,0x3C,0x42,0x42,0x3C,0x00,0x00}; //LED点阵显示数字0的行数据
u8 led_col[] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //LED点阵显示数字0的列数据
/*延时函数:74HC595 对时钟信号的上升/下降沿有最小时间要求
如果时钟翻转太快,芯片来不及采样数据,会导致输出错误。*/
void Delay10us(u16 ms) //@11.0592MHz
{
unsigned char data i;
while(ms--)
{
i = 2;
while (--i);
}
}
//串行数据输入—>并行数据输出
void hc595_write(u8 date)//date即要写入的字节数据
{
u8 i = 0;
for(i=0;i<8;i++)//1字节=8位,逐位传输8次
{
SER = date>>7;//先把最高位传输到SER引脚
date <<= 1; //下一位左移(去掉最高位,末位补0)到最高位
//产生移位时钟脉冲
SRCLK = 0; //时钟拉低
Delay10us(1);//稳定低电平(10us)
SRCLK = 1; //时钟拉高,上升沿触发,将 SER 数据传输到移位寄存器
Delay10us(1);//稳定高电平
}
//产生存储时钟脉冲,触发数据输出
RCLK_595 = 0; //时钟拉低
Delay10us(1); //稳定低电平(10us)
RCLK_595 = 1; //时钟拉高,上升沿触发,将移位寄存器数据传输到存储寄存器
Delay10us(1); ////稳定高电平
//之后,74HC595的 QA-QH 并行输出传入的8位数据,驱动LED点阵
}
void main()
{
u8 i=0;
while(1)
{
for(i=0;i<8;i++)
{
P0 = led_col[i]; // 传送列数据
hc595_write(led_row[i]);// 传送行数据
Delay10us(40); // 延时一段时间,等待显示稳定
hc595_write(0x00); // 消影
}
}
}


浙公网安备 33010602011771号