今天学习一个非常常用的功能。外面的流动字母的LED大屏大家应该很常见吧。今天!学完这个,你就可以自己设计一个LED大屏了!
一、开发板原理图
首先我们看点阵屏幕的输入信号,有P0_X和DP_X控制。P0_X直接就是芯片的P0输出端口,那么我们现在关注一下DP_X的产生。
从这里不难看出,通过P3_4,5,6可以产生DP_X端口。
那具体的怎么怎么产生呢,我们一位一位将数据在SRCLK的上升沿时,放进SER线路中,当RCLK到达上升沿时,将数据并行一次性输出给DP_X。
所以简而言之 ,只需要P0和P3的3个端口,就可以点亮电子屏。
所以我们可以根据这一特性写出,输出的函数
#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;
}
二、显示静态图像
我们实现了基础操作以后,我们现在来看如何点亮屏幕,这里采用的是列扫描的方式。利用P0端口直接给第一列置0,剩余列置1。随后使用P3_4,5,6串行转并行输入行的数字。
/**
* @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;
}
最后我们可以看到,除了逻辑之外,我们还添加了Delay和P0端口置1的操作。这里就是为了消影。
那么,我们最后只需要在while中一行一行依次点亮就好了,因为单片机的处理速度足够快,所以可以在视觉上产生全部图形的效果。
#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 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;
}
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);
}
}
有一个点,不知道大家有没有疑惑,这里我在第一次学习的时候没搞懂
SER=Byte&(0x80>>i);
SER不是一位寄存器吗?为什么可以存8位?其实是因为如果对一个一位寄存器存多位数据,非0即1。
三、显示动态图像
有了前面的知识这里也就简单很多了。
#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;
}
}
}
}
我们只需要提前把数据放在一个数组里,每一轮显示8个。然后下一轮显示9-16个。然后再显示17-24个。我们发现每一轮加8,当大于2*8以后,我们重新显示第一张图片。
这里我们用了count++,这里是为了延时,使得我们能看清每一张图片,不至于太快了看不清。
注意:我们这里以8为单位跳转,所以每次都是一幅图片一幅图片的跳转。如果我们以1为单位,那么我们的动画就会流动起来,变成弹幕的样子。可以去试试了。