1.使用定时器T0,动态显示数码管数字,
T0 到达则显示一个数字
2.对秒信号计数方式来计时,而且不使用外部中断。
3.对外引脚脉冲计数,也不使用外部中断
这样可以避免按键时阻塞进程,使动态显示分时不均
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include "reg52.h" //包含stc15w401单片机的头文件
- #include "defType.h"
- #define MOD_NORMAL 0
- #define MOD_COUNT 1
- #define MOD_SETALARM 2
- //the set BUTTON
- #define P_LED P1
- #define P_WEI P3
- sbit P_MINUTE_UP =P3^0;
- sbit P_HOUR_UP =P3^1;
- sbit P_SEC =P3^2;
- sbit P_CNT =P3^3;
- sbit P_MOD =P2^0;
- sbit P_ALARM =P2^1;
- //p3.0- p3.7 to link to LED‘s a to h,0-9
- u8 code segCode[17]={0xC0,0xF9,0xA4,0xB0,0x99,
- 0x92,0x82,0xF8,0x80,0x90,0xff,//
- 0xa7,0xab,0x87,//cnt, counter mode
- 0x88,0xc7,0x88};//ala,set alarm mode
-
- #define SET_M_BUF(m) dspBuf[0]= m%10; \
- dspBuf[1]= m/10
- #define SET_H_BUF(h) if(h<10) \
- { dspBuf[2]= h;dspBuf[3]= 10;} \
- else \
- { dspBuf[2]= h%10;dspBuf[3]= h/10;}
- #define UP_MINUTE(m) m++; \
- if(m>59) m= 0; \
- SET_M_BUF(m)
- #define UP_HOUR(h) h++; \
- if(h>23) h=0; \
- SET_H_BUF(h)
- #define ZERO_BUF dspBuf[0]= 0; \
- dspBuf[1]= 0; \
- dspBuf[2]= 0; \
- dspBuf[3]= 0
- //current time and alarm time
- u8 minute= 3, hour=2;
- u8 a_minute=0, a_hour=0;
- ///////////////////////////////
- u8 dspBuf[4];
- u8 i= 0, mode= MOD_NORMAL;
- u16 sec=0, count=0;
- u8 oldSec=0, oldCnt=0;
- u8 sec5=0; //when setting alarm, if no key down for 5 sec,alarm is seted
- bool alarmSeted = 0;
- void flashDot()
- {
- if(P_SEC)
- P_LED&= 0x7f;
- }
- void modeDisplay()
- {
- if(mode== MOD_NORMAL)
- {
- SET_M_BUF(minute);
- SET_H_BUF(hour);
- }
- else
- {
- dspBuf[0]= 10; //no display
- dspBuf[1]= 10+3*mode; // '-'
- dspBuf[2]= 9+3*mode;
- dspBuf[3]= 8+3*mode; // '-'
- }
- }
- void counting()
- {
- if(oldCnt== P_CNT)
- return;
- count++; \
- if(count>9999) count= 0;
- SET_M_BUF(count%100); \
- SET_H_BUF(count/100);
- oldCnt= P_CNT;
- }
- void timing() //INT0_INTERRUPT using 0
- {
- if(oldSec== P_SEC)
- return;
- oldSec= P_SEC;
-
- //seting alarm,
- //if no button press over 5 second
- //alarm is seted
- //else alarm will cancle
- if( mode == MOD_SETALARM )
- {
- sec5++;
- if(sec5> 10)
- {
- alarmSeted= 1;
- mode= MOD_NORMAL;
- modeDisplay();
- sec5=0;
- }
- }
-
- sec++;
- if(sec> 119)
- {
- sec= 0;
- minute++;
- if(minute> 59)
- {
- minute= 0;
- hour++;
- if(hour>23) hour=0;
- if(mode== MOD_NORMAL) //normal mod or is alarm mod
- {
- SET_H_BUF(hour);
- }
-
- }
-
- //check alarm every minute
- P_ALARM= 0;
- if( alarmSeted && (minute== a_minute ) && (hour==a_hour) )
- P_ALARM= 1;
-
- if(mode== MOD_NORMAL)
- {
- SET_M_BUF(minute);
- }
-
- }
-
- }
- void display() T0_INTERRUPT using 0
- {
- T0_Stop;
-
- P3&= 0x0f;
- P_WEI |=(0x10<<i);
- P_LED= segCode[dspBuf[i] ];
-
- if(i==2)
- {
- if(mode== MOD_NORMAL)
- flashDot();
- if(mode==MOD_SETALARM)
- P_LED&= 0x7f;
- }
- i++;
- if(i>3)
- {
- i=0;
- timing();
- if(mode== MOD_COUNT)
- counting();
- }
- T0_Load(4000);
- T0_Run;
- }
- void main(void)
- {
- //T0 use to display
- T0_16bit;
- T0_Load(5000);
- T0_PolityHigh;
- T0_Enable;
- T0_Run; //
-
- //
- EnableAllInt;
- SET_H_BUF(hour);
- SET_M_BUF(minute);
- P_ALARM= 0;
- while(1)
- {
-
- KeyPress(P_MOD,{
- mode++;
- if(mode> MOD_SETALARM)
- {
- alarmSeted=0;
- P_ALARM= 0;
- mode= MOD_NORMAL;
- }
- modeDisplay();
- });
- KeyPress(P_MINUTE_UP,
- {
- switch(mode){
- case MOD_NORMAL:
- SET_H_BUF(hour);
- UP_MINUTE(minute);
- break;
- case MOD_SETALARM:
- UP_MINUTE(a_minute);
- SET_H_BUF(a_hour);
- if(i==2) P_LED&= 0x7f;//disply dot
- sec5= 0;
- break;
- case MOD_COUNT:
- count= 0;
- ZERO_BUF;
-
- break;
- }
- });
- KeyPress(P_HOUR_UP , {
- switch(mode){
- case MOD_NORMAL:
- SET_M_BUF(minute);
- UP_HOUR(hour);
- break;
- case MOD_SETALARM:
- SET_M_BUF(a_minute);
- UP_HOUR(a_hour);
-
- sec5= 0;
- break;
-
- }
- });
- }
- }
复制代码
仿真Keil代码下载,请大家多多指教:
cnttm.rar
(30.65 KB, 下载次数: 11)
|