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