單片機(jī)定時(shí)器之改良版:時(shí)間輪定時(shí)器
掃描二維碼
隨時(shí)隨地手機(jī)看文章
前段時(shí)間把自己以前用的單片機(jī)定時(shí)器整理出來(lái),我稱(chēng)之為簡(jiǎn)單定時(shí)器,這種簡(jiǎn)單定時(shí)器比較適合定時(shí)器使用量少的程序中,如果定時(shí)器數(shù)量要求多,精度要求高,效率就會(huì)有問(wèn)題,為此,俺就實(shí)現(xiàn)了一個(gè)時(shí)間輪定時(shí)器,簡(jiǎn)單測(cè)試下來(lái)效果非常不錯(cuò)。
1 #ifndef __SOFT_TIMER_H__
2 #define __SOFT_TIMER_H__
3
4 #define EVENT_TYPE_ONESHOT 0
5 #define EVENT_TYPE_PERIODIC 1
6
7 #define TMR_POOL_SIZE 20 // 定時(shí)器池,即可用定時(shí)器個(gè)數(shù)
8 #define TMR_WHEEL_SIZE 8 // 時(shí)間輪的粒度
9
10 #define HANDLE int
11
12 typedef void (*pTimerProc)(void*);
13
14 void TimerInit(void);
15 HANDLE SetTimer(unsigned long uElapse,pTimerProc pFunc,void *para,unsigned int Tmr_type);
16 void KillTimer(HANDLE hTmr);
17 void TimerServer(void); // call in main loop
18 void TimerSignal(void); // call it in timer isr
19 unsigned long TmrGetTime(void);
20
21 #endif
簡(jiǎn)單介紹一下:
SetTimer():參數(shù)uElapse:定時(shí)器超時(shí)時(shí)間.參數(shù)pFunc:定時(shí)器超時(shí)回調(diào)函數(shù).參數(shù)para:定時(shí)器超時(shí)回調(diào)函數(shù)參數(shù).參數(shù)Tmr_type:定時(shí)器類(lèi)型,EVENT_TYPE_ONESHOT為單次定時(shí)器,定時(shí)器超時(shí)后,會(huì)被自動(dòng)刪除.EVENT_TYPE_PERIODIC表示周期性定時(shí)器,使用完后需主動(dòng)刪除。返回值:返回定時(shí)器id,用于刪除定時(shí)器。KillTimer():刪除由SetTimer()創(chuàng)建的定時(shí)器。
TimerServer():定時(shí)器管理函數(shù),需在主循環(huán)中調(diào)用。
TimerSignal():定時(shí)器信號(hào)函數(shù),提供定時(shí)器運(yùn)行所需節(jié)拍數(shù),需在硬件定時(shí)器中斷中調(diào)用,例如,硬件定時(shí)器10ms中斷一次,在中斷中調(diào)用TimerSignal(),則時(shí)間輪定時(shí)器的節(jié)拍時(shí)間為10ms.
TmrGetTime():記錄定時(shí)器的節(jié)拍數(shù)
1 #include "timer.h"
2
3 typedef struct _tagTimer{
4 unsigned int elapse;
5 unsigned int interval;
6 void *prev;
7 void *next;
8 TimerProc pFunc;
9 void *para;
10 unsigned char state;
11 unsigned char event_type;
12 unsigned char timeout;
13 }Timer_Typedef;
14
15 typedef struct _tagTimerWheel{
16 Timer_Typedef *pFirst;
17 unsigned int entries;
18 }TimerWheel_Typedef;
19
20 #define TMR_STATE_FREE 0
21 #define TMR_STATE_STOP 1
22 #define TMR_STATE_RUNNING 3
23
24 static Timer_Typedef _timerArray[TMR_POOL_SIZE]={0};
25 static TimerWheel_Typedef TmrWheel[TMR_WHEEL_SIZE]={0};
26 static Timer_Typedef* tmr_free_list;
27 static unsigned tmr_free_slot = 0;
28 static unsigned _tmr_tick = 0;
29
30
31 static Timer_Typedef* Tmr_alloc(void);
32 static void Tmr_free(Timer_Typedef* pTmr);
33 static void Tmr_link(Timer_Typedef* pTmr);
34 static void Tmr_unlink(Timer_Typedef* pTmr);
35
36
37 void TimerInit(void)
38 {
39 int i = 0;
40 for(i=0;i 41 { 42 _timerArray[i].next = (void*)(&_timerArray[i+1]); 43 } 44 _timerArray[TMR_POOL_SIZE-1].next = (void*)0; 45 tmr_free_list = _timerArray; 46 tmr_free_slot = TMR_POOL_SIZE; 47 48 for(i=0;i 49 { 50 TmrWheel[i].pFirst = (void*)0; 51 TmrWheel[i].entries = 0; 52 } 53 } 54 55 HANDLE SetTimer(unsigned long uElapse,TimerProc pFunc,void *para,unsigned int Tmr_type) 56 { 57 int unused_slot = -1; 58 Timer_Typedef *pTmr = (Timer_Typedef *)0; 59 60 pTmr = Tmr_alloc(); 61 if(pTmr) unused_slot = pTmr - _timerArray; 62 63 if(unused_slot != -1) 64 { 65 _timerArray[unused_slot].pFunc = pFunc; 66 _timerArray[unused_slot].para = para; 67 _timerArray[unused_slot].interval = uElapse; 68 _timerArray[unused_slot].event_type = Tmr_type; 69 _timerArray[unused_slot].state = 1; 70 Tmr_link(pTmr); 71 } 72 return unused_slot; 73 } 74 75 void KillTimer(HANDLE hTmr) 76 { 77 if((hTmr >= 0)&&(hTmr < TMR_POOL_SIZE)) 78 { 79 switch(_timerArray[hTmr].state) 80 { 81 case TMR_STATE_STOP: 82 Tmr_free(&_timerArray[hTmr]); 83 break; 84 case TMR_STATE_RUNNING: 85 Tmr_unlink(&_timerArray[hTmr]); 86 Tmr_free(&_timerArray[hTmr]); 87 break; 88 default: 89 break; 90 } 91 _timerArray[hTmr].timeout = 0; 92 } 93 } 94 95 void TimerServer(void) 96 { 97 int i = 0; 98 Timer_Typedef* pTmr = _timerArray; 99 for(i = 0;i 100 { 101 if((pTmr->timeout)&&(pTmr->pFunc)) 102 { 103 (*(pTmr->pFunc))(pTmr->para); 104 pTmr->timeout = 0; 105 } 106 pTmr++; 107 } 108 } 109 110 111 void TimerSignal(void) 112 { 113 int spoke = 0; 114 Timer_Typedef* pTmr,*pNext; 115 116 ++_tmr_tick; 117 spoke = _tmr_tick%TMR_WHEEL_SIZE; 118 pTmr = TmrWheel[spoke].pFirst; 119 while(pTmr) 120 { 121 pNext = pTmr->next; 122 if(pTmr->elapse == _tmr_tick) 123 { 124 Tmr_unlink(pTmr); 125 if(pTmr->event_type == EVENT_TYPE_PERIODIC) 126 { 127 Tmr_link(pTmr); 128 } 129 else 130 { 131 Tmr_free(pTmr); 132 } 133 pTmr->timeout = 1; 134 } 135 pTmr = pNext; 136 } 137 } 138 139 static void Tmr_link(Timer_Typedef* pTmr) 140 { 141 int spoke; 142 TimerWheel_Typedef *pWhl; 143 pTmr->state = TMR_STATE_RUNNING; 144 pTmr->elapse = pTmr->interval + _tmr_tick; 145 spoke = pTmr->elapse%TMR_WHEEL_SIZE; 146 pWhl = &TmrWheel[spoke]; 147 148 if(pWhl->pFirst) pWhl->pFirst->prev = pTmr; 149 150 pTmr->next = pWhl->pFirst; 151 pWhl->pFirst = pTmr; 152 pWhl->entries++; 153 } 154 155 static void Tmr_unlink(Timer_Typedef* pTmr) 156 { 157 int spoke; 158 TimerWheel_Typedef *pWhl; 159 pTmr->state = TMR_STATE_STOP; 160 spoke = pTmr->elapse%TMR_WHEEL_SIZE; 161 pWhl = &TmrWheel[spoke]; 162 163 if(pWhl->pFirst == pTmr) 164 { 165 pWhl->pFirst = pTmr->next; 166 if(pTmr->next) ((Timer_Typedef*)pTmr->next)->prev = (void*)0; 167 } 168 else 169 { 170 ((Timer_Typedef*)pTmr->prev)->next = pTmr->next; 171 if(pTmr->next) ((Timer_Typedef*)pTmr->next)->prev = pTmr->prev; 172 } 173 pWhl->entries--; 174 } 175 176 177 static Timer_Typedef* Tmr_alloc(void) 178 { 179 Timer_Typedef *pTmr = (Timer_Typedef*)0; 180 if(tmr_free_list) 181 { 182 pTmr = tmr_free_list; 183 tmr_free_list = tmr_free_list->next; 184 tmr_free_slot--; 185 } 186 return pTmr; 187 } 188 189 190 191 static void Tmr_free(Timer_Typedef* pTmr) 192 { 193 pTmr->state = TMR_STATE_FREE; 194 pTmr->prev = (Timer_Typedef*)0; 195 pTmr->next = tmr_free_list; 196 tmr_free_list = pTmr; 197 tmr_free_slot++; 198 } 199 200 unsigned long TmrGetTime(void) 201 { 202 ret