参考教程:[9-1] LED点阵屏_哔哩哔哩_bilibili
1、LED点阵屏由若干个独立的LED组成,LED以矩阵的形式排列,以灯珠亮灭来显示文字、图片、视频等。LED点阵屏广泛应用于各种公共场合,如汽车报站器、广告屏以及公告牌等。
2、LED点阵屏分类:
(1)按颜色:单色、双色、全彩。
(2)按像素:8*8、16*16等。(大规模的LED点阵通常由很多个小点阵拼接而成)
3、显示原理:LED点阵屏的结构类似于数码管,只不过数码管是把每一列的像素以“8”字型排列而已;LED点阵屏与数码管一样,有共阴和共阳两种接法,不同的接法对应的电路结构不同;LED点阵屏需要进行逐行或逐列扫描,才能使所有LED同时显示。
4、开发板上的LED点阵是单色8*8点阵屏,逐行扫描和数列扫描两种方式都可以使用:
(1)逐行扫描:按照逐行扫描就相当于采用了共阳极接法,以扫描第一行为例,先将DPh置为高电平1(DPa~DPg全部置为低电平0),需要第一行的哪一个LED灯亮,那么其阴极对应的引脚则需要被置为低电平0,比如只需要第一行第一列的LED灯亮,那么DPh处于高电平1的同时,P07要处于低电平0,与此同时P00~P06全部处于高电平1,这样就只有第一行第一列的LED灯有正向电流流过,接着按照这个思路扫描第二行到第八行,根据之前提到的“视觉暂留”,LED点阵屏可以通过在短时间内逐行反复点亮LED灯达到显示图案的效果。
(2)逐列扫描:按照逐列扫描就相当于采用了共阴极接法,以扫描第一列为例,先将P07置为低电平0(P00~P06全部置为高电平1),需要第一列的哪一个LED灯亮,那么其阳极对应的引脚则需要被置为高电平1,比如只需要第一列第一行的LED灯亮,那么P07处于低电平0的同时,DPh要处于高电平1,与此同时DPa~DPg全部处于低电平0,这样就只有第一列第一行的LED灯有正向电流流过,接着按照这个思路扫描第列行到第八列,根据之前提到的“视觉暂留”,LED点阵屏可以通过在短时间内逐列反复点亮LED灯达到显示图案的效果。
5、74HC595是串行输入并行输出的移位寄存器,可用3根线输入串行数据,8根线输出并行数据,多片级联后,可输出16位、24位、32位等,常用于IO口扩展。
(1)SER负责将数据一位一位地送入移位寄存器的最低位(输出最高位的数据最先被送入),每有一位数据被送入,SRCLK(时钟,上升沿移位)就会使寄存器中的数据往高位移动一位(给新数据腾位置),当移位寄存器满后,RCLK(时钟,上升沿锁存)使寄存器中的8位同时往8个引脚输出。(注意8个引脚正好是DPa~DPh)
(2)OE处于低电平(接地)时U6才能有效工作,要注意开发板上的J24,看看OE是否与接地端GND相连。
6、LED点阵屏显示静态图像:
(1)OE处于低电平(接地)时U6才能有效工作,先将OE与GND连接。
(2)该例需要用到Delay()函数,这里不再赘述,然后编写main.c文件,进行编译。
#include <REGX52.H>
#include "Delay.h"
sbit RCK = P3^5; //操作RCK,就相当于操作P3_5这个引脚(原理图上的RCLK)
sbit SCK = P3^6; //操作SCK,就相当于操作P3_6这个引脚(原理图上的SRCLK)
sbit SER = P3^4; //操作SER,就相当于操作P3_4这个引脚(原理图上的SER)
/**
* @brief 74HC595写入的一个字节
* @param 要写入的字节
* @retval 无
*/
void _74HC595_WriteByte(unsigned char Byte)
{
unsigned char i = 0;
for(i = 0; i < 8; i++) //每输入8位数据进行一次输出
{
SER = Byte & (0x80 >> i); //从最高位开始一位一位地取出数据输入移位寄存器的最低位
//Byte & 0x80结果不为0,那么SER被置为1,否则被置为0
SCK = 1; //SCK初始值为0,现在置为1,RCLK会有一个上升沿,寄存器中的数据往高位移动一位
SCK = 0; //SCK置为0,为RCLK的下一个上升沿做准备
}
RCK = 1; //RCK初始值为0,现在置为1,SRCLK会有一个上升沿,寄存器中的8位数据同时输出
RCK = 0; //RCK置为0,为SRCLK的下一个上升沿做准备
}
/**
* @brief LED点阵屏显示一列数据
* @param Column:要选择的列,范围:0~7,0在最左边
Data:选择列显示的数据,高位在上,1为亮,0为灭
* @retval 无
*/
void MatrixLED_ShowColumn(unsigned char Column, Data)
{
_74HC595_WriteByte(Data); //同时选择行(相当于数码管段选)
P0 = ~(0x80 >> Column); //选择一列(相当于数码管位选)
Delay(1);
P0 = 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)将生成的.hex文件下载到开发板中,可以看到LED点阵屏显示一个笑脸图案。
7、LED点阵屏显示动态图像:
(1)OE处于低电平(接地)时U6才能有效工作,先将OE与GND连接。
(2)该例需要用到Delay()函数,这里不再赘述,然后添加如下所示的代码文件,进行编译。
①MAtrixLED.h文件:
#ifndef __MAtrixLED_H__
#define __MAtrixLED_H__
void _74HC595_WriteByte(unsigned char Byte);
void MatrixLED_ShowColumn(unsigned char Column, Data);
void MatrixLED_Init();
#endif
②MAtrixLED.c文件:
#include <REGX52.H>
#include "Delay.h"
sbit RCK = P3^5; //操作RCK,就相当于操作P3_5这个引脚(原理图上的RCLK)
sbit SCK = P3^6; //操作SCK,就相当于操作P3_6这个引脚(原理图上的SRCLK)
sbit SER = P3^4; //操作SER,就相当于操作P3_4这个引脚(原理图上的SER)
/**
* @brief 74HC595写入的一个字节
* @param 要写入的字节
* @retval 无
*/
void _74HC595_WriteByte(unsigned char Byte)
{
unsigned char i = 0;
for(i = 0; i < 8; i++) //每输入8位数据进行一次输出
{
SER = Byte & (0x80 >> i); //从Byte的最高位开始一位一位地取出数据输入移位寄存器的最低位
//Byte & 0x80结果不为0,那么SER被置为1,否则被置为0
SCK = 1; //SCK初始值为0,现在置为1,RCLK会有一个上升沿,寄存器中的数据往高位移动一位
SCK = 0; //SCK置为0,为RCLK的下一个上升沿做准备
}
RCK = 1; //RCK初始值为0,现在置为1,SRCLK会有一个上升沿,寄存器中的8位数据同时输出
RCK = 0; //RCK置为0,为SRCLK的下一个上升沿做准备
}
/**
* @brief LED点阵屏显示一列数据
* @param Column:要选择的列,范围:0~7,0在最左边
Data:选择列显示的数据,高位在上,1为亮,0为灭
* @retval 无
*/
void MatrixLED_ShowColumn(unsigned char Column, Data)
{
_74HC595_WriteByte(Data); //同时选择行(相当于数码管段选)
P0 = ~(0x80 >> Column); //选择一列(相当于数码管位选)
Delay(1);
P0 = 0xFF; //消影,防止扫描到下一列时误点亮和上一列亮灯同一行的灯
}
/**
* @brief 点阵屏初始化
* @param 无
* @retval 无
*/
void MatrixLED_Init()
{
SCK = 0;
RCK = 0;
}
③main.c文件:
#include <REGX52.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, //第三帧(哭脸)
}; //用code修饰变量,它会存储在flash中,节省RAM的空间,不过变量一旦创建就不能更改
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) //每一帧重复扫描15遍,这样就不会受“视觉暂留”影响
{
Count=0;
Offset+=8; //偏移+8,切换下一帧画面
if(Offset>16) //该动画一共三帧,三帧显示完后动画结束,从头开始
{
Offset=0;
}
}
}
}
(3)将生成的.hex文件下载到开发板中,可以看到LED点阵屏会重复显示三帧动画,依次是笑脸、无表情脸、哭脸。