LED显示的原理就是利用扫描把把要显示内容在点阵上扫描过去(说得有点简单啊)。大的显示屏需要扫描更多的行数和一次点亮更多的LED,所以一般需要借助一些数字芯片来扫描,如74154 4-16译码器和74154移位寄存器。
74154带有使能端,可以利用这个来消除移位过程中产生的鬼影。在使用74154的时候有个细节需要注意 一下,有些人会直接对管脚进行++操作,这在有些时候是可以的,但是遇到像我上次LED流水灯实验就会发生错误了(详见《做LED流水灯时犯的一个小错误》)。
LED点阵显示可以分为静态的和动态的,先发一下静态的代码。
#include "stc12c5a.h"
#include "delay.h"
#include "config.h"
#include "chinese.h"//取模方式为行列式取模,从左上到左下,再从右下到右下
#define A P2 //选择行,仅低四位有效
#define DATA P1 //数据发送口,本程序仅低四位有效
#define HZ 32 //定义一个汉字字模的字节数
sbit EN_n = P3^3;//使能端
sbit CLK = P3^4; //时钟信号
void Send_4Byte(uchar *Byte)//发送四个相距16个字节的数据
{
uchar i = 0,j = 0;
uchar temp = 0;
for(i=0;i<8;i++)
{
temp = 0;
for(j=0;j<4;j++)
{
if((*(Byte+16*j))&(1<<i)) temp |= 1<<j;//获得相距16个字节4个数据的第i位数据
}
CLK = 0;
DATA = temp;//发送数据
CLK = 1;//上升沿发送一位数据
}
}
void main()
{
uchar i = 0;
uchar *start;
uchar move = 0;
/***初始化*****/
A = 0;
EN_n = 1;
start = *chinese;
/**************/
while(1)
{
for(i=0;i<16;i++)
{
EN_n = 1;//关闭显示
A = 15 - i;//选择行(自上向下扫描)
Send_4Byte(start+i);
EN_n = 0;//打开显示
delay_ms(1);
}
}
}
动态显示即实现内容的移动。我采用的是将原数据左移,再从后面数据取前N位补在低位。当显示完一个点阵的宽度(即半个字)后,起始点直接跳到下个点阵。看代码。
#include "stc12c5a.h"
#include "delay.h"
#include "config.h"
#include "chinese.h"//取模方式为行列式取模,从左上到左下,再从右下到右下
#define SPEED 8
#define A P2 //选择行,仅低四位有效
#define DATA P1 //数据发送口,本程序仅低四位有效
#define HZ 32 //定义一个汉字字模的字节数
sbit EN_n = P3^3;//使能端
sbit CLK = P3^4; //时钟信号
void Send_4Byte(uchar *Byte,uchar move)//发送四个相距16个字节的数据,move为位移量,原先变量左移move位,后move位补上后16字节的前move位
{
uchar i = 0,j = 0;
uchar temp = 0;
for(i=0;i<8;i++)
{
temp = 0;
if(i>=move)
{
//发送原数据低位数据
for(j=0;j<4;j++)
{
if((*(Byte+16*j))&(1<<i-move)) temp |= 1<<j;
}
}
else
{
//发送后续数据的高位
for(j=0;j<4;j++)
{
if((*(Byte+16+16*j))&(1<<(i+8-move))) temp |= 1<<j;
}
}
CLK = 0;
DATA = temp;
CLK = 1; //上升沿
}
}
void main()
{
uchar i = 0;
uchar *start;
uint count = 0;//计数变量
uchar move = 0;//位移控制变量
unsigned long length= sizeof(chinese);
/***初始化*****/
A = 0;
EN_n = 1;
start = *chinese;//设置起点
/**************/
while(1)
{
/*****速度控制******/
count++;
if(!(count%SPEED))
{
move = ++move%8;
if(count>=8*SPEED)
{
start += 16;
if(start-*chinese==length-2*HZ) start = chinese;
count =0;
}
}
/******************/
for(i=0;i<16;i++)
{
EN_n = 1;//关闭显示
A = 15 - i;//选择行(自上向下扫描)
Send_4Byte(start+i,move);
EN_n = 0;//打开显示
delay_ms(1);
}
}
}