单片机定时器之改良版:时间轮定时器

前段时间把自己以前用的单片机定时器整理出来,我称之为简单定时器,这种简单定时器比较适合定时器使用量少的程序中,如果定时器数量要求多,精度要求高,效率就会有问题,为此,俺就实现了一个时间轮定时器,简单测试下来效果非常不错。

 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<TMR_POOL_SIZE-1;++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<TMR_WHEEL_SIZE;++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<TMR_POOL_SIZE;++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 }

 




 

posted @ 2014-09-27 21:11  西瓜大叔  阅读(672)  评论(0编辑  收藏  举报