LED点阵是一种由发光二极管排列而成的显示器件,在生活里的各种电器中很常见,像汽车报站器和广告屏等地方都会用到它。
平时用得比较多的是 8×8 点阵。多个 8×8 点阵能组合成不同大小的 LED 点阵显示屏,比如 4 个 8×8 点阵可以拼成一个 16×16 点阵。只要懂了 8×8LED 点阵是怎么工作的,其他大小的 LED 点阵显示屏原理也就差不多了。下面就来讲讲 8×8LED 点阵。
8 x 8点阵里一共有64个发光二极管,这些二极管都放在行线和列线交叉的地方。要让某个二极管亮起来,,只要让对应的哪一行接上1电平(也就是高电平,相当于有电),那一列接上0电平(也就是低电平,相当于没有电)就行。
举个例子,要是想点亮第一个点,把 1 脚接上高电平,a 脚接上低电平,这个点就会亮了。
要是想点亮第一行,那就把第 1 脚接上高电平,然后把(a、b、c、d、e、f、g、h )这些引脚都接上低电平,这样第一行的所有点就都亮起来了。
要是想点亮第一列,把第 a 脚接上低电平,再把(1、2、3、4、5、6、7、8)这些引脚都接上高电平,第一列的点就都亮了。
所以说,LED 点阵用起来其实并不难,只要控制好行和列的电平高低,就能让它按我们的想法显示出不同的图案或者文字。
1.8x8LED和74HC595
8*8LED 点阵模块由 8 行 8 列共 64 个发光二极管组成,这些二极管整齐排列在点阵之上,通过控制行与列的电平,就能实现不同二极管的亮灭,进而呈现出各种图案或文字。
而 74HC595 模块则是一种移位寄存器芯片,它在本实验中起着至关重要的作用,主要用于协助控制 LED 点阵的行数据。
在电路连接方面,74HC595 模块有三个关键的控制管脚,分别为 SER(串行数据输入引脚)、RCLK(存储寄存器时钟输入引脚)以及 SRCLK(移位寄存器时钟输入引脚)。这三个管脚被直接连接至 51 单片机的 P3.4 - P3.6 IO 口。当单片机向这些管脚发送不同的电信号时,就能依据 74HC595 芯片的通信时序,精准地控制数据的传输。
74HC595 模块的输出端,与 8*8LED 点阵模块的行端口相连,由于该连接,LED 点阵模块行端口就等同于 LED 发光二极管的阳极。而 LED 点阵模块的列端口,自然就对应着发光二极管的阴极。
在实际控制过程中,要实现对 LED 点阵的有效操控,我们需要严格依照 74HC595 芯片既定的通信时序,通过 51 单片机的相应管脚来传输数据。具体来说,当单片机按照 74HC595 芯片的通信要求,向其控制管脚发送数据时,74HC595 芯片会将接收到的串行数据,转换为并行数据输出至 LED 点阵的行端口,从而控制 LED 点阵的行数据。
再依据 LED 发光二极管的导通原理,当阳极施加高电平,阴极施加低电平时,对应的二极管就会点亮;反之,若阳极电平低于阴极电平,二极管则熄灭。
所以,在本实验设计里,我们利用单片机的 P0 口来控制 LED 点阵的列,通过改变 P0 口各管脚的电平高低,就能控制 LED 点阵列端口的电平状态;同时,借助 74HC595 模块来控制点阵的行,以此实现对整个 8*8LED 点阵的全面控制,让其按照我们的预期显示出各类信息。
2.显示笑脸
#include <REGX52.H>
#include "Delay.h"
sbit RCK=P3^5; //RCLK
sbit SCK=P3^6; //SRCLK
sbit SER=P3^4; //SER
#define MATRIX_LED_PORT P0
// 向 74HC595 写入一个字节的数据
void _74HC595_WriteByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
// 从高位到低位依次取出字节的每一位
SER=(Byte & (0x80 >> i))? 1 : 0;
// 上升沿将数据移入移位寄存器
SCK=1;
SCK=0;
}
// 上升沿将移位寄存器的数据锁存到存储寄存器
RCK=1;
RCK=0;
}
// LED显示屏显示一列数据
void MatrixLED_ShowColumn(unsigned char Column, unsigned char Data)
{
// 向 74HC595 写入数据 0~0xFF 高位在上,1为亮,0为灭
_74HC595_WriteByte(Data);
// 选择要显示的列 0~7
MATRIX_LED_PORT=~(0x80 >> Column);
Delay(1);
MATRIX_LED_PORT=0xFF;
}
void main()
{
// 初始化时钟信号
SCK=0;
RCK=0;
while(1)
{
MatrixLED_ShowColumn(0, 0x3C);
MatrixLED_ShowColumn(1, 0x42);
MatrixLED_ShowColumn(2, 0xA9);
MatrixLED_ShowColumn(3, 0x85);
MatrixLED_ShowColumn(4, 0x85);
MatrixLED_ShowColumn(5, 0xA9);
MatrixLED_ShowColumn(6, 0x42);
MatrixLED_ShowColumn(7, 0x3C);
}
}
3.显示爱心
#include <REG51.H>
sbit RCK=P3^5; //RCLK
sbit SCK=P3^6; //SRCLK
sbit SER=P3^4; //SER
#define MATRIX_LED_PORT P0
//向74HC595写入一个字节的数据
void _74HC595_WriteByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
//从高位到低位依次取出字节的每一位
SER=(Byte&(0x80>>i))? 1:0;
//上升沿将数据移入移位寄存器
SCK=1;
SCK=0;
}
//上升沿将移位寄存器数据锁存到存储寄存器
RCK=1;
RCK=0;
}
void MatrixLED_ShowColumn(unsigned char Column,unsigned char Data)
{
//向74HC595写入数据,0~0xFF 高位在上,1为亮,0为灭
_74HC595_WriteByte(Data);
//选择要显示的列 0~7
MATRIX_LED_PORT=~(0x80>>Column);
}
unsigned char picture[] = {0x30,0x78,0x7C,0x3E,0x3E,0x7C,0x78,0x30};
void main()
{
//初始化时钟信号
SCK=0;
RCK=0;
while(1)
{
unsigned char i;
for(i=0;i<8;i++)
{
MatrixLED_ShowColumn(i,picture[i]);
}
}
}
4.单片鸡点阵屏之坤坤跳舞
main.c
#include <REGX52.H>
#include "MatrixLED.h"
unsigned char code action[]=
{
0x00,0x03,0x24,0x58,0xA4,0x02,0x01,0x00,
0x00,0x01,0x02,0x14,0x2C,0x56,0x01,0x00,
0x00,0x01,0x02,0x04,0x14,0x2E,0x51,0x00,
0x00,0x01,0x02,0x14,0x2C,0x56,0x01,0x00,
0x00,0x03,0x24,0x58,0xA4,0x02,0x01,0x00
};
void main()
{
unsigned char i,offset=0,Count=0;
MatrixLED_Init();
while(1)
{
for(i = 0;i<8;i++)
{
MatrixLED_ShowColumn(i,action[i+offset]);}
Count++;
if(Count>40)
{
Count=0;
offset+=8;
if(offset>24)
offset = 0;
}
}
}
MaatrixLED.c
#include <REGX52.H>
#include "Delay.h"
sbit RCK = P3^5;
sbit SCK = P3^6;
sbit SER = P3^4;
#define MATRIX_LED_PORT P0
/**
* @brief 74HC595写入一个字节
* @param 要写入的字节
* @retval 无
*/
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;
}
/**
* @brief LED点阵屏显示一列数据
* @param Column选择的列,范围:0~7,0在最左边
* @param Data选择列显示的数据,高位在上,1为亮,0为灭
* @retval 无
*/
void MatrixLED_ShowColumn(unsigned char Column,Data)
{
_74HC595_WriteByte(Data);
MATRIX_LED_PORT = ~(0x80>>Column);
}
void MatrixLED_Init()
{
SCK = 0;
RCK = 0;
}
在 51 单片机编程里,code
是一个存储类型修饰符,使用 code
来修饰 action
数组,主要基于以下几个原因:
1. 节省内部 RAM 空间
- 51 单片机内存结构特点:51 单片机的内存资源相对有限,它的内部 RAM 空间较小(通常为 128 字节或 256 字节),并且要用于存储变量、栈空间等。
- 数据存储位置:使用
code
修饰的数组会被存放在程序存储器(ROM)里,而非内部 RAM。像你代码中的action
数组存有大量的显示数据,若不使用code
修饰,这些数据就会占用内部 RAM 空间,这样可能导致内部 RAM 不够用,进而影响其他变量的存储和程序的正常运行。
2. 程序存储器读取稳定
- ROM 特性:程序存储器(ROM)是只读存储器,其数据在程序运行期间不会被修改,数据的存储和读取十分稳定。
- 适合存储固定数据:
action
数组中的数据代表着特定的显示图案序列,属于固定不变的数据。把这些数据存放在程序存储器中,既能保证数据的稳定性,又能避免因意外修改数据而引发的显示错误。