51单片机_LED点阵屏
PS: 普中开发板需要把数码管右边的跳线帽插到左两孔中,否则点阵屏不会点亮。
点阵显示是一种常见的显示技术,广泛应用于电子设备中,如LED显示屏、电子钟表、广告牌等。它由多个LED灯组成,通过控制每个LED的亮灭来显示字符、数字或图形。51单片机是一种常用的微控制器,能够通过编程控制点阵显示的内容和效果。
在本教程中,我们将学习如何使用51单片机控制8x8点阵显示模块,并逐步实现一个简单的字符显示程序。
一、点阵显示的基本原理
点阵显示模块通常由多个LED灯排列成矩阵形式,例如8x8点阵模块由8行8列共64个LED组成。每个LED可以通过控制其所在的行和列的电平来点亮或熄灭。
- LED点阵屏的结构类似于数码管,只不过是数码管把每一列的像素以"8"字型排列而已-
- LED点阵屏与数码管一样,有共阴和共阳两种接法,不同的接法对应的电路结构不同
- LED点阵屏需要进行逐行或逐列扫描,才能使所有LED同时显示

二、硬件电路组成

从上图中可以看出, 该电路是集成的, 电路中的 K1~K8 是 LED 点阵的第1-8 列, 通过 P0 口控制(低电平有效)。
DPh-DPa 是 LED 点阵的 8 行控制管脚, 通过动态数码管模块中的74HC245 进行驱动, 高电平有效。

15 和 1 到 7 脚 QA--QH: 并行数据输出
9 脚 QH 非: 串行数据输出
10 脚 SCLK 非(MR) : 低电平复位引脚
11 脚 SCK(SHCP) : 移位寄存器时钟输入
12 脚 RCK(STCP) : 存储寄存器时钟输入
13 脚 G 非(OE) : 输出有效
14 脚 SER(DS) : 串行数据输入
74HC595 芯片介绍
74HC595 是一个 8 位串行输入、并行输出的位移缓存器, 其中并行输出为三态输出(即高电平、低电平和高阻抗) 。它能将少量数据信号(如51单片机的几个IO口)高效地转换为控制大量LED(如点阵屏的行或列)所需的信号。芯片管脚及功能说明如下:




三、应用实践示例
1)显示图形
main.c
c
#include <REGX52.H> // 包含51单片机寄存器定义头文件,用于操作P0、P3等端口
#include "Delay.h" // 包含自定义延时函数头文件,用于控制显示时间
// 定义74HC595芯片的三个控制引脚与单片机P3口的连接
sbit RCK=P3^5; // RCLK (Register Clock,寄存器时钟/锁存时钟),上升沿时将移位寄存器的数据锁存到输出寄存器
sbit SCK=P3^6; // SRCLK (Shift Register Clock,移位寄存器时钟),上升沿时移位寄存器数据移动一位
sbit SER=P3^4; // SER (Serial Data Input,串行数据输入),逐位输入数据(1或0)
#define MATRIX_LED_PORT P0 // 定义LED点阵列选择控制端口为P0口,用于选择要点亮哪一列
void _74HC595_WriteByte(unsigned char Byte)
{
unsigned char i; // 循环计数器,用于控制8位数据的移位
for(i=0;i<8;i++) // 循环8次,依次处理字节的每一个位(从最高位MSB开始)
{
// 核心操作:逐位提取并发送
// 1. 数据提取:(0x80>>i) 生成从最高位到最低位的位掩码(0x80=1000 0000)
// 2. 位与操作:Byte & (0x80>>i) 检查Byte的特定位是1还是0
// 3. 赋值结果:将比较结果(0或非0)赋给SER引脚。非0即1,0就是0。
SER = Byte & (0x80>>i);
// 产生一个移位时钟上升沿,将SER引脚上的当前位数据"推入"74HC595的移位寄存器
SCK = 1; // 时钟线拉高
SCK = 0; // 时钟线拉低,完成一次上升沿触发
// 循环8次后,Byte的8个位就依次全部移入了移位寄存器
}
// 产生一个锁存时钟上升沿,将移位寄存器中已准备好的8位数据,一次性锁存到输出寄存器(Q0-Q7)
RCK = 1; // 锁存线拉高,此时输出引脚更新
RCK = 0; // 锁存线拉低,完成更新。输出将保持直到下次锁存。
// 此操作是"两段式"的关键:后台移位,瞬间更新,显示稳定无拖影。
}
void MatrixLED_ShowColumn(unsigned char Column, Data) // 参数:Column(0~7), Data(列数据)
{
// 第一步:通过74HC595设置该列8个LED的行状态(哪个亮哪个灭)
_74HC595_WriteByte(Data); // 将列数据Data写入595,其输出直接控制LED行(阳极或阴极,取决于硬件接法)
// 第二步:通过P0口选择要点亮的列
// 假设点阵屏为共阴接法,列选通为低电平有效。
// (0x80 >> Column): 0x80(1000 0000)右移Column位,将1移动到对应列的位置。
// ~(0x80 >> Column): 按位取反,将对应列位变为0(低电平),其余列为1(高电平),从而选通该列。
MATRIX_LED_PORT = ~(0x80 >> Column);
// 第三步:保持点亮一小段时间,形成视觉暂留
Delay(1); // 调用延时函数,大约维持1ms(具体时间取决于Delay.h的实现)
// 第四步:消影操作!关闭所有列选通(将P0口全部置高),在切换列前熄灭所有LED。
MATRIX_LED_PORT = 0xFF; // 0xFF(1111 1111)使所有列都为高电平(无效),点阵屏所有LED熄灭
// 这是动态扫描显示避免"鬼影"的关键一步。
}
void main()
{
// 初始化:将74HC595的时钟引脚置为低电平,确保初始状态稳定
SCK = 0;
RCK = 0;
// 主循环,动态刷新显示
while(1)
{
// 依次显示第0列到第7列的数据,每列数据是一个8位二进制数,对应8行LED的状态(1亮0灭)。
// 这些数据共同构成了一个笑脸图案。
// 由于循环执行速度极快,人眼看到的是完整的静态图案。
MatrixLED_ShowColumn(0, 0x3C); // 0x3C -> 0011 1100
MatrixLED_ShowColumn(1, 0x42); // 0x42 -> 0100 0010
MatrixLED_ShowColumn(2, 0xA9); // 0xA9 -> 1010 1001
MatrixLED_ShowColumn(3, 0x85); // 0x85 -> 1000 0101
MatrixLED_ShowColumn(4, 0x85); // 0x85 -> 1000 0101
MatrixLED_ShowColumn(5, 0xA9); // 0xA9 -> 1010 1001
MatrixLED_ShowColumn(6, 0x42); // 0x42 -> 0100 0010
MatrixLED_ShowColumn(7, 0x3C); // 0x3C -> 0011 1100
// 循环回到开头,不断重复,实现稳定显示。
}
}
//笔记:
// P0 控制的是点亮哪一列 (低电平有效)
//74CH595 控制的是每列哪个LED灯点亮(高电平有效)
//综上,通过不断的扫描,实现LCD点阵屏效果
Delay.c
c
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
Delay.h
c
#ifndef __DELAY_H__
#define __DELAY_H__
void Delay(unsigned int xms);
#endif
2)显示动画
main.c
c
#include <REGX52.H>
#include "Delay.h"
#include "MatrixLED.h"
//动画数据
unsigned char code Animation[]={
0x3C,0x42,0xA9,0x85,0x85,0xA9,0x42,0x3C,
0x3C,0x42,0xA1,0x85,0x85,0xA1,0x42,0x3C,
0x3C,0x42,0xA5,0x89,0x89,0xA5,0x42,0x3C,
};
void main()
{
unsigned char i,Offset=0,Count=0;
MatrixLED_Init();
while(1)
{
for(i=0;i<8;i++) //循环8次,显示8列数据
{
MatrixLED_ShowColumn(i,Animation[i+Offset]);
}
Count++; //计次延时
if(Count>15)
{
Count=0;
Offset+=8; //偏移+8,切换下一帧画面
if(Offset>16)
{
Offset=0;
}
}
}
}
Delay.c
c
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
Delay.h
c
#ifndef __DELAY_H__
#define __DELAY_H__
void Delay(unsigned int xms);
#endif
MatrixLED.c
c
#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
/**
* @brief 74HC595写入一个字节
* @param Byte 要写入的字节
* @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 点阵屏初始化
* @param 无
* @retval 无
*/
void MatrixLED_Init()
{
SCK=0;
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);
Delay(1);
MATRIX_LED_PORT=0xFF;
}
MatrixLED.h
c
#ifndef __MATRIX_LED_H__
#define __MATRIX_LED_H__
void MatrixLED_Init();
void MatrixLED_ShowColumn(unsigned char Column,Data);
#endif
3)显示滚动字幕

只需要修改main.c部分即可,其余代码同上。
c
#include <REGX52.H>
#include "Delay.h"
#include "MatrixLED.h"
//动画数据
unsigned char code Animation[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x3F,0x48,0x48,0x48,0x3F,0x00,0x7F,0x49,
0x49,0x49,0x36,0x00,0x1C,0x22,0x41,0x41,
0x41,0x00,0x7F,0x41,0x41,0x22,0x1C,0x00,
0x7F,0x49,0x49,0x49,0x49,0x00,0x7D,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
void main()
{
unsigned char i,Offset=0,Count=0;
MatrixLED_Init();
while(1)
{
for(i=0;i<8;i++) //循环8次,显示8列数据
{
MatrixLED_ShowColumn(i,Animation[i+Offset]);
}
Count++; //计次延时
if(Count>10)
{
Count=0;
Offset+=1; //偏移+1
if(Offset>40)
{
Offset=0;
}
}
}
}