需求:(题目来自小蜜蜂老师)
#include<reg52.h>
sfr AUXR = 0x8e; //设置辅助寄存器AUXR
sbit S7 = P3^0; //独立按键S7
sbit S5 = P3^2; //独立按键S5
unsigned char command; //接收串口数据
unsigned char state = 0xff; //LED当前状态
unsigned char hour = 0; //时
unsigned char minute = 0; //分
unsigned char second = 0; //秒
unsigned char count = 0; //50ms定时计数
unsigned char code SEG_code[19] =
{ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,
0xbf,0x7f,0x00}; //定义共阳数码管段码内容:0~F,—,.
//端口选择
void Select_HC138(unsigned char n)
{
switch(n)
{
case 0:
P2 = (P2 & 0x1f) | 0x00; //不选择
break;
case 4:
P2 = (P2 & 0x1f) | 0x80; //选择LED
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0; //选择蜂鸣器和继电器
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0; //选择数码管的位置
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0; //选择数码管的值
break;
}
}
//普通延时函数
void Delay_common(unsigned int t)
{
while(--t); //--t
}
//初始化
void Init_system()
{
Select_HC138(5);
P0 = 0x00; //关闭蜂鸣器和继电器
Select_HC138(4);
P0 = state; //关闭LED
Select_HC138(0);
}
//LED检测
void Check_LED()
{
unsigned char i;
Select_HC138(4);
for(i=1;i<=8;i++) //依次点亮LED
{
P0 = state << i;
Delay_common(60000);
Delay_common(60000);
Delay_common(60000);
}
for(i=1;i<=8;i++) //依次熄灭LED
{
P0 = ~(state << i);
Delay_common(60000);
Delay_common(60000);
Delay_common(60000);
}
Select_HC138(0);
}
//数码管检测
void Check_SMG()
{
unsigned char j;
for(j=1;j<=8;j++)
{
Select_HC138(6);
P0 = ~(0xff << j); //依次点亮数码管
Select_HC138(7);
P0 = SEG_code[18];
Delay_common(60000);
Delay_common(60000);
Delay_common(60000);
}
for(j=1;j<=8;j++)
{
Select_HC138(6);
P0 = 0xff << j; //依次熄灭数码管
Select_HC138(7);
P0 = SEG_code[18];
Delay_common(60000);
Delay_common(60000);
Delay_common(60000);
}
Select_HC138(0);
}
//数码管显示
void Show_tube(unsigned char position,unsigned char value)
{
Select_HC138(6);
P0 = 0x01 << position;
Select_HC138(7);
P0 = value;
}
//数码管动态显示
void Dynamic_display()
{
Show_tube(0,SEG_code[hour/10]); //显示时的十位
Delay_common(500);
Show_tube(1,SEG_code[hour%10]); //显示时的个位
Delay_common(500);
Show_tube(2,SEG_code[16]); //显示分隔符
Delay_common(500);
Show_tube(3,SEG_code[minute/10]); //显示分的十位
Delay_common(500);
Show_tube(4,SEG_code[minute%10]); //显示分的个位
Delay_common(500);
Show_tube(5,SEG_code[16]); //显示分隔符
Delay_common(500);
Show_tube(6,SEG_code[second/10]); //显示秒的十位
Delay_common(500);
Show_tube(7,SEG_code[second%10]); //显示秒的个位
Delay_common(500);
}
//去抖动延时函数
void Delay_keys()
{
unsigned char m = 108,n = 145;
while(--m)
{
while(--n);
}
}
//独立按键
void Press_keys()
{
if(S7 == 0) //按下S7,点亮L8
{
Delay_keys(); //去抖动
if(S7 == 0)
{
Select_HC138(4);
state = (state & 0x7f) | (~state & 0x80); //将最高位取反:将最高位置0、保留state低7位,然后取state取反后的最高位、其他位置0,最后组合
P0 = state; //将当前状态赋值给P0
Select_HC138(0);
while(S7 == 0)
{
Dynamic_display(); //保证数码管动态显示
}
}
}
else if(S5 == 0) //按下S5,点亮L7
{
Delay_keys(); //去抖动
if(S5 == 0)
{
Select_HC138(4);
state = (state & 0xbf) | (~state & 0x40); //将第7位取反:将第7位置0、保留state其他位,然后取state取反后的第7位、其他位置0,最后组合
P0 = state; //将当前状态赋值给P0
Select_HC138(0);
while(S5 == 0)
{
Dynamic_display(); //保证数码管动态显示
}
}
}
}
//定时器timer0中断初始化
void Init_timer0()
{
TMOD = 0x21; //注意:同时给定时器0和定时器1赋值
TH0 = (65535 - 50000) / 256; //定时50ms
TL0 = (65535 - 50000) % 256;
EA =1; //打开总中断
ET0 = 1; //打开定时器0的中断
TR0 = 1; //启动定时器0
}
//定时器0中断服务函数
void Service_timer0() interrupt 1
{
TH0 = (65535 - 50000) / 256; //重新赋值
TL0 = (65535 - 50000) % 256;
count++; //定时满50ms加1
if(count == 20)
{
count = 0;
second++; //定时满1s加1
}
if(second == 60)
{
second = 0;
minute++; //定时满1min加1
}
if(minute == 60)
{
minute = 0;
hour++; //定时满1h加1
}
}
//发送字节
void Send_byte(unsigned char dat)
{
SBUF = dat; //注意:串口自动转换输出16进制数
while(TI == 0); //等待发送
TI = 0; //清0
}
//发送字符串
//void Send_string(unsigned char *str)
//{
// while(*str != '\0')
// {
// Send_byte(*str++);
// }
//}
//串口中断初始化
void Init_uart()
{
SCON = 0x50; //8位异步uart并允许接收
AUXR = 0x00; //将AUXR置0
TMOD = 0x21; //注意:同时给定时器0和定时器1赋值
TH1 = 0xfd;
TL1 = 0xfd;
EA = 1; //打开总中断
ES = 1; //打开串口中断
TR1 = 1; //启动定时器1
}
//串口中断服务函数
void Service_uart() interrupt 4
{
if(RI == 1)
{
RI = 0; //清0
command = SBUF; //接收数据
}
}
//对串口接收的命令进行相应处理
void Command_process()
{
if(command)
{
switch(command & 0xf0) //取command的高4位,低4位清0
{
case 0xa0: //远程灯光控制
Select_HC138(4);
state = (state & 0xf0) | (~command & 0x0f); //保留state高4位,取~command的低4位,然后组合
P0 = state; //将当前状态赋值给P0
Select_HC138(0);
break;
case 0xb0: //读取系统运行时间
Send_byte((hour/10 << 4) | (hour%10)); //发送时
//Send_string("-"); //分隔符
Send_byte((minute/10 << 4) | (minute%10)); //发送分
//Send_string("-"); //分隔符
Send_byte((second/10 << 4) | (second%10)); //发送秒
//Send_string("\r\n"); //换行
break;
}
command = 0;
}
}
void main()
{
Init_system(); //初始化
Check_LED(); //LED检测
Check_SMG(); //数码管检测
Init_uart(); //串口初始化
Init_timer0(); //定时器0初始化
while(1)
{
Dynamic_display(); //数码管动态显示
Press_keys(); //独立按键
Command_process(); //命令处理
}
}