基於Proteus學習微控制器系列(五)——定時器實現電子錶
阿新 • • 發佈:2019-02-03
專案下載
1. 電路圖
2. 程式
主函式
#include<reg51.h> #include<DEFINE.c> #include<KEY.c> #include<DISPLAY.c> void timer_isr()interrupt 1 //中斷服務函式 { TL0 = (65536-2000) %256; //TL0重置函式 TH0 = (65536-2000)/256; //TH0重置函式 cp++; if(cp>=250) //0.5s { cp1++; cp = 0; flash = ~flash; //0.5s - 閃爍 if(cp1>=2) //1s { if(mode==0) //調整時,時間停止 sec++; cp1 = 0; if(sec>=60) //1min { min++; sec = 0; if(min>60) //1h { hour++; min = 0; if(hour>=24)hour = 0; } } } } P0 = 0xff; //消隱 switch(mode) { case 0:dis_play0();break; //正常 case 1:dis_play1();break; //調時 case 2:dis_play2();break; //調分 case 3:dis_play3();break; //調秒 case 4:dis_play4();break; //調鬧時 case 5:dis_play5();break; //調鬧分 } i++; if(i>=8)i = 0; } void timer0_init() //中斷初始化函式 { TMOD = 0x01; //方式一 TL0 = (65536-2000)%256; //TL0 預置,65536十六進位制低8位。 TH0 = (65536-2000)/256; //TH0 預置,65536十六進位制高8位。 EA = 1; //CPU中斷開放 ,總中斷開啟 ET0 = 1; //定時計數器T0的溢位終端控制位,T0中斷開啟 TR0 = 1; //定時計數器T0的啟停控制位,啟動T0 } void main() { timer0_init(); //timer0初始化,為中斷做準備 while(1) { key(); if(hour == hour_n && min == min_n) //鬧鐘到時間,蜂鳴器響 { P3_2 = !P3_2; delay(50); } } }
定義
#define uchar unsigned char; #define uint unsigned int; sbit key_set = P2^0; sbit key_up = P2^1; sbit key_down = P2^2; sbit P3_0 = P3^0; sbit P3_2 = P3^2; //蜂鳴器 sbit P2_4 = P2^4; uchar sec = 45,min = 12,hour; uchar sec_t,min_t,hour_t; uchar min_n = 13,hour_n; uchar cp,cp1; uchar flash,mode,i; code uchar seven_seg[] ={0xc0,0xf9,0xa4,0xb0,0x99,0x92, 0x82,0xf8,0x80,0x90};
按鍵函式
void delay(unsigned int x) //延時函式 { while(x--); } void key() //按鍵函式 { P2_4 = 0; if(key_set==0) //如果調整按鍵按下 { delay(300); //消抖 if(key_set==0) //如果調整按鍵真的按下 { while(key_set==0); mode++; if(mode>=6)mode = 0; //mode=0,退出調整 hour_t = hour; min_t = min; sec_t = sec; } } if(key_up==0) //如果增加按鍵按下 { delay(300); //消抖 if(key_up==0) //如果增加按鍵真的按下 { while(key_up==0); if(mode==1)hour_t++;if(hour_t>24)hour_t = 23;hour = hour_t; if(mode==2)min_t++;if(min_t>60)min_t = 59;min=min_t; if(mode==3)sec_t++;if(sec_t>60)sec_t = 59;sec = sec_t; if(mode==4)hour_n++;if(hour_n>24)hour_n = 23; if(mode==5)min_n++;if(min_n>60)min_n = 59; } } if(key_down==0) //如果減小按鍵按下 { delay(300); //消抖 if(key_down==0) //如果減小按鍵真的按下 { while(key_down==0); if(mode==1)hour_t--;if(hour_t<0)hour_t = 0;hour = hour_t; if(mode==2)min_t--;if(min_t<0)min_t = 0;min=min_t; if(mode==3)sec_t--;if(sec_t<0)sec_t = 0;sec = sec_t; if(mode==4)hour_n--;if(hour_n<0)hour_n = 0; if(mode==5)min_n--;if(min_n<0)min_n = 0; } } }
顯示函式
void display(unsigned char x1,x2)
{
P3_0 = 0; //鎖存器關
P0 = x1; //輸入位選
P3_0 = 1; //鎖存器開
P3_0 = 0; //鎖存器關
P0 = x2; //輸入段選
}
void dis_play0() //mode = 0 正常 顯示
{
switch(i)
{
case 0:display(0x01,seven_seg[sec%10]);break; //顯示秒個位
case 1:display(0x02,seven_seg[sec/10]);break; //顯示秒十位
case 2:display(0x04,0xbf|flash);break; //顯示 - 閃爍
case 3:display(0x08,seven_seg[min%10]);break; //顯示分個位
case 4:display(0x10,seven_seg[min/10]);break; //顯示分十位
case 5:display(0x20,0xbf|flash);break; //顯示 - 閃爍
case 6:display(0x40,seven_seg[hour%10]);break; //顯示時個位
case 7:display(0x80,seven_seg[hour/10]);break; //顯示時十位
}
}
void dis_play1() //mode = 1 調時
{
switch(i)
{
case 0:display(0x01,seven_seg[sec_t%10]);break; //顯示調秒個位
case 1:display(0x02,seven_seg[sec_t/10]);break; //顯示調秒十位
case 2:display(0x04,0xbf);break; //顯示 -
case 3:display(0x08,seven_seg[min_t%10]);break; //顯示調分個位
case 4:display(0x10,seven_seg[min_t/10]);break; //顯示調分十位
case 5:display(0x20,0xbf);break; //顯示 -
case 6:display(0x40,seven_seg[hour_t%10]|flash);break; //顯示調時個位 閃爍
case 7:display(0x80,seven_seg[hour_t/10]|flash);break; //顯示調時十位 閃爍
}
}
void dis_play2() //mode = 2 調分
{
switch(i)
{
case 0:display(0x01,seven_seg[sec_t%10]);break; //顯示調秒個位
case 1:display(0x02,seven_seg[sec_t/10]);break; //顯示調秒十位
case 2:display(0x04,0xbf);break; //顯示 -
case 3:display(0x08,seven_seg[min_t%10]|flash);break; //顯示調分個位 閃爍
case 4:display(0x10,seven_seg[min_t/10]|flash);break; //顯示調分十位 閃爍
case 5:display(0x20,0xbf);break; //顯示 -
case 6:display(0x40,seven_seg[hour_t%10]);break; //顯示調時個位
case 7:display(0x80,seven_seg[hour_t/10]);break; //顯示調時十位
}
}
void dis_play3() //mode = 3 調秒
{
switch(i)
{
case 0:display(0x01,seven_seg[sec_t%10]|flash);break; //顯示調秒個位 閃爍
case 1:display(0x02,seven_seg[sec_t/10]|flash);break; //顯示調秒十位 閃爍
case 2:display(0x04,0xbf);break; //顯示 -
case 3:display(0x08,seven_seg[min_t%10]);break; //顯示調分個位
case 4:display(0x10,seven_seg[min_t/10]);break; //顯示調分十位
case 5:display(0x20,0xbf);break; //顯示 -
case 6:display(0x40,seven_seg[hour_t%10]);break; //顯示調時個位
case 7:display(0x80,seven_seg[hour_t/10]);break; //顯示調時十位
}
}
void dis_play4() //mode = 4 調鬧時
{
switch(i)
{
case 0:display(0x01,0xbf);break; //顯示 -
case 1:display(0x02,0xbf);break; //顯示 -
case 2:display(0x04,0xbf);break; //顯示 -
case 3:display(0x08,seven_seg[min_n%10]);break; //顯示鬧分個位
case 4:display(0x10,seven_seg[min_n/10]);break; //顯示鬧分十位
case 5:display(0x20,0xbf);break; //顯示 -
case 6:display(0x40,seven_seg[hour_n%10]|flash);break; //顯示鬧時個位 閃爍
case 7:display(0x80,seven_seg[hour_n/10]|flash);break; //顯示鬧時十位 閃爍
}
}
void dis_play5() //mode = 5 調鬧分
{
switch(i)
{
case 0:display(0x01,0xbf);break; //顯示 -
case 1:display(0x02,0xbf);break; //顯示 -
case 2:display(0x04,0xbf);break; //顯示 -
case 3:display(0x08,seven_seg[min_n%10]|flash);break; //顯示鬧分個位 閃爍
case 4:display(0x10,seven_seg[min_n/10]|flash);break; //顯示鬧分十位 閃爍
case 5:display(0x20,0xbf);break; //顯示 -
case 6:display(0x40,seven_seg[hour_n%10]);break; //顯示鬧時個位
case 7:display(0x80,seven_seg[hour_n/10]);break; //顯示鬧時十位
}
}