单片机开发实验:LED点阵显示数字

实验目标

了解LED点阵的基本原理和实现方法,并掌握用CPU控制扫描的方式实现点阵LED显示器的字符显示‌。通过实验掌握LED点阵的基本结构和扫描显示程序的设计方法,熟悉LED点阵的构造和工作原理,以及如何设计扫描显示程序来控制点阵的显示。
在完成基本数字显示实验后,可以进一步拓展实验内容,如尝试显示更复杂的字符或图形、实现动态滚动显示等。这有助于加深对LED点阵显示技术的理解和应用能力。

LED点阵介绍

LED点阵,简而言之,是由众多LED(发光二极管)小灯依据特定规律排列而成的显示模块。这些小灯犹如微小光点,故称为点阵。
每个LED灯均配备正极与负极两引脚。当施加适当电压于这两极,LED灯即会发光。通过精准控制每个LED灯的亮灭状态,可以在点阵上灵活展现各类文字、数字或图形。
在日常生活中,LED点阵应用广泛,从手机屏幕上的时间显示到室内外广告牌,再到交通信号灯,都应用到了LED点阵。如下所示:

8*8点阵因其结构简洁而得到广泛应用。通过组合多个8*8点阵,可以构建出不同分辨率的LED点阵显示屏。例如,一个16*16点阵显示屏便是由4个8*8点阵拼接而成。因此掌握了8*8 LED点阵的工作原理,对于其他分辨率的LED点阵显示屏,其基本原理也是相通的。8*8其外观和内部结构图如下所示:

从8*8点阵结构上可以看出,点阵 LED 点亮原理还是很简单的。在图中大方框外侧的就是点阵 LED 的引脚号,左侧的 8 个引脚是接的内部 LED 的阳极,上侧的 8 个引脚接的是内部LED 的阴极。那么如果我们把 9 脚置成高电平、13 脚置成低电平的话,左上角的那个 LED小灯就会亮了。

硬件设计

本实验使用的硬件资源如下:
(1)8*8 LED点阵模块
(2)74HC595模块

LED点阵芯片

开发板上的8*8 LED点阵模块电路如下图所示:

从图中可以明显看出,电路中的RE57至RE64构成了LED点阵的第1至8列,这些列通过P0 IO口进行控制。而RE8至RE64则代表了LED点阵的第1至8行,它们通过74HC595芯片进行控制。
DPa至DPh作为LED点阵的8行控制管脚,经由动态数码管模块中的74HC245驱动,这些行的连接端均为LED的阴极。

8*8的LED点阵包含64个LED单元,若仅依赖单片机IO口直接驱动,效果可能不尽人意。为了高效驱动此点阵并最大限度地减少IO口占用,采用了74HC595模块。

74HC595芯片介绍

74HC595芯片通过串行方式接收数据,并在内部进行移位操作,最终将8位数据并行输出。芯片引脚如下图所示:

Q1-Q7‌:8位并行数据输出引脚,用于连接显示设备(如数码管、点阵屏)的相应段。
GND‌:接地引脚。
‌Q7'‌:串行数据输出引脚,用于级联下一个74HC595芯片。
‌MR‌:主复位引脚(低电平有效),用于复位芯片至初始状态。
‌SH_CP(SCK)‌:数据输入时钟引脚,控制串行数据的移位操作。
‌ST_CP(LCK)‌:输出存储器锁存时钟引脚,控制数据的锁存操作。
‌/OE‌:输出有效引脚(低电平有效),控制并行输出的使能状态。
‌DS‌:串行数据输入引脚,用于接收串行输入的数据。
‌VCC‌:电源引脚,提供芯片工作所需的电压。
下图形象展示了74HC595芯片引脚接线方式:

第14引脚为芯片的串行数据输入引脚。第1至7引脚,外加第15引脚构成了芯片的8个并行输出引脚,第9脚为1路串行数据输出引脚。第13引脚为芯片的低电平使能引脚。第10为低电平复位引脚。第11,12引脚分别为移位寄存器、存储寄存器的时钟输入引脚,我们用单片机的两只引脚控制第11、12引脚来产生数据移位、存储的时钟节拍。第8、16引脚为电源引脚

74HC245芯片介绍

74HC245具有两组8位输入输出端口,分别称为A端和B端。通过控制引脚(如DIR和OE),可以实现数据从A端到B端的传输,或者从B端到A端的传输。芯片引脚如下图所示:

A1-A8(输入输出端口A)‌:双向传输数据端口,根据DIR引脚的状态,这些引脚可以作为数据输入或输出端口。
B1-B8(输入输出端口B)‌:双向传输数据端口,同样根据DIR引脚的状态,这些引脚作为数据输入或输出端口的对应部分。
‌GND(地线)‌:接地使用,为芯片提供基准电压。
VCC(电源正极)‌:电源接口,为芯片提供工作电压,通常为+5V或+3.3V。
DIR(方向控制输入端)‌:决定数据传输的方向。当DIR引脚接高电平时,数据从A端(A1-A8引脚)输入,B端(B1-B8引脚)输出;当DIR引脚接低电平时,数据从B端输入,A端输出。
‌OE(输出使能输入端)‌:控制输出端口是否有效。当OE引脚接低电平时,输出端口处于使能状态,可以正常输出数据;当OE引脚接高电平时,输出端口处于失能状态,呈现高阻态,不会输出数据。

在工业控制系统中,74HC245可用于信号放大、隔离和驱动控制等场合。

 

电路原理图


从图中可以看出,74HC595芯片的11、12、14引脚分别接单片机的P36、P35、P34引脚,14引脚为芯片的串行数据输入引脚,第11,12引脚分别为移位寄存器、存储寄存器的时钟输入引脚,用单片机的两只引脚控制第11、12引脚来产生数据移位。第1至7引脚,外加第15引脚构成了芯片的8个并行输出引脚,链接到LED点阵芯片的DPa至DPh引脚,作为LED点阵的8行控制管脚,经由动态数码管模块中的74HC245驱动控制点亮。

软件设计

从原理图可见,LED灯以行列形式排列,每行每列均连接多个LED。单独点亮一个LED依据原理不难,但同步点亮多个LED则需要好好思考一下。
首要问题是如何激活一行或一列上的多个LED灯。显然,需确保特定行或列有效,同时可能还需其他行或列也处于激活状态。以第一行为例,当该行有效时,与其相交的有效列上的LED灯将被点亮。单独点亮一行或一列相对简单,但如何让不同行不同列上的LED灯同时亮起?
具体做法是:依次点亮每一行LED灯,每行点亮一段时间后熄灭,再点亮下一行,如此循环,直至所有行均被点亮一次。此过程中,从第一行到最后一行的总点亮时间需控制在人眼无法察觉的范围内,即不超过24毫秒。同时,在每行点亮期间,为列提供新的数据,以指定该行上哪些LED灯应被点亮。这一过程类似于数码管的动态显示,但LED点阵显示的是数字,通过同时点亮多个LED灯来实现。
要想在LED点阵上显示数字等字符,还需要获取这些字符在LED点阵上显示的数字或字符数据。每个数字或字符在点阵上呈现时,会对应到特定的行列组合,其中某些LED灯会点亮,而其余的则熄灭,从而构成该数字或字符的图案。这些点亮与熄灭的状态组合起来,就形成了一组数据,我们称之为该数字或字符的显示数据。

有了数字或字符数据,接下来就可以利用74HC595这类移位寄存器芯片,将这些数据逐一发送到点阵对应的行或列上。通过精确控制每行每列LED灯的亮灭状态,我们就能够在点阵上清晰地显示出所需的数字或字符。

如何提取数字或字符数据呢?单片机开发板厂商在提供的开发工具中,已经包含了取字模软件,若没有提供,可以通过互联网下载。取字模软件允许你绘制数字和字符图像,并形成C51或A51格式的字符数据。

应用取字模软件,生成数字0的数据,然后复制所生成的数据到我们程序内
定义的数组中,如下所示:
u8 ledduan[]={0x00,0x00,0x3E,0x41,0x41,0x41,0x3E,0x00};

编写程序

启动Keil软件后,创建一个新项目,选择单片机型号STC89C52RC。在项目中添加C语言源文件main.c。
在main.c文件内输入下面的源代码:

#include "reg51.h" // 引入51单片机寄存器定义的头文件
#include<intrins.h> // 引入内建函数库,例如_nop_(),用于生成一个NOP(无操作)指令

// 定义数据类型别名
typedef unsigned int u16;
typedef unsigned char u8;

// 定义连接到74HC595的控制引脚
sbit SRCLK=P3^6; // 串行时钟引脚,连接到P3.6
sbit RCLK=P3^5; // 寄存器时钟引脚,连接到P3.5
sbit SER=P3^4; // 串行数据引脚,连接到P3.4

// 定义LED显示器段码和位选码数组
u8 ledduan[]={0x00,0x00,0x3e,0x41,0x41,0x41,0x3e,0x00}; // 8个LED段码,这里只定义了前7个(0-6),最后一个为0(不显示)
u8 ledwei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; // 8个位选码,用于选择哪一个LED显示

// 延时函数,通过空循环实现,i=1时大约延时10us(具体时间取决于单片机时钟频率)
void delay(u16 i)
{
while(i--);
}

// 向74HC595发送一个字节的数据
void Hc595SendByte(u8 dat)
{
u8 a;
SRCLK=0; // 初始化串行时钟为低
RCLK=0; // 初始化寄存器时钟为低
for(a=0;a<8;a++) // 循环8次,每次发送一位数据
{
SER=dat>>7; // 将数据的最高位(MSB)送到SER引脚
dat<<=1; // 数据左移一位,为发送下一位做准备

SRCLK=1; // 产生一个SRCLK上升沿,将SER上的数据锁存到74HC595的移位寄存器中
_nop_(); // 插入NOP指令,确保时序正确
_nop_();
SRCLK=0; // SRCLK下降沿
}

RCLK=1; // 产生一个RCLK上升沿,将移位寄存器中的数据并行输出到LED显示器
_nop_();
_nop_();
RCLK=0; // RCLK下降沿
}

// 主函数
void main()
{
u8 i;
while(1) // 无限循环
{
P0=0x7f; // 假设这里用于其他目的,例如控制其他设备或引脚,但在此代码中并未直接使用
for(i=0;i<8;i++) // 循环8次,依次点亮LED显示器的每一位
{
P0=ledwei[i]; // 设置位选码,选择哪一个LED显示
Hc595SendByte(ledduan[i]); // 发送对应的段码到LED显示器
delay(100); // 延时,使LED显示稳定
Hc595SendByte(0x00); // 发送0x00到LED显示器,进行消隐(但在这个循环中实际上没有作用,因为随后会立即被新的数据覆盖)
}
}
}

3.7.6.实验现象
使用 USB 线将开发板和电脑连接成功后,把编写好的程序编译后将编译产生的.hex 文件烧入到芯片内,开发板会自动运行下载的程序,LED点阵模块显示数字0。