深入浅出玩转51单片机——学习笔记:数码管时间显示+调时功能
0赞
发表于 5/23/2014 9:11:16 AM
阅读(3963)
/********************************************** 实现功能:数码管时间显示+调时功能(按键只具备单击功能) 时间初始值:12:34:56 Key1未按下,Key2、Key3按下无效 当Key1第一次按下,可以调整秒时间(Key2按下,秒加1;Key3按下,秒减1) 当Key1第二次按下,可以调整分时间(Key2按下,分加1;Key3按下,分减1) 当Key1第三次按下,可以调整时时间(Key2按下,时加1;Key3按下,时减1) 当Key1第四次按下,时间正常运行 硬件平台:基于MGMC-V1.0实验板 晶振频率:11.0592Mhz 时间:2014年5月16日 ***********************************************/ #include<reg52.h> typedef unsigned char uint8; typedef unsigned int uint16; sbit We_En = P1^6; //定义数码管位选 sbit Du_En = P1^7; //定义数码管段选 uint8 Key_Return = 0; //返回的按键键值 uint8 j = 0; sbit Key1 = P3^4; sbit Key2 = P3^5; sbit Key3 = P3^6; #define Initial_State 0 //按键初始状态 #define Affirm_State 1 //按键消抖状态 #define Signel_State 2 //按键松手确认状态 uint8 Bit_Tab[8] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //数码管位选 uint8 SEG_Tab[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f}; //数码管段选 char time[3]; uint8 Dis_Buff[6]; uint8 We_Cnt = 0; uint8 time_2ms_ok = 0; //2ms时间到标志位 uint8 time_1s_ok = 0; //1s时间到标志位 uint8 time_10ms_ok = 0; //10ms时间到标志位 uint16 i = 0; void initial_myself(); //上电初始化 void initial_peripheral(); //外围设备初始化 void Dleay_Ms(uint16 z); void Dis_Buffer(); //时间分离函数 void SEG_Display(); //数码管刷新函数 void Time_Service(); //时间计时函数 char Key_Scan(); //按键扫描函数 void Key_Service(); //按键调整时间函数 void main() { initial_myself(); //上电初始化 Dleay_Ms(10); initial_peripheral(); //外围设备初始化 time[0] = 56; time[1] = 34; time[2] = 12; //设置时间为:12:34:56 while(1) { if(1 == time_10ms_ok) //10ms时间到 { time_10ms_ok = 0; Key_Scan(); //按键扫描 } Dis_Buffer(); //时间分离函数 SEG_Display(); //数码管刷新函数 Time_Service(); //时间计时函数 Key_Service(); //按键调整时间函数 } } void Time_Service() //时间计时函数 { if(1 == time_1s_ok) //1s时间到 { time_1s_ok = 0; if(++time[0] >= 60) { time[0] = 0; if(++time[1] >= 60) { time[1] = 0; if(++time[2] >= 24) { time[2] = 0; } } } } } void SEG_Display() //数码管刷新函数 { if(1 == time_2ms_ok) //2ms时间到 { time_2ms_ok = 0; switch(We_Cnt) { case 0: //刷新第一个数码管 { Du_En = 1; P0 = 0x00; Du_En = 0; We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0; P0 = 0x00; Du_En = 1; P0 = SEG_Tab[Dis_Buff[0]]; Du_En = 0; We_Cnt++; } break; case 1: //刷新第二个数码管 { Du_En = 1; P0 = 0x00; Du_En = 0; We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0; P0 = 0x00; Du_En = 1; P0 = SEG_Tab[Dis_Buff[1]]; Du_En = 0; We_Cnt++; } break; case 2: //刷新第三个数码管 { Du_En = 1; P0 = 0x00; Du_En = 0; We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0; P0 = 0x00; Du_En = 1; P0 = 0x40; Du_En = 0; We_Cnt++; } break; case 3: //刷新第四个数码管 { Du_En = 1; P0 = 0x00; Du_En = 0; We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0; P0 = 0x00; Du_En = 1; P0 = SEG_Tab[Dis_Buff[2]]; Du_En = 0; We_Cnt++; } break; case 4: //刷新第五个数码管 { Du_En = 1; P0 = 0x00; Du_En = 0; We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0; P0 = 0x00; Du_En = 1; P0 = SEG_Tab[Dis_Buff[3]]; Du_En = 0; We_Cnt++; } break; case 5: //刷新第六个数码管 { Du_En = 1; P0 = 0x00; Du_En = 0; We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0; P0 = 0x00; Du_En = 1; P0 = 0x40; Du_En = 0; We_Cnt++; } break; case 6: //刷新第七个数码管 { Du_En = 1; P0 = 0x00; Du_En = 0; We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0; P0 = 0x00; Du_En = 1; P0 = SEG_Tab[Dis_Buff[4]]; Du_En = 0; We_Cnt++; } break; case 7: //刷新第八个数码管 { Du_En = 1; P0 = 0x00; Du_En = 0; We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0; P0 = 0x00; Du_En = 1; P0 = SEG_Tab[Dis_Buff[5]]; Du_En = 0; We_Cnt = 0; } break; } } } void Dis_Buffer() //时间分离函数 { Dis_Buff[0] = time[0]%10; //秒个位 Dis_Buff[1] = time[0]/10; //秒十位 Dis_Buff[2] = time[1]%10; //分个位 Dis_Buff[3] = time[1]/10; //分十位 Dis_Buff[4] = time[2]%10; //时个位 Dis_Buff[5] = time[2]/10; //时十位 } void initial_myself() //上电初始化 { P0 = 0xff; P3 = 0xff; We_En = 0; //关位选 Du_En = 0; //关段选 TMOD &= 0x00; TMOD |= 0x01; // 定时器0,模式1 TMOD |= 0x10; // 定时器1,模式1 TH0 = 0xf8; //设置初值,没2ms进入一次中断 TL0 = 0xcd; TH1 = 0xdc; //设置初值,没10ms进入一次中断 TL1 = 0x00; } void initial_peripheral() //外围设备初始化 { EA = 1; //开总中断 ET0 = 1; //使能T0中断 TR0 = 1; //使能T0 ET1 = 1; //使能T1中断 TR1 = 1; //使能T1 } void T0_interrupt() interrupt 1 //定时器0中断函数 { TF0 = 0; TH0 = 0xf8; TL0 = 0xcd; time_2ms_ok = 1; //2ms时间到 if(++j >= 5) { j = 0; time_10ms_ok = 1; //10ms时间到 } } void T1_interrupt() interrupt 3 //定时器1中断函数 { TF1 = 0; TH1 = 0xdc; TL1 = 0x00; if(++i >= 100) { i = 0; time_1s_ok = 1; //1s时间到 } } void Dleay_Ms(uint16 z) { uint16 x,y; for(x = 0; x < z; x++) for(y = 0; y < 100; y++); } char Key_Scan() { static uint8 Key_State = 0; uint16 Key_Valve; Key_Valve = (Key1&Key2&Key3); switch(Key_State) { case Initial_State : //按键初始状态 { if(Key_Valve != 1) { Key_State = Affirm_State; } } break; case Affirm_State : //按键消抖状态 { if(Key_Valve != 1) { if(0 == Key1) { Key_Return = 1; } if(0 == Key2) { Key_Return = 2; } if(0 == Key3) { Key_Return = 3; } Key_State = Signel_State; //转到松手检测 } else { Key_State = Initial_State; //转到初始状态 } } break; case Signel_State : //按键松手检测 { if(1 == Key_Valve) { Key_State = Initial_State; } } break; } return 0; } void Key_Service() { static uint8 Key_Num = 0; if(1 == Key_Return) // Key1按下 { Key_Return = 0; TR1 = 0; //关定时器1,时间停止计数 Key_Num++; //Key1按下次数 } switch(Key_Num) { case 1: //Key1按下1次,秒调整状态 { if(2 == Key_Return) //Key2按下,秒时间加1; { Key_Return = 0; time[0]++; if(time[0] > 59) { time[0] = 0; } } if(3 == Key_Return) //Key3按下,秒时间减1 { Key_Return = 0; time[0]--; if(time[0]<0) { time[0] = 59; } } } break; case 2: //Key1按下2次,分钟调整状态 { if(2 == Key_Return) //Key2按下,分时间加1; { Key_Return = 0; time[1]++; if(time[1] > 59) { time[1] = 0; } } if(3 == Key_Return) //Key3按下,分时间减1 { Key_Return = 0; time[1]--; if(time[1]<0) { time[1] = 59; } } } break; case 3: //Key1按下3次,小时调整状态 { if(2 == Key_Return) //Key2按下,小时时间加1; { Key_Return = 0; time[2]++; if(time[2] > 24) { time[2] = 0; } } if(3 == Key_Return) //Key3按下,小时时间减1 { Key_Return = 0; time[2]--; if(time[2]<0) { time[2] = 24; } } } break; case 4: //Key1按下4次,时间运行确认 { Key_Num = 0; TR1 = 1; } break; } }