目录
一、实现功能
1、实现最基本的计时功能,显示时、分、秒,可以通过按键设置时间。
要求:时钟计时精确,按键操作不影响计时。
2、具备秒表计时功能。
要求:记时精度达到100ms,计时支持启动、暂停、继续和停止操作。
3、具备整点响铃提示功能。
要求:整点闹铃五短一长,闹钟响铃时可以按键清楚响铃。
4、具备日期显示和调整功能。
二、思路1的分析
1、定时器0
进行时分秒的递增与计算,其中定时器0的采用了16位的50ms定时,
cpp
void T0_ISR(void) interrupt 1
{
uchar i=0;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
if(time_flag==0)
{
count++;
if(count==20)
{
count=0;
miao++;
}
if(miao==60)
{
miao=0;
fen++;
}
if(fen==60)
{
fen=0;
shi++;
}
if(shi==24)
{
shi=0;
}
if(shi!=0)
if(fen==0)
if(miao==0)
beep_flag=1;
}
else
{
if(TIME_CONTROL==0)
{
Timing++;
if(Timing==2)
{
Timing=0;
TIME_CLK++;
}
}
}
}
2、外部中断0
实现按键触控实现调整时分秒、秒表定时设定、日期调整设定。当然受限于屏幕大小,可以通过按键调整当前显示的功能。
即按下KEY1,实现DATA-CLK,即从日期显示改为时间显示,或从时间显示切换为日期显示。
即按下KEY2,实现CLK-TIMING,即从时间显示改为定时,或从定时切换为时间显示。
前文提到过,外部定时只有一个,除了上述两个按键,还有年月日、时分秒、开始暂停等调整,如何都实现外部中断呢。
可以看到通过两级与非门,实现了所有按键最后接到了外部中断,同时每个引脚再分别接到IO上,从而实现任意一个按键按下都会进入中断,在中断中再进行判断哪个按键被按下。
cpp
void keyscan()
{
if(key1==0)
{
delay_ms(10);
if(key1==0);
{
shi++;
}
}
if(key2==0)
{
delay_ms(10);
if(key2==0)
{
fen++;
}
}
if(key3==0)
{
delay_ms(10);
if(key3==0)
{
miao++;
}
}
if(key4==0)
{
delay_ms(10);
if(key4==0)
{
BEEP_Control=0;;
}
}
if(key5==0)
{
delay_ms(10);
if(key5==0)
{
time_flag=~time_flag;
lcd_clr();
delay_ms(10);
lcd_clr();
}
}
if(key6==0)
{
delay_ms(10);
if(key6==0)
{
TIME_CONTROL=~TIME_CONTROL;
lcd_clr();
delay_ms(10);
lcd_clr();
}
}
if(key7==0)
{
delay_ms(10);
if(key7==0)
{
date_CONTROL=~date_CONTROL;
lcd_clr();
delay_ms(10);
lcd_clr();
}
}
if(key8==0)
{
delay_ms(10);
if(key8==0)
{
ri++;
}
}
if(key9==0)
{
delay_ms(10);
if(key9==0)
{
yue++;
}
}
if(key10==0)
{
delay_ms(10);
if(key10==0)
{
nian++;
}
}
}
void INT0_ISR(void) interrupt 0
{
EX0=0;
delay_ms(1);
if(0==P3_2)
{
keyscan();
}
IE0=0;
EX0=1;
}
3、主函数main
循环刷新LCD显示时分秒、秒表、日期。
cpp
void api()
{
uchar i=0;
if(date_CONTROL==0)
{
TIME_CLK=0;
shi=fen=miao=0;
date_display();
for(i=0;i<8;i++)
{
lcd_wcom(0x8B+i);
lcd_wdat(table5[i]);
}
}
else
{
if(time_flag==0)
{
TIME_CLK=0;
if(beep_flag==1)
{
beep_flag=0;
beep_on();
}
time_display();
for(i=0;i<7;i++)
{
lcd_wcom(0x88+i);
lcd_wdat(table1[i]);
}
}
else
{
timing_display();
if(TIME_CONTROL==0)
{
shi=fen=miao=0;
for(i=0;i<11;i++)
{
lcd_wcom(0x86+i);
lcd_wdat(table2[i]);
}
}
else
{
for(i=0;i<11;i++)
{
lcd_wcom(0x86+i);
lcd_wdat(table3[i]);
}
}
}
}
}
void main(void) //主函数,单片机开机后就是从这个函数开始运行
{
lcd_init(); //液晶初始化
time_init();
while(1)
{
api();
}
}
其中timing_display实现了定时的显示;data_display实现了日期的显示;time_display实现了时间的显示;beep_on实现了准点蜂鸣器响(该缺点暂时使用了delay_ms(50)此类操作,从而占用了单片机前台刷新LCD,但是由于定时、日期等后台计数不会影响;可以考虑加入定时器1来进行延时的计算,保证LCD的刷新)
4、其他重要功能函数
cpp
void time_display()
{
lcd_wcom(0x80);
lcd_wdat(table[shi/10]);
lcd_wcom(0x81);
lcd_wdat(table[shi%10]);
lcd_wcom(0x82);
lcd_wdat(table[10]);
lcd_wcom(0x83);
lcd_wdat(table[fen/10]);
lcd_wcom(0x84);
lcd_wdat(table[fen%10]);
lcd_wcom(0x85);
lcd_wdat(table[10]);
lcd_wcom(0x86);
lcd_wdat(table[miao/10]);
lcd_wcom(0x87);
lcd_wdat(table[miao%10]);
lcd_wcom(0x88);
}
void timing_display()
{
if(TIME_CLK==1000)
TIME_CLK=0;
lcd_wcom(0x80);
lcd_wdat(table[TIME_CLK/1000]);
lcd_wcom(0x81);
lcd_wdat(table[TIME_CLK/100%10]);
lcd_wcom(0x82);
lcd_wdat(table[TIME_CLK%100/10]);
lcd_wcom(0x83);
lcd_wdat(table[11]);
lcd_wcom(0x84);
lcd_wdat(table[TIME_CLK%10]);
}
void date_display()
{
int a[12]={31,28,31,30,31,30,31,31,30,31,30,31};
int b[12]={31,29,31,30,31,30,31,31,30,31,30,31};
if(nian%100==0)
{ if(nian%4==0)
if(ri>b[yue])
{
ri=1;
yue+=1;
}
}
else if(nian%4==0)
{
if(ri>b[yue])
{
ri=1;
yue+=1;
}
}
else
{
if(ri>a[yue])
{
ri=1;
yue+=1;
}
}
if(yue==13)
{
yue=1;
nian+=1;
}
lcd_wcom(0x80);
lcd_wdat(table4[nian/1000]);
lcd_wcom(0x81);
lcd_wdat(table4[nian/100%10]);
lcd_wcom(0x82);
lcd_wdat(table4[nian%100/10]);
lcd_wcom(0x83);
lcd_wdat(table4[nian%10]);
lcd_wcom(0x84);
lcd_wdat(table4[10]);
lcd_wcom(0x85);
lcd_wdat(table4[yue/10]);
lcd_wcom(0x86);
lcd_wdat(table4[yue%10]);
lcd_wcom(0x87);
lcd_wdat(table4[10]);
lcd_wcom(0x88);
lcd_wdat(table4[ri/10]);
lcd_wcom(0x89);
lcd_wdat(table4[ri%10]);
lcd_wcom(0x8A);
}
void beep_on()
{
BEEP_Control=1;
BEEP=0;
delay_ms(50);
BEEP=1;
delay_ms(50);
BEEP=0;
delay_ms(50);
BEEP=1;
delay_ms(50);
BEEP=0;
delay_ms(50);
BEEP=1;
delay_ms(50);
BEEP=0;
delay_ms(50);
BEEP=1;
delay_ms(50);
BEEP=0;
delay_ms(50);
BEEP=1;
delay_ms(50);
BEEP=0;
delay_ms(1000);
BEEP=1;
delay_ms(1000);
}
后续还有其他两个方法,在下一个博客进行介绍。