51单片机16*16LED点阵图像显示学习总结
51单片机16*16LED点阵显示图像学习总结
51单片机16*16LED点阵显示图像—笑脸
利用STC89C51的单片机开发板16*16点阵模块(独立)+开发资料、电路图+4个74HC595芯片+取模软件+c语言编程实现笑脸显示。
一、 学习思路—基于STC89C51单片机(A7)
1. 电路图详情 ;
- STC89C51(A7)版本的单片机各模块独立,还需要用的是4片74HC595芯片。
-
74HC595芯片特点是8位串行输入/输出或者并行输出移位寄存器,具有高阻关断状态。
三态:8位串行输入、 8位串行或并行输出、 存储状态寄存器。
移位寄存器和存储器是分别的时钟。
-
74HC595有三态,SER(数据输入)、SRCLK(移位寄存器时钟)和RCLK(锁存器时钟),且SER/SRCLK和RCLK均需要连接到51I/O引脚上,这里将SER连接到 P0-3,SRCLK连接到P0-5和RCLK连接到P0-4引脚。
-
74HC595(A)、74HC595(B)、74HC595©、74HC595(D)四个芯片由QH非相互连接
SER负责数据输入,第一个数据通过SER输入,通过SRCLK移位到QA,第二个数据通过SER输入,通过SRCLK移位时,原来第一个SER输入的数据QA被移位到QB,第二个数据就进入到QA中以此类推。 直至74HC595(A)中 QA-QH的8位被填满。这是第一个8位对应74HC595(A),当有第二组8位数据传入的时候,第一组8位中的74HC595(A)也会被移位到74HC595(B)中,并且依次类推。 这样74HC595A/B/C/D四个芯片依次被依次传入8位数据。 -
具体为:通过SER口输入串行的数据,当SRCLK有上升沿信号时,数据就往下移一位,当数据满了8位时,给RCLK上升沿信号时,8位数据就锁存到QA~QH,QH’连接到下一片74HC595,继续拓展16位、32位…,这里只是3线拓展到8线,QH’就不用接了。这样单片机通过3个I/O口连接74HC595,输出4*8=32位数据
2. 独立模块的接线和验证;
STC89C51(A7)版本各模块独立,所以使用时需要接线使用。根据电路图显示 U6/U7分别连接J27和J32,这里需要强调一下,电路图中的现实不一定正确,所以需要验证连接是否正确!需要注意!!!本实验J10连接J34、J27连接J28,现实是正极。QA–QH为低到高位
C/D芯片显示为NEG,所以为阴极。
74HC595程序:
void _HC595_DATA(u8 dat1, u8 dat2, u8 dat3, u8 dat4)
{
u8 i = 0;
RCLK = 0;
SRCLK = 0;
for(i=0; i<8; i++)
{
SER = dat4 >> 7;
dat4 <<= 1;
SRCLK = 0;
SRCLK = 1;
}
for(i=0; i<8; i++)
{
SER = dat3 >> 7;
dat3 <<= 1;
SRCLK = 0;
SRCLK = 1;
}
for(i=0; i<8; i++)
{
SER = dat2 >> 7;
dat2 <<= 1;
SRCLK = 0;
SRCLK = 1;
}
for(i=0; i<8; i++)
{
SER = dat1 >> 7;
dat1 <<= 1;
SRCLK = 0;
SRCLK = 1;
}
RCLK = 0;
Dately_10us(10);
RCLK = 1;
}
3. 取模软件进行取模(横向取模)
取模软件取模方法:取模方向——横向取模,字节倒序,取模方式——C51格式,取出的字模样式如图:
数组我们用U8别名变量保存下来:(横向取模两两对应— —)
后续使用的时候需要取反
u8 _hc595_xiaolian_L[32] = {
0x00,0x00,0x00,0x00,0x10,0x04,0x28,0x0A,
0x44,0x11,0x00,0x00,0x80,0x00,0x80,0x00,
0x00,0x00,0x00,0x00,0x04,0x20,0x08,0x10,
0xF0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00};
行的数组也用U8数组标示出来:
u8 _hc595_xiaolian_H[32] = {
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
取模这里需要注意的是:
-
横向取模,横向取模对应的是纵向排列图像,即实际描述的是按照74HC595的 C/D 的数据。 纵向取模的话则要把输入的文字横向排列成图像,即实际描述的是按照74HC595的 A/B 的数据。但是取模完后的数据在后续使用的时候需要取反
-
“取模倒序”,本课题参考的开发板采用的是下高位,上低位的顺序,所以需要采用字模倒序的。
4. 程序编译与调试 ;
1.首先开头代码格式写出来:
#include "reg51.h"
void main(void)
{
}
- 同时定义一个别名变量,管脚定义以及一个延时函数(用于SRCLK和RCLK上沿时移动、存储数据用),还要定义一个函数用于调用数组,程序如下:
#include "reg51.h"
typedef unsigned char u8;
sbit SER = P0^3;
sbit RCLK = P0^4;
sbit SRCLK = P0^5;
void Dately_10us(u8 t)
{
while(t--);
}
u8 _hc595_xiaolian_L[32] = {
0x00,0x00,0x00,0x00,0x10,0x04,0x28,0x0A,
0x44,0x11,0x00,0x00,0x80,0x00,0x80,0x00,
0x00,0x00,0x00,0x00,0x04,0x20,0x08,0x10,
0xF0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00};
u8 _hc595_xiaolian_H[32] = {
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
u8 dat1, dat2, dat3, dat4;
void _HC595_DATA(u8 dat1, u8 dat2, u8 dat3, u8 dat4)
{
u8 i = 0;
RCLK = 0;
SRCLK = 0;
for(i=0; i<8; i++)
{
SER = dat4 >> 7;
dat4 <<= 1;
SRCLK = 0;
SRCLK = 1;
}
for(i=0; i<8; i++)
{
SER = dat3 >> 7;
dat3 <<= 1;
SRCLK = 0;
SRCLK = 1;
}
for(i=0; i<8; i++)
{
SER = dat2 >> 7;
dat2 <<= 1;
SRCLK = 0;
SRCLK = 1;
}
for(i=0; i<8; i++)
{
SER = dat1 >> 7;
dat1 <<= 1;
SRCLK = 0;
SRCLK = 1;
}
RCLK = 0;
Dately_10us(10);
RCLK = 1;
}
void Display(u8 shuzu_H[32], u8 shuzu_L[32])
{
u8 i = 0;
while(1)
{
for(i=0; i<16; i++)
{
_HC595_DATA(shuzu_H[i], shuzu_H[i+16], ~shuzu_L[2*i], ~shuzu_L[2*i+1]);
}
}
}
- 最后调用这个函数:
void main(void)
{
Display(_hc595_xiaolian_H, _hc595_xiaolian_L);
}
- Keil编译器编译:
“dztuxiang” – 0 Error(s), 0 Warning(s).
5. 效果展示;
6. 程序保存 ;
// 笑脸显示程序
#include "reg51.h"
typedef unsigned char u8;
sbit SER = P0^3;
sbit RCLK = P0^4;
sbit SRCLK = P0^5;
void Dately_10us(u8 t)
{
while(t--);
}
u8 _hc595_xiaolian_L[32] = {
0x00,0x00,0x00,0x00,0x10,0x04,0x28,0x0A,
0x44,0x11,0x00,0x00,0x80,0x00,0x80,0x00,
0x00,0x00,0x00,0x00,0x04,0x20,0x08,0x10,
0xF0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00};
u8 _hc595_xiaolian_H[32] = {
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
u8 dat1, dat2, dat3, dat4;
void _HC595_DATA(u8 dat1, u8 dat2, u8 dat3, u8 dat4)
{
u8 i = 0;
RCLK = 0;
SRCLK = 0;
for(i=0; i<8; i++)
{
SER = dat4 >> 7;
dat4 <<= 1;
SRCLK = 0;
SRCLK = 1;
}
for(i=0; i<8; i++)
{
SER = dat3 >> 7;
dat3 <<= 1;
SRCLK = 0;
SRCLK = 1;
}
for(i=0; i<8; i++)
{
SER = dat2 >> 7;
dat2 <<= 1;
SRCLK = 0;
SRCLK = 1;
}
for(i=0; i<8; i++)
{
SER = dat1 >> 7;
dat1 <<= 1;
SRCLK = 0;
SRCLK = 1;
}
RCLK = 0;
Dately_10us(10);
RCLK = 1;
}
void Display(u8 shuzu_H[32], u8 shuzu_L[32])
{
u8 i = 0;
while(1)
{
for(i=0; i<16; i++)
{
_HC595_DATA(shuzu_H[i], shuzu_H[i+16], ~shuzu_L[2*i], ~shuzu_L[2*i+1]); //4、3数组取反,数组对应为0-1, 2-3, 3-4....这样
}
}
}
void main(void)
{
Display(_hc595_xiaolian_H, _hc595_xiaolian_L);
}