说明
本人使用的是清翔的51单片机开发板,如果型号相同最方便,但是如果型号不同也可以参考,因为芯片都是一样的,只是外设不同而已,使用时只需要对照自己的开发板原理图稍微修改下引脚即可。
本次笔记对应清翔视频教程的第23,24,25 8x8点阵屏(理论+实践)
目录
一、LED点阵屏简介
1.1 组成
LED点阵屏(LED Matrix Display)是一种显示设备,由许多LED(Light Emitting Diode,发光二极管)组成的矩阵排列而成。每个LED都可以独立控制,通过控制不同LED的亮灭状态以及亮度,可以显示出各种图案、文字和动画。LED安装方便,一大块屏幕可以由很多小块拼接而成,便捷低成本,方便运输。
1.2 优点
LED点阵屏广泛应用于数字时钟、计数器、信息显示、广告牌、游戏机等领域。它们有很高的亮度、对比度和可见性,因此在各种环境下都能清晰显示内容。此外,LED点阵屏具有低功耗、长寿命、反应速度快等优点。
1.3 分类
根据LED点阵屏的特性,常见的LED点阵屏可以分为以下几种类型:
-
单色点阵屏:由单色LED组成,通常是红色或绿色。可以显示简单的图案和文字。
-
双色点阵屏:由两种颜色的LED(通常是红色和绿色)组成,可以显示更丰富的图案和文字,并支持一些简单的动画效果。
-
全彩点阵屏:由多种颜色的LED组成,可以显示出丰富的颜色,支持更复杂的图案、文字和动画。
为了控制LED点阵屏的显示,通常需要使用微控制器或其他驱动芯片。这些芯片提供了控制LED点阵屏的接口和功能,可以通过编程来实现所需的显示效果。
1.4 实际图片
1.5 共阳极点阵屏原理图
点亮指定位置的LED就可以显示出想要的图案,比如给⑨1,给⑬0,其余的行都为0,其余的列都为1,那么左上角的就会点亮。
如果要显示不同位置的点,需要动态扫描。同一时刻只有1个点被点亮
二、点阵屏芯片74HC595
芯片:2片74HC595级联,只需要3个IO口就可以驱动,节省IO口
2.1 芯片工作原理
以下内容均来自清翔给的文档
串行输入,并行输出
8 位串行输入/输出或者并行输出移位寄存器,具有高阻关断状态。三态。
特点
8 位串行输入
8 位串行或并行输出
存储状态寄存器,三种状态
输出寄存器可以直接清除
100MHz 的移位频率
输出能力
并行输出,总线驱动
串行输出;标准
中等规模集成电路74595 的控制端说明:
/SCLR(10 脚): 低点平时将移位寄存器的数据清零。通常我将它接 Vcc。
SCK(11 脚):上升沿时数据寄存器的数据移位。QA-->QB-->QC-->...-->QH;下
降沿移位寄存器数据不变。(脉冲宽度:5V 时,大于几十纳秒就行了。)
RCK(12 脚):上升沿时移位寄存器的数据进入数据存储寄存器,下降沿时存储寄
存器数据不变。通常我将 RCK 置为低点平,当移位结束后,在 RCK 端产生一
个正脉冲(5V 时,大于几十纳秒就行了。我通常都选微秒级),更新显示数据。
/G(13 脚): 高电平时禁止输出(高阻态)。如果单片机的引脚不紧张,用一个引
脚控制它,可以方便地产生闪烁和熄灭效果。比通过数据端移位控制要省时省力。
注:74164 和 74595 功能相仿,都是 8 位串行输入转并行输出移位寄存器。74164
的驱动电流(25mA)比 74595(35mA)的要小,14 脚封装,体积也小一些。
74595 的主要优点是具有数据存储寄存器,在移位的过程中,输出端的数据可以
保持不变。这在串行速度慢的场合很有用处,数码管没有闪烁感。
与 164 只有数据清零端相比,595 还多有输出端时能/禁止控制端,可以使输出为
高阻态。程序说明:
每当 spi_shcp 上升沿到来时,spi_ds 引脚当前电平值在移位寄存器中左移
一位,在下一个上升沿到来时移位寄存器中的所有位都会向左移一位,
同时 Q7'也会串行输出移位寄存器中高位的值,
这样连续进行 8 次,就可以把数组中每一个数(8 位的数)送到移位寄存器;
然后当 spi_stcp 上升沿到来时,移位寄存器的值将会被锁存到锁存器里,
并从 Q1~7 引脚输出
清翔PPT截图,讲的很清晰
2.2 点阵原理图
2.2.1 点阵部分
2.2.2 开发板部分
可以看到
14脚数据输入(DI) 是接在单片机的P3^4
11输入时钟 (CLK) 接在单片机P3^5
12输出控制 (LE) 接在单片机P3^6
2.2.3 芯片总结
14脚串行输入
9脚级联输出端,接下一个74HC595的14脚(也就是下一个74HC595的数据输入脚)
11脚 输入时钟,在它的上升沿数据从14脚串行输入。
12脚 上升沿时数据从Q0~Q7并行输出
移位寄存器:假设要发送的数据是1011 0001,从高位往低位发,过程如表
发送顺序 | Q1 | Q2 | Q3 | Q4 | Q5 | Q6 | Q7 | Q8 |
1 | 1 | |||||||
0 | 0 | 1 | ||||||
1 | 1 | 0 | 1 | |||||
1 | 1 | 1 | 0 | 1 | ||||
0 | 0 | 1 | 1 | 0 | 1 | |||
0 | 0 | 0 | 1 | 1 | 0 | 1 | ||
0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | |
1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 1 |
注:上方动图来源于CSDN文章:51单片机 74hc595使用用法(利用proteus仿真)
第1个发送的数据最终会被放到Q7,最后发送的数据最终会被放到Q0。如果从高位往低位发,那么最终Q7~Q0的数据就与我们发送的数据相同,如果从最低位开始发送,那么最终Q7~Q0的数据与我们实际的字节顺序相反
上升沿:从低电平到高电平的变化
下降沿:从高电平到低电平的变化
注:在视频教程中对芯片的讲解中,最先发送的位被放在了Q0,最后发送的位被放在了Q7,根据我自己查的资料以及仿真,我发现最先发送的位其实是被放在了Q7,所以在上面的分析中我也是按照最先发送的位被放在Q7位基准的。
2.3 点阵在开发板的连接方式
对应插下就行
三、编程
3.1 创建工程
复制一份工程模板,修改名称为“8.点阵屏”,进入项目文件夹,打开工程文件
3.2 main.c
非全部代码,仅提供改变部分的代码,头问件等格式请自行补全
void main()
{
//先发送一个b1111 1110 1000 0000看一下点亮的是哪个点
//发送时要先发送高位,因为移位寄存器会自动把先接收到的数据放到高位上
//定义一个字符型变量
uchar i;
uchar temp;
LE = 0;
CLK = 0;
temp = 0xfe; //11111110
for (i = 0; i < 8; i++) //发送第一个字节(高8位)
{
DI = temp & 0x80;
CLK = 1;
CLK = 0;
temp <<= 1;
}
temp = 0x80; //1000 0000
for (i = 0; i < 8; i++) //发送第2个字节(低8位)
{
DI = temp & 0x80;
CLK = 1;
CLK = 0;
temp <<= 1;
}
LE = 1; //发送完毕,打开数据输出
LE = 0;
}
注意,我传输的数据是按照行从右往左,列从上往下的顺序,也可以按照别的顺序,只需要改变传输过程的传输方式就可以了,不要弄错位了
我的数据顺序
3.3 main.h代码
//非全部代码,仅提供改变部分代码
typedef unsigned char uchar;
typedef unsigned int uint;
sbit DI = P3^4;
sbit LE = P3^6;
sbit CLK = P3^5;
3.4 现象
3.5 封装函数
3.5.1 main.c
void SendDat(uchar dat)
{
uchar i;
LE = 0;
CLK = 0;
for (i = 0; i < 8; i++)
{
DI = dat & 0x80;
CLK = 1;
CLK = 0;
dat <<= 1;
}
}
这样只需要把要发送的数据写在参数里面就行了
3.5.2 main.h
在main.h里面写函数的声明
void SendDat(uchar dat);
3.5.3 main函数
在main.c里面写完函数本体,在main.h写完函数声明之后,可以开始改造main函数的内容了,现在在main函数内部调用刚才写的函数
void main()
{
SendDat(0xfe);
SendDat(0x80);
LE = 1; //发送完毕,打开数据输出
LE = 0;
}
下载编译,左上角的点被点亮,证明封装没问题。既然封装了,那么可以再进一步封装,直接一次发送两个字节,并且把打开数据输出也封装进去
3.6 再次封装
3.6.1 main.c
void main()
{
SendDat2(0xfe, 0x80);
while (1)
{
}
}
void SendDat2(uchar col, uchar row)
{
SendDat(col);
SendDat(row);
LE = 1; //发送完毕,打开数据输出
LE = 0;
}
封装后在main函数里面要加一个while循环,否则显示不正常,目前还不清楚是什么原因
3.6.2 main.h
void SendDat2(uchar col, uchar row);
只需要在main.h写一下函数声明
3.7 动态显示
3.7.1 原理
人眼视觉暂留效应,每次只点亮1行的某些点,如果快速刷新下一行的点,人眼就会认为这几行是一起在现实的,从而实现动态显示。
在先代码的时候,需要先通过软件取模,获得每行对应要显示的列的位置,再通过循环去刷新界面
3.7.2 取模
软件PCtoLCD2002
具体设定如下
- 点击设置图标
- 按照图片设置
设置完成点击确定,就可以在主界面输入框输入汉字了。
软件有2种模式,字符模式和图片模式,在上方工具栏“模式”里面可以选择
3.7.3 main.c
#include <intrins.h>
void main()
{
uchar i;
for (i = 0; i < 8; i++)
SendDat2(chara[i], _cror_(0x80,i));
}
3.7.4 main.h
main.h里面需要存放刚才取得的字模
uchar code chara[] = {
0xF7,0xC1,0xD5,0xC1,0xD5,0xC1,0x77,0x87,//电,0
0xFF,0xA3,0xDF,0x81,0xEF,0xEF,0xEF,0xF7//"子",1
};
3.7.5 现象
如何编译下载已不必多说,下载完成后可以看到如图现象
这样我们就可以通过取模软件来取模,然后把字模放在main.h的数组里面,通过main函数的调用,就可以显示想要的字符了。
3.7.6 两个字符循环显示
循环原理就是循环显示一个字符很多次,然后再循环另一个字符很多次,比如循环显示“电”,“子”
main.c代码
void main()
{
uchar i;
uint j;
for (j = 0; j < 1000; j++)
{
for (i = 0; i < 8; i++)
SendDat2(chara[i], _cror_(0x80,i));
}
for (j = 0; j < 1000; j++)
{
for (i = 0; i < 8; i++)
SendDat2(chara[8 + i], _cror_(0x80,i));
}
}
当然你也可以选择使用二维数组,或者其他的嵌套循环来显示这两个字,动图制作不便,就不放了
本次笔记对应清翔视频教程的第23,24,25 8x8点阵屏(理论+实践),到此结束,下一篇笔记将对应视频教程的26,27 中断系统和外部中断(理论+实践)