關(guān)于51單片機(jī)定時(shí)器的靈活使用
想法有了,我覺得實(shí)現(xiàn)就是很簡單了。下面給大家貼上我的代碼:
.h 文件:
#ifndef __SC_TIMER_H#define __SC_TIMER_H/* SC_Common.h文件中包含了對(duì)數(shù)據(jù)類型的定義和包含對(duì)應(yīng)的單片機(jī)的配置頭文件,這里就沒有列出,根據(jù)個(gè)人所使用情況而定 */#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; /* 定時(shí)器的id,實(shí)則指明了起所在數(shù)組中的位置 */S8 isRuning; /* 表明當(dāng)前timer是否正在運(yùn)行 */U16 curTimes; /* 當(dāng)前timer時(shí)間 */U16 expireTimes; /* 當(dāng)前timer的溢出時(shí)間 */U8 existInArry; /* 當(dāng)前的timer是否存在于數(shù)組之中 */TimerFunc timerFunc; /* 當(dāng)前timer的指定運(yùn)行函數(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*/
下面是這部分思想的重點(diǎn)實(shí)現(xiàn),無非就是向timerArray數(shù)組中添加刪除定時(shí)器,簡言之,即所謂的增刪改查,還有就是啟動(dòng)停止定時(shí)器,考慮到51單片機(jī)的性能,沒有像linux內(nèi)核中那樣用鏈表實(shí)現(xiàn),同時(shí)定時(shí)器的總數(shù)也是有上限要求的。
.c文件:
#include "SC_Timer.h"#include#include /* 這里采用數(shù)組的方式管理各個(gè)timer結(jié)構(gòu)體 */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í)器的中斷函數(shù)負(fù)責(zé)判斷各個(gè)事件的時(shí)間是否到達(dá),如果到達(dá)調(diào)用相應(yīng)的相應(yīng)函數(shù)進(jìn)行運(yùn)行* 由于51單片機(jī)的函數(shù)指針是沒有堆棧保護(hù)的,所以這里加入了匯編指令執(zhí)行堆棧的保護(hù),個(gè)人* 水平有限,這里希望大家指正是否有錯(cuò)誤之處,謝謝*/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轉(zhuǎn)化過的,為了時(shí)時(shí)刻刻關(guān)于自己的內(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;
個(gè)人認(rèn)為這個(gè)對(duì)于項(xiàng)目后面的能夠有效快速的進(jìn)行起到了很大的幫助。 典型的用法如下:
Timer pressKeyTimer; /* 這里的timer請使用全局變量,大家應(yīng)該懂的,就是變量的生命周期的問題啦 */pressKeyTimer.curTimes = 0;pressKeyTimer.expireTimes = 11;pressKeyTimer.timerFunc = JudgeKeyType;AddTimer(&pressKeyTimer);StartTimer(&pressKeyTimer);
至此,到規(guī)定的時(shí)間11msec時(shí),就會(huì)調(diào)用這里的JudeKeyType函數(shù),進(jìn)行輪詢發(fā)現(xiàn)是否有按鍵按下,并判斷其類型。
望有改進(jìn)意見,謝謝高手指正。
評(píng)論