图1
一、数码管与LED
由上面三个图可得知六个数码管与八个LED一起受到U3(74HC138)的控制。
当我们让六个数码管同时亮时,采取的是动态扫描,即1ms进入一次中断进行扫描IO口,又因为一个数码管是由八个LED组成,所以要想数码管和LED同时亮,先用一个数组来暂存LED0~LED7的地址(unsigned char code Led[] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}),再用一个来暂存数码管的显示数值地址,同时扩大数码管与LED的缓冲区成LEDBuf[7]。
动态扫描思路如下:
1、先定义一个静态变量i,用来改变扫描的索引。
2、定义变量之后紧接着写上P0=0xFF,此语句是为了消隐。
3、因为138受到P1.0~P1.2控制,也即受P1低3位控制,所以先使P1低3位清空,然后再改变P1低3位的状态。P1=(P1&0xF8)|i。
例:P1&0xF8 XXXXX000;假如此时i=2,也即010,现在(P1&0xF8)|i =xxxxx010,这样就改变了P1低三位的状态。0xF8=11111000
4、把缓冲区的数据送给P0,P0=LEDBuf[i],i的值递增到i=5即可。
5、这个函数(函数名随意)需要放到中断中,中断时间为1ms。
代码如下:
static unsigned char i = 0;
P0 = 0xFF;
P1 = (P1&0xF8)|i;
if(i==6)
LEDBuf[6]=Led[cnt];//cnt为全局变量,控制点亮哪个LED
P0=LEDBuf[i];
if(i<6)
i++;
else
i=0;
二、点阵
由上图可知点阵也连到了P0口,并且受到U4(74HC138)的控制,由图1可知U4又受到ADDR3的控制,当ADDR3=0时有效。点阵是1ms进入中断进行扫描
点阵显示图案也是P0口进行动态扫描,时间为1ms扫描一次,先定义一个数组暂存显示图案的地址(unsigned char code Lattice[]),图案地址从取模软件获取
动态扫描思路:
只需把数码管与LED的扫描思路第4点改成把Lattice数组的数据送给P0,P0=Lattice[i],i的值递增到i=7即可,其他思路一样。
代码如下:
static unsigned char i = 0;
P0 = 0xFF; //消隐
P1 = (P1&0xF8)|i;
P0=Lattice[i];
if(i<8)
i++;
else
i=0;
三、数码管、LED、点阵
三者都连到了P0口,若想一起点亮,把他们放到同一个函数内进行扫描。
扫描思路:
1、先定义静态变量i,用来改变扫描索引。
2、当i<8时进行点阵扫描,打开U4,ADDR3=0;
3、当i>7时进行LED和数码管的扫描,打开U3,ADDR3=1;
4、当i>15时,i=0。
代码如下:
Static unsigned char i = 0;
P0 = 0xFF;//消隐
if(i>7)
{
ADDR3 = 1;
P1 = (P1&0xF8)|(i-8);
if(i==14)
LEDBuf[6]=Led[cnt];
P0 =LEDBuf[i-8];
}
else
{
ADDR3 = 0;
P1 = (P1&0xF8)|i;
P0=Lattice[i];
}
i++;
if(i>15)
i=0;
注:以上扫描函数需要放到中断中
全部代码如下:
#include<reg52.h>
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
void ConfigTimer0(unsigned long ms);//定时多少毫秒
void ScanLattLed();//点阵扫描
unsigned char T0RH = 0;
unsigned char T0RL = 0;
unsigned char code Lattice[8] = {//心形字模表
0x99,0x00,0x00,0x00,0x81,0xC3,0xE7,0xFF
};
unsigned char code LedChar[]={//数码管显示字符转换表
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
unsigned char code Led[8] = {
0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F
};
unsigned char LedBuff[]={
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
bit flag1s = 0;//1s定时标志
unsigned char cnt = 0;//记录T0中断次数
void main()
{
unsigned long sec = 0;
ENLED = 0;
EA = 1;
ConfigTimer0(1);
while(1)
{
if(flag1s == 1)
{
flag1s = 0;
sec++;
LedBuff[0] = LedChar[sec%10];
LedBuff[1] = LedChar[sec/10%10];
LedBuff[2] = LedChar[sec/100%10];
LedBuff[3] = LedChar[sec/1000%10];
LedBuff[4] = LedChar[sec/10000%10];
LedBuff[5] = LedChar[sec/100000%10];
}
}
}
void ConfigTimer0(unsigned long ms)//定时多少毫秒
{
unsigned long tmp;
tmp = 11059200/12;
tmp = (tmp*ms)/1000;
tmp = 65536-tmp;
tmp += 18;
T0RH = (unsigned char)(tmp>>8);
T0RL = (unsigned char)tmp;
TMOD &= 0xF0;
TMOD |= 0x01;
TH0 = T0RH;
TL0 = T0RL;
ET0 = 1;
TR0 = 1;
}
void ScanLattLed()
{
static unsigned char i = 0;
P0 = 0xFF;
if(i>7)//扫描数码管与LED小灯
{
ADDR3 = 1;
P1 = (P1&0xF8)|(i-8);
if(i==14)
LedBuff[6]=Led[cnt];
P0 = LedBuff[i-8];
}
else //i<7时扫描点阵
{
ADDR3 = 0;
P1 = (P1&0xF8)|i;
P0 = Lattice[i];
}
i++;
if(i>15)
i=0;
}
void InterruptTimer0() interrupt 1
{
static unsigned long cut = 0;
TH0 = 0xFC;
TL0 = 0x67;
cut++;
if(cut>=1000)
{
cut=0;
cnt++;
flag1s=1;
if(cnt>7)//cnt为LED数组索引
cnt=0;
}
ScanLattLed();//点阵、数码管、LED扫描
}