题目为基于单片机的电子钟程序设计与调试
特点:切换界面多
方法:多个界面时用一个变量display_mode来管理,按键按下后对display_mode赋值,在while(1)每2ms程序里写if(display_mode==…)来完成功能
思路:
按键后,记录当前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 2
u8 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;}//灭
}
}
}