【本代码定时器与串口部分的初始化函数均由ISP自动生成。】
本代码参考多位csdn博主,进行融汇修改,可自行烧录查看。
#include"reg52.h"
unsigned char code SMG_duanma[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f}; //记得最后有;
sfr AUXR = 0x8e; //辅助寄存器
sbit S5 = P3^2;//定义按键S5引脚
sbit S4 = P3^3;//定义按键S4引脚
void InitSys(); //系统初始化,关闭无关设备
void Timer0Init(); //定时器初始化
void UartInit();//串口初始化
void LED_Check();//LED灯测试
void SMG_Check();//数码管测试
void SMG_Bit(unsigned char value,unsigned char pos); //数码管显示指定数据
void SMG_Display();//时间显示
void SendData(unsigned char dat); //单字节发送数据
void ExecuteCommand(); //数据解析函数
void HC573(unsigned char n); //寄存器选择
void Delay_SW(unsigned char t);
void Delay_SMG(unsigned int t);
void Delay_LED(unsigned int t); //延时函数
void ScanKeys(); //按键扫描
//========================================锁存器选择函数=====================================
void HC573(unsigned char n)
{
switch(n)
{
case 4: P2 = (P2 & 0x1f) | 0x80; break;
case 5: P2 = (P2 & 0x1f) | 0xa0; break;
case 6: P2 = (P2 & 0x1f) | 0xc0; break;
case 7: P2 = (P2 & 0x1f) | 0xe0; break;
case 0: P2 = (P2 & 0x1f) | 0x00; break; //所有锁存器不选择
}
}
//========================================定时器T0初始化函数==================================
void Timer0Init(void) //50毫秒@11.0592MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x00; //设置定时初始值
TH0 = 0x4C; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
//以上由ISP生成
ET0 = 1;
EA = 1;
}
//========================================定时器T0中断服务函数================================
unsigned char t_h = 0;
unsigned char t_m = 0;
unsigned char t_s = 0;
unsigned char count = 0;
void ServiceTime0() interrupt 1
{
TH0 = (65535 - 50000) / 256; //50000脉冲对应50ms
TL0 = (65535 - 50000) % 256;
count++;
if(count == 20) //50000*20=1000000脉冲对应1000ms即1s
{
count = 0;
t_s++;
}
if(t_s == 60)
{
t_m++;
t_s = 0;
if(t_m == 60)
{
t_h++;
t_m = 0;
}
}
}
//========================================串口初始化函数======================================
void UartInit(void) //9600bps@11.0592MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器时钟1T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xE0; //设置定时初始值
TH1 = 0xFE; //设置定时初始值
ET1 = 0; //禁止定时器%d中断
TR1 = 1; //定时器1开始计时
//以上由ISP生成
ES = 1;
EA = 1;
}
//========================================串口发送单字节函数==================================
void SendData(unsigned char dat)
{
SBUF = dat;
while(TI == 0);
TI = 0;
}
//========================================串口中断服务函数====================================
unsigned char command = 0; //!!!!串口命令字接受变量
void ServiceUart() interrupt 4
{
if (RI)
{
//改成
command = SBUF;
RI = 0;
/*
RI = 0; //清除RI位
P0 = SBUF; //P0显示串口数据
P22 = RB8; //P2.2显示校验位
*/
//以上由ISP生成
}
/*
if (TI)
{
TI = 0; //清除TI位
busy = 0; //清忙标志
}
*/
//以上由ISP生成
}
//========================================上位机命令执行解析函数==============================
unsigned char stat_led = 0xff;
void ExecuteCommand()
{
if(command)
{
switch(command & 0xf0)
{
case 0xa0:
HC573(4);
stat_led = (stat_led | 0x0f) & (~command | 0xf0); //(stat_led | 0x0f):保持高四位状态不变
P0 = stat_led;
HC573(0);
command = 0x00; //清零
break;
case 0xb0:
SendData((t_h / 10 << 4)|(t_h % 10));
SendData((t_m / 10 << 4)|(t_m % 10));
SendData((t_s / 10 << 4)|(t_s % 10));
command = 0x00; //清零
break;
}
}
}
//========================================独立按键扫描函数====================================
void Delay_SW(unsigned char t)
{
while(t--);
}
void ScanKeys()
{
if (S5 == 0)//按键S5控制L7
{
Delay_SW(100);
if (S5 == 0)
{
while(S5 == 0) //等待按键S5松开(没有结束,不能空等待)
{
SMG_Display();//等待的同时不断刷新数码管
}
HC573(4);
stat_led = (stat_led | 0x40) & (~stat_led | 0xbf);
P0 = stat_led;// (1111 1111 | 0100 000)&(0000 0000 | 1011 1111)
HC573(0); // 1011 1111 & 1011 1111 = 1011 1111(S7亮)
}
}
if (S4 == 0)//按键S5控制L7
{
Delay_SW(100);
if (S4 == 0)
{
while(S4 == 0) //等待按键S5松开(没有结束,不能空等待)
{
SMG_Display();//等待的同时不断刷新数码管
}
HC573(4);
stat_led = (stat_led | 0x80) & (~stat_led | 0x7f);
P0 = stat_led;// (1111 1111 | 1000 000)&(0000 0000 | 0111 1111)
HC573(0); // 0111 1111 & 0111 1111 = 0111 1111(S8亮)
}
}
}
//========================================LED检测=============================================
void Delay_LED(unsigned int t) //是int!!!!!!char会特别快
{
while(t--);
while(t--);
}
unsigned int i = 0;
void LED_Check()
{
HC573(4);
for(i = 1; i <= 8; i++) //i=1开始 且i <= 8
{
P0 = 0xff << i; //0xff
Delay_LED(60000);
Delay_LED(60000);
}
for(i = 1; i <= 8; i++)
{
P0 = ~(0xff << i);
Delay_LED(60000);
Delay_LED(60000);
}
HC573(0);
}
//========================================时间显示模块检测函数================================
void Delay_SMG(unsigned int t)
{
while(t--);
}
void SMG_Bit(unsigned char value,unsigned char pos)
{
HC573(7);
P0 = 0xff;
HC573(6);
P0 = 0x01 << pos;
HC573(7);
P0 = value;
}
void SMG_Check()
{
HC573(7);
P0 = 0x00;
for(i = 0; i < 8; i++)
{
HC573(6);
P0 = ~(0xff << i);
Delay_SMG(60000);
Delay_SMG(60000);
Delay_SMG(60000);
}
for(i = 0; i < 8; i++)
{
HC573(6);
P0 = 0xff << i;
Delay_SMG(60000);
Delay_SMG(60000);
Delay_SMG(60000);
}
HC573(0); //!!
}
//========================================系统显示时间========================================
void SMG_Display()
{
SMG_Bit(SMG_duanma[t_h/10],0);
Delay_SMG(600);
SMG_Bit(SMG_duanma[t_h%10],1);
Delay_SMG(600);
SMG_Bit(SMG_duanma[16],2);
Delay_SMG(600);
SMG_Bit(SMG_duanma[t_m/10],3);
Delay_SMG(600);
SMG_Bit(SMG_duanma[t_m%10],4);
Delay_SMG(600);
SMG_Bit(SMG_duanma[16],5);
Delay_SMG(600);
SMG_Bit(SMG_duanma[t_s/10],6);
Delay_SMG(600);
SMG_Bit(SMG_duanma[t_s%10],7);
Delay_SMG(600);
}
//========================================系统初始化函数======================================
void InitSys()
{
HC573(5);
P0 = 0x00;
HC573(4);
P0 = 0xff;
HC573(0);
}
//========================================主函数===============================================
void main()
{
InitSys();
LED_Check();
SMG_Check();
Timer0Init();
UartInit();
while(1)
{
ExecuteCommand();
SMG_Display();
ScanKeys();
}
}