本帖最后由 半导体 于 2016-9-23 22:44 编辑
简介:
前几天在坛里分享的
MultiButton按键模块看到大家对此感兴趣,这让我备受鼓舞!今天分享的是一个简易的软件定时器模块,跟MultiButton一样使用单向链表串连管理同样的套路。
这种类似的软件定时器模块其实在很多SOC的SDK上都已经有自带的API接口了,但很多工程师在裸机上开发还是习惯使用判断定时变量计数或标志位的方式去传递执行一些定时任务,
虽然这种方式简单高效,但随着工程增大会出现满天飞的定时全局变量和标志位,加大了各代码段之间的耦合程度,并且很不优雅。
MultiTimer 是一个软件定时器扩展模块,可无限扩展你所需的定时器任务,取代传统的标志位判断方式, 更优雅更便捷地管理程序的时间触发时序。
使用方法:
1.先申请一个定时器管理handle:
struct Timer timer1;
2.初始化定时器对象,注册定时器回调处理函数,设置定时时间(ms),循环定时触发时间:
timer_init(struct Timer* handle, void(*timeout_cb)(), uint32_t timeout, uint32_t repeat);
3.启动定时器
timer_start(&timer1);
4.设置1ms的硬件定时器循环调用 timer_ticks() 以提供时间基准
void HAL_SYSTICK_Callback(void)
{
timer_ticks();
}
5.在主循环调用定时器后台处理函数
int main()
{
while(1) {
...
timer_loop();
}
}
例程:- #include "multi_timer.h"
- struct Timer timer1;
- struct Timer timer2;
- void timer1_callback()
- {
- printf("timer1 timeout!
");
- }
- void timer2_callback()
- {
- printf("timer2 timeout!
");
- }
- int main()
- {
- timer_init(&timer1, timer1_callback, 1000, 0); //1s delay
- timer_start(&timer1);
-
- timer_init(&timer2, timer2_callback, 50, 50); //50ms loop
- timer_start(&timer2);
-
- while(1) {
-
- timer_loop();
- }
- }
- void HAL_SYSTICK_Callback(void)
- {
- timer_ticks(); //1ms ticks
- }
复制代码
模块下载地址:
https://github.com/0x1abin/MultiTimer
(注:使用github的原因是我后面的一些改动能够及时更新,附件没法及时更新)
1.
时钟计数值_timer_ticks是32位无符号数,在51类单片机下读取时不是原子操作,读取时可能中断发生,导致读取到的数值出错,此时运行timer_loop()函数肯定会出错!
建议加入_timer_ticks读取保护措施!
2.
timer_loop()函数中判断超时部分可能出错:
由程序中判断语句 if(_timer_ticks >= target->timeout)可知,超时与否仅仅根据_timer_ticks 值的大小比较,当_timer_ticks 发生溢出时可能出错。
你能保证单个定时器模块的回调函数运行时间在1个ticks内,但如果多个回调函数刚好同时运行在单次调用timer_loop()时,总运行时间可能超出1个ticks,
甚至达到2~3个ticks。比如我们经常延时5ms,10ms,20ms,50ms等,当ticks=100ms时,可能要运行4个回调函数。
如果此时某个target->timeout=0xFFFFFFFF,而在_timer_ticks = 0xFFFFFFFF时恰好因为延误未调用到此模块,当_timer_ticks = 0 反转后,此回调函数再想运行就要等到猴年马月了!
一周热门 更多>