關于51單片機定時器的靈活使用
想法有了,我覺得實現(xiàn)就是很簡單了。下面給大家貼上我的代碼:
.h 文件:
#ifndef __SC_TIMER_H#define __SC_TIMER_H/* SC_Common.h文件中包含了對數(shù)據(jù)類型的定義和包含對應的單片機的配置頭文件,這里就沒有列出,根據(jù)個人所使用情況而定 */#include "SC_Common.h"#ifdef MODE1T#define T0TIMES (65536-FOSC/1000)#define T1TIMES (65536-10*FOSC/1000)#else#define T0TIMES (65536-FOSC/12/1000) // 0.1ms#define T1TIMES (65536-10*FOSC/12/1000) // 10ms#endif /*MODE1T*/#define TIMER_SIZE 4typedef struct{U8 timerId; /* 定時器的id,實則指明了起所在數(shù)組中的位置 */S8 isRuning; /* 表明當前timer是否正在運行 */U16 curTimes; /* 當前timer時間 */U16 expireTimes; /* 當前timer的溢出時間 */U8 existInArry; /* 當前的timer是否存在于數(shù)組之中 */TimerFunc timerFunc; /* 當前timer的指定運行函數(shù) */} Timer;void InitTimer(void);S8 AddTimer(Timer *timer);S8 DelTimer(Timer *timer);S8 StartTimer(Timer *timer);S8 ModifyTimer(Timer *timer);S8 StopTimer(Timer *timer);S8 IsRunningTimer(Timer *timer);#endif /*__SC_TIMER_H*/
下面是這部分思想的重點實現(xiàn),無非就是向timerArray數(shù)組中添加刪除定時器,簡言之,即所謂的增刪改查,還有就是啟動停止定時器,考慮到51單片機的性能,沒有像linux內(nèi)核中那樣用鏈表實現(xiàn),同時定時器的總數(shù)也是有上限要求的。
.c文件:
#include "SC_Timer.h"#include#include /* 這里采用數(shù)組的方式管理各個timer結構體 */Timer timerArray[TIMER_SIZE];U8 timerUsed = 0;void InitTimer(void){TMOD |= 0x01;TL0 = T0TIMES;TH0 = T0TIMES >> 8;ET0 = 1;TR0 = 1;timerUsed = 0;memset(timerArray, 0, sizeof(timerArray));}S8 AddTimer(Timer *timer){if(timerUsed >= TIMER_SIZE)timerUsed = 0;/*×Ô¶šÒåtimerIdµÄÉú³É·œÊœ¬Œ??ú±íÆäÔÚÊý×éÖеÄλÖÃ*/timer->timerId = timerUsed;timerArray[timerUsed] = *timer;timerUsed++;timer->existInArry = 1;timer->isRuning = 0;printf("%bun", timer->timerId);return 0;}static void Del_Timer(Timer *timerArray, U8 *timerUsed, U8 pos){U8 i = 0;U8 len = *timerUsed;for(i=pos; i timerId >= TIMER_SIZE || timer->timerId < 0 || timer->existInArry == 0)return -1;if(timerUsed <= 0)return -1;Del_Timer(timerArray, &timerUsed, timer->timerId);timer->existInArry = 0;return 0;}S8 StartTimer(Timer *timer){if(timer->timerId >= TIMER_SIZE || timer->timerId < 0 || timer->existInArry == 0)return -1;timerArray[timer->timerId].isRuning = 1;return 0;}S8 ModifyTimer(Timer *timer){if(timer->timerId >= TIMER_SIZE || timer->timerId < 0 || timer->existInArry == 0)return -1;timerArray[timer->timerId].curTimes = timer->curTimes;timerArray[timer->timerId].expireTimes = timer->expireTimes;timerArray[timer->timerId].timerFunc = timer->timerFunc;return 0; }S8 StopTimer(Timer *timer){if(timer->timerId >= TIMER_SIZE || timer->timerId < 0 || timer->existInArry == 0)return -1;timerArray[timer->timerId].isRuning = 0;return 0;}S8 IsRunningTimer(Timer *timer){S8 ret = -1;if(timer->timerId >= TIMER_SIZE || timer->timerId < 0 || timer->existInArry == 0)return ret;ret = timerArray[timer->timerId].isRuning;return ret;}/* * 定時器的中斷函數(shù)負責判斷各個事件的時間是否到達,如果到達調(diào)用相應的相應函數(shù)進行運行* 由于51單片機的函數(shù)指針是沒有堆棧保護的,所以這里加入了匯編指令執(zhí)行堆棧的保護,個人* 水平有限,這里希望大家指正是否有錯誤之處,謝謝*/void Tm0Isr(void) interrupt 1{ U8 i = 0;TL0 = T0TIMES;TH0 = T0TIMES >> 8;for(i=0; i = timerArray[i].expireTimes){#pragma asmpush ACCpush DPHpush DPL#pragma endasm(*timerArray[i].timerFunc)();#pragma asmpop DPLpop DPHpop ACC#pragma endasmtimerArray[i].curTimes = 0;}}}}
本文中的數(shù)據(jù)類型都是通過typedef轉化過的,為了時時刻刻關于自己的內(nèi)存使用量,,定義如下
typedef unsigned char U8;typedef unsigned short int U16;typedef unsigned long int U32;typedef signed char S8;typedef signed short int S16;typedef signed long int S32;typedef bit BOOL;
個人認為這個對于項目后面的能夠有效快速的進行起到了很大的幫助。 典型的用法如下:
Timer pressKeyTimer; /* 這里的timer請使用全局變量,大家應該懂的,就是變量的生命周期的問題啦 */pressKeyTimer.curTimes = 0;pressKeyTimer.expireTimes = 11;pressKeyTimer.timerFunc = JudgeKeyType;AddTimer(&pressKeyTimer);StartTimer(&pressKeyTimer);
至此,到規(guī)定的時間11msec時,就會調(diào)用這里的JudeKeyType函數(shù),進行輪詢發(fā)現(xiàn)是否有按鍵按下,并判斷其類型。
望有改進意見,謝謝高手指正。
評論