搜索
查看: 6245|回复: 14

[原创] 【开源】软件定时器

[复制链接]

该用户从未签到

35

主题

458

帖子

93

蝴蝶豆

版主

最后登录
2020-9-9
发表于 2017-7-20 19:23:21 | 显示全部楼层 |阅读模式
本帖最后由 Inc_brza 于 2017-7-20 19:25 编辑

前言:这里不谈RTOS,而是主要针对裸机开发,很多时候,我们发现硬件定时器是不够用的,于是乎,很多时候,
程序员都会利用一个硬件定时器来产生N个软件定时器,误差是肯定有的,但是误差范围是可接受的,这样,
就能解决了很多时候定时器不够用的场合。
当然,楼主也遇到这种时候,所以就临时写了个软件定时器。

主题:这个软甲定时器采用了数组+回调的机制,硬件定时器产生tick,而主循环中获取tick产生计数,计数到达之后
调用定时器对应的回调函数。其中包含删除,注册的功能。

数据结构
  1. typedef struct soft_timer {
  2.     uint32_t timer_count;      //定时器用的计数器
  3.     uint32_t time_out;           //阀值
  4.     void (*time_out_callback)(void *param); //回调函数
  5.     void *param; //回调函数参数
  6.     uint8_t timer_flag; //定时器属性标志
  7. }soft_timer_t;
复制代码
原理很简单,主循环timer_count不断的自减,到0的时候就调用一次函数,不停循环。
  1. <blockquote>/*
复制代码
以上是使用到的api接口,分别是注册,删除,初始化,中断调用,主循环任务函数,
一下是源码:
  1. /*
  2. * !brief include header
  3. */
  4. #include <stdint.h>
  5. #include "soft_timer.h"


  6. #ifndef NULL
  7. #define NULL ((void *)0)
  8. #endif



  9. /*
  10. * !brief
  11. */
  12. static uint8_t exec_run_flag;

  13. /*
  14. * !brief timer_list, you can change the timers num by SOFT_TIMERS_MAX
  15. */
  16. static soft_timer_t timer_list[SOFT_TIMERS_MAX];

  17. /*
  18. * !brief module init, you can run this function in first main
  19. */
  20. void soft_timer_init(void)
  21. {
  22.     uint8_t i;
  23.     for (i = 0; i < SOFT_TIMERS_MAX; i++) {
  24.         timer_list[i].timer_count = 0;
  25.         timer_list[i].timer_flag = 0;
  26.         timer_list[i].time_out = 0;
  27.         timer_list[i].time_out_callback = NULL;
  28.         timer_list[i].param = NULL;
  29.     }
  30. }

  31. /*
  32. * !brief use this function to create a soft_timer
  33. * !param first time the timer count machine's period
  34. * !param every loop cycles
  35. * !param callback run with the time up
  36. * !param callback 's param
  37. * !param 0:periods 1:one shot
  38. * !retval timer handle
  39. */
  40. soft_timer_handle_t soft_timer_registered(uint32_t first_timer_period,
  41.                                           uint32_t period,
  42.                                           timer_out_callback *callback,
  43.                                           void *callback_param,
  44.                                           uint8_t flag)
  45. {
  46.     uint8_t i;
  47.    
  48.     if (callback == NULL) return NULL;
  49.    
  50.     for (i = 0; i < SOFT_TIMERS_MAX; i++) {
  51.         if (timer_list[i].time_out_callback != NULL) continue;
  52.         timer_list[i].timer_count = first_timer_period;
  53.         timer_list[i].time_out = period;
  54.         timer_list[i].time_out_callback = callback;
  55.         timer_list[i].param = callback_param;
  56.         timer_list[i].timer_flag = flag;
  57.         break;
  58.     }
  59.    
  60.     return (soft_timer_handle_t)&timer_list[i];
  61. }

  62. /*
  63. * !brief you can use this function to delete a soft_timer
  64. * !param timer handle
  65. * !retval 0 is successful, 1 is fail
  66. */
  67. int soft_timer_delete(soft_timer_handle_t handle)
  68. {
  69.     soft_timer_t *p = (soft_timer_t *)handle;
  70.    
  71.    
  72.     if (p == NULL) return 1;
  73.     p->time_out_callback = NULL;
  74.    
  75.     return 0;
  76. }

  77. /*
  78. * !brief you should run this function in a hardware timer interrupt
  79. *        it can provide ticks for soft_timer
  80. */
  81. void soft_timer_interrupt(void)
  82. {
  83.     if (exec_run_flag < 100)
  84.         exec_run_flag ++;
  85. }

  86. /*
  87. * !brief you should run this function in main loop
  88. */
  89. void soft_timer_exec(void)
  90. {
  91.     uint8_t i;
  92.    
  93.     if (exec_run_flag == 0) return;
  94.     exec_run_flag --;
  95.     for (i = 0; i < SOFT_TIMERS_MAX; i ++) {
  96.         if (timer_list[i].time_out_callback == NULL) continue;
  97.         if (timer_list[i].timer_count) {
  98.             timer_list[i].timer_count --;
  99.         } else {
  100.             timer_list[i].time_out_callback(timer_list[i].param);
  101.             if (!timer_list[i].timer_flag) {
  102.                 timer_list[i].timer_count = timer_list[i].time_out;
  103.             } else {    //one shot
  104.                 timer_list[i].time_out_callback = NULL;
  105.             }
  106.         }
  107.     }
  108. }
复制代码
总结,虽然误差是肯定有的,但是由于误差可接受,所以用起来还是很方便的,如果哪里写的不好,还请给点意见!

评分

参与人数 1ST金币 -1 收起 理由
wxl0704010220-3 -1 神马都是浮云

查看全部评分

回复

使用道具 举报

该用户从未签到

29

主题

1285

帖子

59

蝴蝶豆

论坛元老

最后登录
2021-6-27
发表于 2017-7-20 19:54:15 | 显示全部楼层
谢谢分享         
回复 支持 反对

使用道具 举报

该用户从未签到

60

主题

2111

帖子

31

蝴蝶豆

版主

最后登录
2023-6-21
发表于 2017-7-20 21:26:40 | 显示全部楼层
感谢分享!
回复

使用道具 举报

该用户从未签到

2

主题

17

帖子

0

蝴蝶豆

中级会员

最后登录
2020-6-26
发表于 2017-7-21 08:30:55 | 显示全部楼层
标记收藏!
回复

使用道具 举报

该用户从未签到

3

主题

1002

帖子

363

蝴蝶豆

版主

最后登录
2021-4-15
发表于 2017-7-21 10:16:18 | 显示全部楼层
总体来说就是时间片!!!!当然了也相当于一个调度系统。。。。只是这里的打断要自己主动让出MCU!!!
回复 支持 反对

使用道具 举报

该用户从未签到

35

主题

458

帖子

93

蝴蝶豆

版主

最后登录
2020-9-9
 楼主| 发表于 2017-7-21 10:38:21 | 显示全部楼层
MrJiu 发表于 2017-7-21 10:16
总体来说就是时间片!!!!当然了也相当于一个调度系统。。。。只是这里的打断要自己主动让出MCU!!!; ...

定时器的中断周期一般是1ms,也就是这个软件定时器的误差是毫秒级的,中断的处理很短基本可以忽略,主要其他任务不阻塞,还是很准确的。
回复 支持 反对

使用道具 举报

该用户从未签到

7

主题

126

帖子

80

蝴蝶豆

金牌会员

最后登录
2021-4-6
发表于 2017-7-21 12:09:28 | 显示全部楼层
把count--换成直接对比比较好,count--需要读内存,减一,放回内存,比较四步,直接对比只需要读内存,比较两步。直接比较就是当前tick+定时tick而已
回复 支持 反对

使用道具 举报

该用户从未签到

35

主题

458

帖子

93

蝴蝶豆

版主

最后登录
2020-9-9
 楼主| 发表于 2017-7-21 12:27:06 | 显示全部楼层
Dandjinh 发表于 2017-7-21 12:09
把count--换成直接对比比较好,count--需要读内存,减一,放回内存,比较四步,直接对比只需要读内存,比较 ...

你的意思是把tick当成所有的计数器?如果这样子,定时器之间就不能相互独立了
回复 支持 反对

使用道具 举报

该用户从未签到

7

主题

126

帖子

80

蝴蝶豆

金牌会员

最后登录
2021-4-6
发表于 2017-7-21 12:40:53 | 显示全部楼层
Inc_brza 发表于 2017-7-21 12:27
你的意思是把tick当成所有的计数器?如果这样子,定时器之间就不能相互独立了 ...

定义个全局tick,定时加一,作为标准,定时器触发的标准就是注册时的tick+period
回复 支持 反对

使用道具 举报

该用户从未签到

12

主题

280

帖子

0

蝴蝶豆

金牌会员

最后登录
2018-10-15
发表于 2017-7-21 15:36:33 | 显示全部楼层
感谢分享!
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|论坛-意法半导体STM32/STM8技术社区

GMT+8, 2024-4-26 06:32 , Processed in 0.195696 second(s), 44 queries .

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表