<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 關于51單片機定時器的靈活使用

          關于51單片機定時器的靈活使用

          作者: 時間:2016-11-20 來源:網(wǎng)絡 收藏
          前段時間,做一個項目,有串口收發(fā)指令判斷,按鍵類型判斷,長短按之類,power的定時關電,事件的輪詢掃描更新和display的定時掃描。這些要求就對定時器提出了要求,但是我的51單片機只有兩個定時器,其中一個又有debug口的波特率產(chǎn)生之用。于是乎我可以用的定時器就只剩下了一個。怎么辦?可能大家都只能用變量在定時中斷函數(shù)去做多了任務就行了,但是我總是感覺這樣會導致代碼看起來太不具有條理性,而且對于日后的管理不是很容易。思來想去,就想到了linux內(nèi)核中對于定時器的封裝,那種面向對象的思想。

          本文引用地址:http://www.ex-cimer.com/article/201611/318667.htm

          想法有了,我覺得實現(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; itimerId >= 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)是否有按鍵按下,并判斷其類型。

          望有改進意見,謝謝高手指正。



          評論


          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();