×
嵌入式 > 技术百科 > 详情

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

发布时间:2020-06-12 发布时间:
|

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

 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 }











『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
FPGA及CPLD应用领域不断拓展