[蓝桥杯国赛]练手第八届省赛题目

题目为基于单片机的电子钟程序设计与调试
分析 程序如何宏观规划(十分重要) 特点:切换界面多
方法:多个界面时用一个变量display_mode来管理,按键按下后对display_mode赋值,在while(1)每2ms程序里写if(display_mode==…)来完成功能
按键调整RTC时间 思路:
按键后,记录当前RTC的值,即时分秒,根据其他按键操作,对记录下的变量操作,最后再对RTC赋值set_sfm就可以
Tip:
①涉及到操作RTC的hour min sec最好将要操作的转换为10进制,16进制不能++操作
②出现了按键不起作用,是因为++save_shi,但是每次save_shi会被shi赋值,所以按键无效。要通过按键改变输出值,则输出更改输入固定的变量,不然总是被赋新值,按键操作不起作用了
③RTC不能直接放在WHLIE1里 更新太快不可以,每2或者3ms更新一次即可,不然不会更新数据
④RTC:如果跳动,或1s跳两下说明中断干扰了
松开按键检测 状态机消抖的KEY_STATE_2状态下就可以检测是否松开

//根据是否松开来决定是否切换界面 case KEY_STATE_2: if(key_temp==NO_KEY) { if(display_mode==3)display_mode=0; key_state=KEY_STATE_0; } break;

闹钟提示功能关闭实现 ①5s自动关闭
当闪烁的时候有一个标志,定时5s结束闪烁的方法:
闪烁标志开始时,5s定时也开始了,如果5s到了闪烁标志被清掉
②按键手动关闭(闹钟提示状态下,按下任意按键,关闭闪烁提示功能)
case KEY_STATE_1: if(key_temp == NO_KEY) { key_state=KEY_STATE_0; } else { if(alarm_led_flag==1) { key_delete_alarm=1; } switch(key_temp) { ..... .... }

灯闪烁实现 比如0.2s标志bit切换,一个功能亮,一个功能灭
if(alarm_led_flag==1 && key_delete_alarm==0) { if(delay_200ms_flag_flag==0) {P2=0x80; P0=0xfe; P2=0x00; }//亮 else {P2=0x80; P0=0xff; P2=0x00; }//灭 }

待调整位闪烁 定义了一个set_clock_number,这个是按键按一次加一,切换到下一调整位,在不同调整位闪烁相应位置的数码管,按set_clock_number切换到4时,就切换到初始显示模式(这是本题的要求)
if(display_mode==2) //闹钟设置界面 { alarm_display_menu[0]=smg_duan[alarm_shi/10]; alarm_display_menu[1]=smg_duan[alarm_shi%10]; alarm_display_menu[3]=smg_duan[alarm_fen/10]; alarm_display_menu[4]=smg_duan[alarm_fen%10]; alarm_display_menu[6]=smg_duan[alarm_miao/10]; alarm_display_menu[7]=smg_duan[alarm_miao%10]; if(set_clock_number==1) {if(blink_1s_flag==0)//1s闪烁 { alarm_display_menu[0]=smg_duan[alarm_shi/10]; alarm_display_menu[1]=smg_duan[alarm_shi%10]; } else { alarm_display_menu[0]=0x00; alarm_display_menu[1]=0x00; } } if(set_clock_number==2) {if(blink_1s_flag==0)//1s闪烁 { alarm_display_menu[3]=smg_duan[alarm_fen/10]; alarm_display_menu[4]=smg_duan[alarm_fen%10]; } else { alarm_display_menu[3]=0x00; alarm_display_menu[4]=0x00; } } if(set_clock_number==3) {if(blink_1s_flag==0)//1s闪烁 { alarm_display_menu[6]=smg_duan[alarm_miao/10]; alarm_display_menu[7]=smg_duan[alarm_miao%10]; } else { alarm_display_menu[6]=0x00; alarm_display_menu[7]=0x00; } } if(set_clock_number==4)//恢复 { display_mode=0; set_clock_number=0; } }

代码 【[蓝桥杯国赛]练手第八届省赛题目】晚上熬夜写的,可能可读性不强
#include "STC15F2K60S2.h" #include "ds1302.h" #include "onewire.h"#define u8 unsigned char #define u16 unsigned int #define NO_KEY 0xff #define KEY_STATE_0 0 #define KEY_STATE_1 1 #define KEY_STATE_2 2u8 code smg_duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40,0x00}; u8 code smg_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; u8 display_menu[8]={0}; u8 set_clock_display_menu[8]={0}; u8 temperature_display_menu[8]={0}; u8 alarm_display_menu[8]={0}; sbit buzzer=P0^6; sbit relay=P0^4; sbit LED1=P0^0; bit blink_1s_flag=0; bit delay_200ms_flag_flag=0; bit alarm_led_flag=0; u8 temperature_val=0; u8 circle_2ms_flag=0; u8 shi,fen,miao; u8 alarm_shi=0,alarm_fen=0,alarm_miao=0; u8 save_shi,save_fen,save_miao; u8 set_clock_number=0; u8 key_val=0; u8 display_mode=0; //0:时钟显示界面 1:时钟设置界面 2:闹钟设置界面 3:温度显示界面 u8 key_delete_alarm=0; //0:正常 1:取消功能u8 Read_Key(void) { static u8 key_state = KEY_STATE_0; u8 key1,key2,key_temp; u8 key_return=0; P30=0; P31=0; P32=0; P33=0; P34=1; P35=1; P42=1; P44=1; if(0==P34)key1=0xe0; if(0==P35)key1=0xd0; //1101 0000 if(0==P42)key1=0xb0; //1011 if(0==P44)key1=0x70; if( 1==P34 && 1==P35 && 1==P42 && 1==P44)key1=0xf0; P30=1; P31=1; P32=1; P33=1; P34=0; P35=0; P42=0; P44=0; if(0==P30)key2=0x0e; if(0==P31)key2=0x0d; //1101 0000 if(0==P32)key2=0x0b; //1011 if(0==P33)key2=0x07; if( 1==P30 && 1==P31 && 1==P32 && 1==P33)key2=0x0f; key_temp=key1|key2; switch(key_state) { case KEY_STATE_0: if(key_temp != NO_KEY) { key_state=KEY_STATE_1; } break; case KEY_STATE_1: if(key_temp == NO_KEY) { key_state=KEY_STATE_0; } else { if(alarm_led_flag==1) { key_delete_alarm=1; } switch(key_temp) { case 0x77:key_return=4; break; case 0x7b:key_return=5; break; case 0x7d:key_return=6; break; case 0x7e:key_return=7; break; case 0xb7:key_return=8; break; case 0xbb:key_return=9; break; case 0xbd:key_return=10; break; case 0xbe:key_return=11; break; case 0xd7:key_return=12; break; case 0xdb:key_return=13; break; case 0xdd:key_return=14; break; case 0xde:key_return=15; break; case 0xe7:key_return=16; break; case 0xeb:key_return=17; break; case 0xed:key_return=18; break; case 0xee:key_return=19; break; } key_state=KEY_STATE_2; } break; case KEY_STATE_2: if(key_temp==NO_KEY) { if(display_mode==3)display_mode=0; key_state=KEY_STATE_0; } break; } return key_return; }void Timer0Init(void)//1毫秒@12.000MHz { AUXR |= 0x80; //定时器时钟1T模式 TMOD &= 0xF0; //设置定时器模式 TL0 = 0x20; //设置定时初值 TH0 = 0xD1; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0=1; EA=1; }//--------------------------------------------------------------------- //--------------------------------------------------------------------- //--------------------------------------------------------------------- //--------------------------------------------------------------------- //---------------------------------------------------------------------void main(void) { Timer0Init(); P2=0xa0; buzzer=0; relay=0; P2=0x00; set_sfm(23,59,58); display_menu[2]=0x40; display_menu[5]=0x40; set_clock_display_menu[2]=0x40; set_clock_display_menu[5]=0x40; alarm_display_menu[2]=0x40; alarm_display_menu[5]=0x40; while(1) { if(circle_2ms_flag==1) { circle_2ms_flag=0; /// if(display_mode==0) //时钟显示界面 { EA=0; shi=Read_Ds1302(0x85); fen=Read_Ds1302(0x83); miao=Read_Ds1302(0x81); shi=(shi/16)*10+shi%16; fen=(fen/16)*10+fen%16; miao=(miao/16)*10+miao%16; EA=1; display_menu[0]=smg_duan[shi/10]; display_menu[1]=smg_duan[shi%10]; display_menu[3]=smg_duan[fen/10]; display_menu[4]=smg_duan[fen%10]; display_menu[6]=smg_duan[miao/10]; display_menu[7]=smg_duan[miao%10]; }/ if(display_mode==1) //时钟设置界面 { save_shi=shi; //巨坑,最好shi,fen,miao自己使用的都转换为10进制,因为16进制++会有问题 save_fen=fen; save_miao=miao; set_clock_display_menu[0]=smg_duan[save_shi/10]; set_clock_display_menu[1]=smg_duan[save_shi%10]; set_clock_display_menu[3]=smg_duan[save_fen/10]; set_clock_display_menu[4]=smg_duan[save_fen%10]; set_clock_display_menu[6]=smg_duan[save_miao/10]; set_clock_display_menu[7]=smg_duan[save_miao%10]; if(set_clock_number==1) {if(blink_1s_flag==0)//1s闪烁 { set_clock_display_menu[0]=smg_duan[save_shi/10]; set_clock_display_menu[1]=smg_duan[save_shi%10]; } else { set_clock_display_menu[0]=0x00; set_clock_display_menu[1]=0x00; } } if(set_clock_number==2) {if(blink_1s_flag==0)//1s闪烁 { set_clock_display_menu[3]=smg_duan[save_fen/10]; set_clock_display_menu[4]=smg_duan[save_fen%10]; } else { set_clock_display_menu[3]=0x00; set_clock_display_menu[4]=0x00; } } if(set_clock_number==3) {if(blink_1s_flag==0)//1s闪烁 { set_clock_display_menu[6]=smg_duan[save_miao/10]; set_clock_display_menu[7]=smg_duan[save_miao%10]; } else { set_clock_display_menu[6]=0x00; set_clock_display_menu[7]=0x00; } } if(set_clock_number==4)//恢复 { display_mode=0; set_clock_number=0; //set_sfm(((save_shi/16)*10+save_shi%16),((save_fen/16)*10+save_fen%16),((save_miao/16)*10+save_miao%16)); //这里被困扰了好久set_sfm(save_shi,save_fen,save_miao); } }/ if(display_mode==3) //温度显示界面 { temperature_val = rd_temperature_f(); temperature_display_menu[5]=smg_duan[temperature_val/10]; temperature_display_menu[6]=smg_duan[temperature_val%10]; temperature_display_menu[7]=0x39; }if(display_mode==2) //闹钟设置界面 { alarm_display_menu[0]=smg_duan[alarm_shi/10]; alarm_display_menu[1]=smg_duan[alarm_shi%10]; alarm_display_menu[3]=smg_duan[alarm_fen/10]; alarm_display_menu[4]=smg_duan[alarm_fen%10]; alarm_display_menu[6]=smg_duan[alarm_miao/10]; alarm_display_menu[7]=smg_duan[alarm_miao%10]; if(set_clock_number==1) {if(blink_1s_flag==0)//1s闪烁 { alarm_display_menu[0]=smg_duan[alarm_shi/10]; alarm_display_menu[1]=smg_duan[alarm_shi%10]; } else { alarm_display_menu[0]=0x00; alarm_display_menu[1]=0x00; } } if(set_clock_number==2) {if(blink_1s_flag==0)//1s闪烁 { alarm_display_menu[3]=smg_duan[alarm_fen/10]; alarm_display_menu[4]=smg_duan[alarm_fen%10]; } else { alarm_display_menu[3]=0x00; alarm_display_menu[4]=0x00; } } if(set_clock_number==3) {if(blink_1s_flag==0)//1s闪烁 { alarm_display_menu[6]=smg_duan[alarm_miao/10]; alarm_display_menu[7]=smg_duan[alarm_miao%10]; } else { alarm_display_menu[6]=0x00; alarm_display_menu[7]=0x00; } } if(set_clock_number==4)//恢复 { display_mode=0; set_clock_number=0; } }/ if(alarm_shi==shi && alarm_fen==fen && alarm_miao==miao) { alarm_led_flag=1; } if(alarm_led_flag==1 && key_delete_alarm==0) { if(delay_200ms_flag_flag==0) {P2=0x80; P0=0xfe; P2=0x00; }//亮 else {P2=0x80; P0=0xff; P2=0x00; }//灭 } key_val=Read_Key(); switch(key_val) { case 4: if(display_mode==0) { display_mode=3; } if(display_mode==1) { switch(set_clock_number) { case 1: if(shi>0) shi--; break; //出现了按键不起作用,是因为++save_shi,每次save_shi会被shi赋值,所以按键无效 case 2: if(fen>0) fen--; break; case 3: if(miao>0) miao--; break; } } if(display_mode==2) { switch(set_clock_number) { case 1: if(alarm_shi>0) alarm_shi--; break; //出现了按键不起作用,是因为++save_shi,每次save_shi会被shi赋值,所以按键无效 case 2: if(alarm_fen>0) alarm_fen--; break; case 3: if(alarm_miao>0) alarm_miao--; break; } } break; case 5: if(display_mode==1) { switch(set_clock_number) { case 1: if(shi<23) shi++; break; //出现了按键不起作用,是因为++save_shi,每次save_shi会被shi赋值,所以按键无效 case 2: if(fen<59) fen++; break; case 3: if(miao<59) miao++; break; } } if(display_mode==2) { switch(set_clock_number) { case 1: if(alarm_shi<23) alarm_shi++; break; //出现了按键不起作用,是因为++save_shi,每次save_shi会被shi赋值,所以按键无效 case 2: if(alarm_fen<59) alarm_fen++; break; case 3: if(alarm_miao<59) alarm_miao++; break; } } break; case 6: if(display_mode==0 || display_mode==2) { display_mode=2; set_clock_number++; ; } break; case 7: display_mode=1; set_clock_number++; break; case 8:break; case 9:break; case 10:break; case 11:break; case 12:break; case 13:break; case 14:break; case 15:break; case 16:break; case 17:break; case 18:break; case 19:break; }} } }void tm0_isr() interrupt 1 using 1 { static int delay_10ms_flag_int=0,delay_2ms_flag_int=0,i=0,blink_1s_flag_int=0,delay_200ms_flag_int=0,delay_200ms_flag_count=0; delay_10ms_flag_int++; delay_2ms_flag_int++,blink_1s_flag_int++,delay_200ms_flag_int++; if(delay_10ms_flag_int==10) {delay_10ms_flag_int=0; } if(delay_2ms_flag_int==2) { circle_2ms_flag=1; delay_2ms_flag_int=0; P2=0xc0; P0=0x00; P2=0x00; if(display_mode==0)P2=0xe0; P0=~display_menu[i]; P2=0x00; if(display_mode==1)P2=0xe0; P0=~set_clock_display_menu[i]; P2=0x00; if(display_mode==2)P2=0xe0; P0=~alarm_display_menu[i]; P2=0x00; if(display_mode==3)P2=0xe0; P0=~temperature_display_menu[i]; P2=0x00; P2=0xc0; P0=smg_wei[i]; P2=0x00; i++; if(i==8)i=0; } if(blink_1s_flag_int==1000)//1s { blink_1s_flag_int=0; blink_1s_flag=~blink_1s_flag; } if(delay_200ms_flag_int==200) { delay_200ms_flag_int=0; delay_200ms_flag_flag=~delay_200ms_flag_flag; } if(alarm_led_flag==1)//亮5s怎么写,我想了好久!!!! { delay_200ms_flag_count++; // if(delay_200ms_flag_count==5000) { alarm_led_flag=0; delay_200ms_flag_count=0; {P2=0x80; P0=0xff; P2=0x00; }//灭} }}

    推荐阅读