前言
本篇文章属于STC89C52单片机(以下简称单片机)的学习笔记,来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记,只能做参考,细节方面建议观看视频,肯定受益匪浅。
一、 LED点阵屏介绍
二、显示原理
三、开发板引脚对应关系
四、74HC595(串转并)
QA-QH是输出端
OE(output enable):输出使能,OE上面加一横线,代表这个芯片低电平有效,即OE接0才工作
SRCLR(serial clear):串行清零端,左边接VCC,代表它不清空
P35-->RCLK(register clock):寄存器时钟,上升沿锁存
P36-->SRCLK(serial clock):串行时钟,上升沿移位
P34-->SER:串行数据
示例:假如给QA-QH 0000 0101的数据
SERCLK和RCLK初始化为0,SER写一个1,然后SERCLK给一个高电平,然后就会有一个上升沿,1就进到寄存器中,SERCLK配置回0,SER再写一个0,然后SERCLK给一个高电平,1就往下移,0就进到寄存器中,如此进行八次后,移位寄存器中的数据就是0000 0101的形式了(串行输入),然后将RCLK配置为1,移位寄存器中内容就会同时进入输出缓存中,然后给到输出端(并行输出)。
RCLK初始化为0就是起到一个锁住数据的作用,给1之后这个锁才被打开,进入到输出缓存
补充:数据分为串行和并行,串行即在时钟的激励下,数据一个一个出去的;并行即同时发送多个数据,这里即同时发送八个数据给八个输出端
QH'还可以接到下一个74HC595的SER上形成多片级联,所有74HC595的时钟是一样的
区别前面讲到的38译码器,38译码器只能选择出其中一位进行输出,其它七位输出的都是同样的数据,而74HC595就可以是八个输出端输出不同的数据,真正实现IO口的扩展
五、补充知识
六、实例一(LED点阵屏显示图形)
代码演示:
#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()
{
RCK=0;
SCK=0;
while(1)
{
//爱心
MatrixLED_ShowColumn(0,0x38);
MatrixLED_ShowColumn(1,0x44);
MatrixLED_ShowColumn(2,0x82);
MatrixLED_ShowColumn(3,0x41);
MatrixLED_ShowColumn(4,0x41);
MatrixLED_ShowColumn(5,0x82);
MatrixLED_ShowColumn(6,0x44);
MatrixLED_ShowColumn(7,0x38);
}
}
七、实例二(LED点阵屏显示动画)
代码演示:
#include <REGX52.H>
#include "Delay.h"
#include "MatrixLED.h"
unsigned char Animation[]={
0X00,0X00,0X00,0X00,0X00,0x00,0x00,0x00,
0x21,0x3f,0x21, //I
0x00,0x18,0x24,0x22,0x11,0x22,0x24,0x18,//爱心
0x00,0x3f,0x01,0x01,0x3f, //U
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++)
{
MatrixLED_ShowColumn(i,Animation[i+Offset]);
}
Count++;
if(Count>40)
{
Count=0;
Offset++;
if(Offset>24)
{
Offset=0;
}
}
}
}
流动动画版
#include <REGX52.H>
#include "Delay.h"
#include "MatrixLED.h"
unsigned char 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++)
{
MatrixLED_ShowColumn(i,Animation[i+Offset]);
}
Count++;
if(Count>40)
{
Count=0;
Offset+=8;
if(Offset>16)
{
Offset=0;
}
}
}
}
帧动画版
流动动画和帧动画的区别就是偏移量一次改变的大小,流动动画偏移量一次改变1,帧动画一次改变8
由于直接这样定义数组是将其中内容放在RAM也就是运存中,会很占运存,而且动画素材是不变的,所以可以加个code关键字,放入flash中,flash的空间也更大,能够存储更多的动画素材
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,
};