需求:(題目來自小蜜蜂老師)



#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(); //保證數碼管動態顯示
}
}
}
}
/*=========================================================================*/
/*================================定時器T0=================================*/
//定時器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(); //命令處理
}
}
/*=========================================================================*/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/260316.html
標籤:其他
上一篇:北汽eu5車機降級方法
