51 单片机外设进阶:LED 点阵屏

LED 点阵屏基础

  • 结构特点:LED 点阵屏的内部结构类似于数码管,本质上是像素点按矩阵排列。数码管可看作像素按“8”字型排列的特殊点阵。

  • 接法分类:与数码管一致,分为共阴共阳两种接法。不同的接法决定了驱动电路的电平逻辑。

  • 显示原理:LED 点阵屏通常采用逐行或逐列扫描(动态刷新)的方式,利用人眼视觉暂留效应实现多点同时显示的视觉效果。

点阵屏主要分类

  • 按颜色:单色、双色(通过组合可显示三种颜色)、全彩屏。

  • 按像素密度:常见的有 8×8、16×16 等规格。

74HC595 移位寄存器

  • 功能概述:74HC595 是一款 8 位串行输入、并行输出的移位寄存器。它仅需 3 根控制线即可扩展出 8 根并行输出线。通过级联多片芯片,可以轻松扩展出 16 位、24 位乃至更多 IO 口。

形象理解
可以将 74HC595 比作一把手枪:

  • SER:填入子弹(数据输入)。
  • SERCLK:控制子弹装填移位(移位寄存器时钟)。
  • QH’:多余子弹溢出位(用于级联下一片芯片)。
  • RCLK:锁存并清空弹夹(存储寄存器时钟,将数据输出到引脚)。

开发要点
要注意 J24 模块的 GND 端连接,并使用文字取模软件生成显示代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/* LED 点阵屏动画显示示例 - main.c */
#include <REGX52.H>
#include "Delay.h"
#include "MatrixLED.h"

// 动画取模数组。使用 code 关键字将数据强制存储在 Flash 中以节省 RAM
unsigned char code Animation[]= {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0xFE,0x90,0x98,0x64,0x02,0x00,0x02,
0x0C,0x30,0xD0,0x30,0x0C,0x02,0x00,0xFE,
0x80,0x70,0x1C,0x02,0xFE,0x00,0xFE,0x82,
0x82,0x44,0x38,0x00,0x7C,0x82,0x82,0x82,
0x7C,0x00,0xFE,0x02,0x02,0x02,0x00,0xFE,
0x90,0x90,0x80,0x00,0xFE,0x02,0x02,0x02,
0x00,0xFC,0x02,0x02,0x02,0xFC,0x00,0x7C,
0x82,0x82,0x82,0x7C,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};

void main() {
unsigned char i = 0, Offset = 0, Count = 0;
MatrixLED_Init(); // 初始化点阵屏

while(1) {
// 逐列扫描显示当前偏移量下的 8 列数据
for (i = 0; i < 8; i++) {
MatrixLED_ShowColumn(i, Animation[i + Offset]);
}

Count++;
// 注意:此处不使用标准 Delay 延时,否则会导致扫描闪烁
if(Count > 10) {
Count = 0;
Offset++; // 移动动画窗口
if(Offset > 72) // 边界检查防止数组越界
Offset = 0;
}
}
}

* MatrixLED.c *\

include

include “Delay.h”

sbit RCK = P3^5 ; //RCLK,取P3第5位
sbit SCK = P3^6; //SRCLK,取P3第6位
sbit SER = P3^4 ; //SER,取P3第4位

define MATRIX_LED_PORT P0 //LED显示寄存器

void _74HC595_WriteByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++) { SER=Byte&(0x80>>i); //从高位向低位写入
SCK=1; //上升延移位
SCK=0; //软件复位
}
RCK=1; //锁存
RCK=0; //软件复位
}

void MatrixLED_ShowColumn(unsigned char Column,Data)
{
_74HC595_WriteByte(Data); // 写入并锁存
MATRIX_LED_PORT=~(0x80>>Column); // 选择列写入
Delay(1);
MATRIX_LED_PORT=0xFF;
}

void MatrixLED_Init() //初始化
{
SCK=0;
RCK=0;
}
* MatrixLED.c *\

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

### DS1302实时时钟



- DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能
- RTC(Real Time Clock):实时时钟,是一种集成电路,通常称为时钟芯片

{% asset_img a2cb160acfbdce294850df0d26a610e6.png image-20240227185909359 %}

{% asset_img e01b7c2afd37876c99d9eb5fcff72b06.png image-20240227192928469 %}

- DS1302 涓流充电计时芯片包含一个实时时钟/日历和 31 字节的静态 RAM.通过简单的串行通信。

- 与时钟/RAM 通讯只需要三根线: CE, I/O (数据线), and SCLK (串行时钟). 数据输出输入时钟/RAM 一次1字节或者在脉冲串中多达 31 字节.





{% asset_img 907ed3748ce357076eab12d9cfa0e691.png image-20240227195752523 %}





{% asset_img 0cbb26fcce6ac5329df503b5e58981db.png image-20240227200002026 %}

- I/O口电平由命令字和数据组成
- CE:操作使能
- 根据第一位判断是写入还是读出
- SCLK:上升沿,I/O口电平被写入。下降沿,DS1302输出数据。
- 读比写少一个周期
- 输出为`BCD码`,每相邻数字只有一位不同
- DEC=BCD/16*10+BCD%16; (2位BCD)*
- *BCD=DEC/10*16+DEC%10; (2位BCD)



从这开始就不写全部代码了(懒的敲yes!),主要写写思路:

通过定义一个数组来存储时间,修改时间也是通过修改时间数组来实现。通过`Timeshow()`来更新时间数组,通过`TimeSet()`来设置时间。通过`DS1302_SetTime()`将时间数组的更新写入时钟。

```c
//通过按键设置mode值,然后就调用对应函数
while(1)
{
KeyNum=Key();//读取键码
if(KeyNum==1)//按键1按下
{
if(MODE==0){MODE=1;TimeSetSelect=0;}//功能切换
else if(MODE==1){MODE=0;DS1302_SetTime();}
}
switch(MODE)//根据不同的功能执行不同的函数
{
case 0:TimeShow();break;
case 1:TimeSet();break;
}
}
}

//每次TimeSetFlashFlag为1就熄灭,TimeSetFlashFlag每隔固定时间取反。
if(TimeSetSelect==0 && TimeSetFlashFlag==1){LCD_ShowString(1,1," ");}
else {LCD_ShowNum(1,1,DS1302_Time[0],2);}

蜂鸣器