前段时间把自己以前用的单片机定时器整理出来,我称之为简单定时器,这种简单定时器比较适合定时器使用量少的程序中,如果定时器数量要求多,精度要求高,效率就会有问题,为此,俺就实现了一个时间轮定时器,简单测试下来效果非常不错。
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 // 定时器池,即可用定时器个数
8 #define TMR_WHEEL_SIZE 8 // 时间轮的粒度
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
简单介绍一下:
SetTimer(): 参数uElapse:定时器超时时间. 参数pFunc:定时器超时回调函数. 参数para:定时器超时回调函数参数.参数Tmr_type:定时器类型,EVENT_TYPE_ONESHOT为单次定时器,定时器超时后,会被自动删除.EVENT_TYPE_PERIODIC 表示周期性定时器,使用完后需主动删除。 返回值:返回定时器id,用于删除定时器。 KillTimer(): 删除由SetTimer()创建的定时器。
TimerServer(): 定时器管理函数,需在主循环中调用。
TimerSignal(): 定时器信号函数,提供定时器运行所需节拍数,需在硬件定时器中断中调用,例如,硬件定时器10ms中断一次,在中断中调用TimerSignal(),则时间轮定时器的节拍时间为10ms.
TmrGetTime():记录定时器的节拍数
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 return _tmr_tick;
203 }
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』