#include<reg52.h> // 引入头文件
// 定义IO口
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
// 定义点阵显示图案
unsigned char code image[10][8]=
{
{0xFF,0xE7,0xDB,0xDB,0xDB,0xDB,0xE7,0xFF},
{0xFF,0xE3,0xE7,0xE7,0xE7,0xE7,0xC3,0xFF},
{0xFF,0xE7,0xDB,0xEF,0xF7,0xFB,0xC3,0xFF},
{0xFF,0xE7,0xDB,0xEF,0xF7,0xEF,0xDB,0xE7},
{0xEF,0xE7,0xEB,0xED,0x81,0xEF,0xEF,0xFF},
{0xFF,0xE3,0xFB,0xE3,0xDF,0xDF,0xEB,0xF7},
{0xEF,0xF7,0xFB,0xE3,0xDD,0xDD,0xE3,0xFF},
{0xFF,0xC3,0xDF,0xDF,0xDF,0xDF,0xDF,0xFF},
{0xE7,0xDB,0xBD,0xC3,0xBD,0xDB,0xE7,0xFF},
{0xC1,0xDD,0xDD,0xC1,0xDF,0xDF,0xC1,0xFF},
};
// 定义数码管显示字符
unsigned char code LedChar[]={
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
0x80, 0x90, // 扩展数码管显示范围
0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E // 数码管显示范围扩展
};
// 定义数码管缓冲区
unsigned char LedBuff[]={
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
// 定义LED点阵缓冲区
unsigned char Led[16] = {
0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,
0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F // 扩展LED显示范围
};
bit flag1s = 0; // 1s定时标志
unsigned int cnt = 0; // 记录T0中断次数
unsigned int sec = 0; // 秒数
void ConfigTimer0(unsigned long ms); // 定时多少毫秒
void ScanLattLed(); // 点阵和数码管扫描
void main()
{
ADDR3 = 0;
ENLED = 0;
EA = 1; // 允许中断
ET0 = 1; // 允许定时器0中断
TMOD = 0x01; // 设置定时器0为模式1
TH0 = 0xFC; // 定时器0初始值高位
TL0 = 0x67; // 定时器0初始值低位
TR0 = 1; // 启动定时器0
while(1)
{
if(flag1s == 1) // 每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;
TH0 = (unsigned char)(tmp >> 8);
TL0 = (unsigned char)tmp;
}
void ScanLattLed()
{
static unsigned char i = 0;
P0 = 0xFF;
if(i > 15) // 扩展了LED显示范围
i = 0;
if(i > 7) //扫描数码管与LED小灯
{
ADDR3 = 1;
P1 = (P1&0xF8)|(i-8);
LedBuff[6] = Led[cnt + 8]; // 选择扩展范围的LED
P0 = LedBuff[i - 8];
}
else // i < 8时扫描点阵
{
ADDR3 = 0;
P1 = (P1 & 0xF8) | i;
P0 = image[sec % 10][i];
}
i++;
}
void InterruptTimer0() interrupt 1
{
static unsigned long cut = 0;
TH0 = 0xFC;
TL0 = 0x67;
cut++;
if(cut >= 1000)
{
cut = 0;
cnt++;
flag1s = 1;
if(cnt > 15) // cnt为LED数组索引,扩展了LED的显示范围
cnt = 0;
}
ScanLattLed(); // 点阵和数码管扫描
}