当前位置:首页 > 单片机 > 单片机
[导读]前段时间把自己以前用的单片机定时器整理出来,我称之为简单定时器,这种简单定时器比较适合定时器使用量少的程序中,如果定时器数量要求多,精度要求高,效率就会有问题,为此,俺就实现了一个时间轮定时器,简单测

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

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 ret

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭