找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3083|回复: 3
收起左侧

完全由C语言编写,高度可移植,超级牛逼的软件定时器!

[复制链接]
ID:68814 发表于 2019-9-14 19:57 | 显示全部楼层 |阅读模式
帖子来自芯片之家公众号

作为一个搞电子嵌入式的你来说,定时器相信绝对不会陌生,去翻看STM32的官方数据手册,可能有四分之一的篇幅都在讲定时器,可见定时器的重要性,定时器定时器嘛,最重要的功能还是定时。之前经常有师弟跟我抱怨,哎呀,这个单片机怎么只有2个定时器,我都不够用了,怎么办呀,然后一头雾水,其实,只要有一个硬件定时器,在实际不是要求特别特别精准的场合,我们可以模拟很多个软件定时器出来,今天,群主给大家分享一个完全由C语言编写,高度可移植,超级牛逼的软件定时器!

MultiTimer 是一个软件定时器扩展模块,可无限扩展你所需的定时器任务,取代传统的标志位判断方式, 更优雅更便捷地管理程序的时间触发时序。一共有3个文件:
multi_timer.c--定时器c源文件;
multi_timer.h--定时器h头文件;
main--用户代码文件。

我们直接上代码:
  1. /*
  2. *     main.c
  3. *
  4. *      Created on: 20161229
  5. *      @Author   : 晓宇
  6. *      @version  :V1.0.0
  7. *
  8. *                        ,%%%%%%%%,
  9. *                      ,%%/\%%%%/\%%
  10. *                     ,%%%\c''''J/%%%
  11. *           %.        %%%%/ o  o \%%%
  12. *           `%%.      %%%%       |%%%
  13. *            `%%      `%%%%(__Y__)%%'
  14. *            //        ;%%%%`\-/%%%'
  15. *            ((      /   `%%%%%%%'
  16. *             \\     .'           |
  17. *              \\   /        \  | |
  18. *               \\/          ) | |
  19. *                \          /_ | |__
  20. *                (____________))))))) 攻城狮
  21. *
  22. */

  23. #include "multi_timer.h"

  24. struct Timer timer1;
  25. struct Timer timer2;

  26. void timer1_callback()
  27. {
  28.    printf("timer1 timeout!\r\n");
  29. }

  30. void timer2_callback()
  31. {
  32.    printf("timer2 timeout!\r\n");
  33. }

  34. int main()
  35. {
  36. timer_init(&timer1, timer1_callback, 1000, 1000); //1s loop
  37. timer_start(&timer1);

  38. timer_init(&timer2, timer2_callback, 50, 0); //50ms delay
  39. timer_start(&timer2);

  40. while(1) {
  41.      
  42.      timer_loop();
  43. }
  44. }

  45. void HAL_SYSTICK_Callback(void)
  46. {
  47.    timer_ticks(); //1ms ticks
  48. }
复制代码


1、先申请一个定时器管理handle
  1. struct Timer timer1;
复制代码


2、初始化定时器对象,注册定时器回调处理函数,设置定时时间(ms),循环定时触发时间

  1. timer_init(struct Timer* handle, void(*timeout_cb)(), uint32_t timeout, uint32_t repeat);
复制代码


3.启动定时器
  1. timer_start(&timer1);
复制代码



4.设置1ms的硬件定时器循环调用 *timer_ticks()* 以提供时间基准

  1. void HAL_SYSTICK_Callback(void)
  2. {
  3.    timer_ticks();
  4. }
复制代码



5.在主循环调用定时器后台处理函数

  1. int main()
  2. {    ...
  3.    while(1) {
  4.        ...
  5.        timer_loop();
  6.    }
  7. }
复制代码



上面,我们定义了两个定时器,第一个以每1秒一次进行循环执行,第二个定时器50ms之后只执行一次,执行之后,可以通过相应的回调函数打印出来,里面就可以添加我们的定时任务了。怎么样,是不是很简单,只需要设置好定时基准,申请好定时器,初始化完毕,你想要的效果,是定时一次还是进行循环,都没问题,多个定时器之间使用链表来实现,可以启动暂停每个定时器,用起来之后,是不是很爽?具体的代码,需要大家仔细去推敲其中的原理,当然直接用也是可以的。

部分源代码展示:
  1. /*
  2. *     multi_timer.h
  3. *
  4. *      Created on: 20161229
  5. *      @Author   : 晓宇
  6. *      @version  :V1.0.0
  7. */

  8. #ifndef _MULTI_TIMER_H_
  9. #define _MULTI_TIMER_H_

  10. #include "stdint.h"

  11. typedef struct Timer {
  12.    uint32_t timeout;
  13.    uint32_t repeat;
  14.    void (*timeout_cb)(void);
  15.    struct Timer* next;
  16. }Timer;

  17. #ifdef __cplusplus  
  18. extern "C" {  
  19. #endif  

  20. void timer_init(struct Timer* handle, void(*timeout_cb)(), uint32_t timeout, uint32_t repeat);
  21. int  timer_start(struct Timer* handle);
  22. void timer_stop(struct Timer* handle);
  23. void timer_ticks(void);
  24. void timer_loop(void);

  25. // void timer_again(struct Timer* handle);
  26. // void timer_set_repeat(struct Timer* handle, uint32_t repeat);

  27. #ifdef __cplusplus
  28. }
  29. #endif

  30. #endif/*
  31. *     multi_timer.c
  32. *
  33. *      Created on: 20161229
  34. *      @Author   : 晓宇
  35. *      @version  :V1.0.0
  36. */


  37. #include "multi_timer.h"

  38. //timer handle list head.
  39. static struct Timer* head_handle = NULL;

  40. //Timer ticks
  41. static uint32_t _timer_ticks = 0;

  42. /**
  43. * @brief  Initializes the timer struct handle.
  44. * @param  handle: the timer handle strcut.
  45. * @param  timeout_cb: timeout callback.
  46. * @param  repeat: repeat interval time.
  47. * @retval None
  48. */
  49. void timer_init(struct Timer* handle, void(*timeout_cb)(), uint32_t timeout, uint32_t repeat)
  50. {
  51. // memset(handle, sizeof(struct Timer), 0);
  52. handle->timeout_cb = timeout_cb;
  53. handle->timeout = _timer_ticks + timeout;
  54. handle->repeat = repeat;
  55. }

  56. /**
  57. * @brief  Start the timer work, add the handle into work list.
  58. * @param  btn: target handle strcut.
  59. * @retval 0: succeed. -1: already exist.
  60. */
  61. int timer_start(struct Timer* handle)
  62. {
  63. struct Timer* target = head_handle;
  64. while(target) {
  65.    if(target == handle) return -1;  //already exist.
  66.    target = target->next;
  67. }
  68. handle->next = head_handle;
  69. head_handle = handle;
  70. return 0;
  71. }

  72. /**
  73. * @brief  Stop the timer work, remove the handle off work list.
  74. * @param  handle: target handle strcut.
  75. * @retval None
  76. */
  77. void timer_stop(struct Timer* handle)
  78. {
  79. struct Timer** curr;
  80. for(curr = &head_handle; *curr; ) {
  81.    struct Timer* entry = *curr;
  82.    if (entry == handle) {
  83.      *curr = entry->next;
  84. //      free(entry);
  85.    } else
  86.      curr = &entry->next;
  87. }
  88. }

  89. /**
  90. * @brief  main loop.
  91. * @param  None.
  92. * @retval None
  93. */
  94. void timer_loop()
  95. {
  96. struct Timer* target;
  97. for(target=head_handle; target; target=target->next) {
  98.    if(_timer_ticks >= target->timeout) {
  99.      if(target->repeat == 0) {
  100.        timer_stop(target);
  101.      } else {
  102.        target->timeout = _timer_ticks + target->repeat;
  103.      }
  104.      target->timeout_cb();
  105.    }
  106. }
  107. }

  108. /**
  109. * @brief  background ticks, timer repeat invoking interval 1ms.
  110. * @param  None.
  111. * @retval None.
  112. */
  113. void timer_ticks()
  114. {
  115. _timer_ticks++;
  116. }
复制代码

全部资料51hei下载地址:
MultiTimer.zip (2.26 KB, 下载次数: 47)
回复

使用道具 举报

ID:428438 发表于 2019-9-16 10:30 | 显示全部楼层
学习一下,给楼主点个赞。软定时还是经常用到的。
回复

使用道具 举报

ID:68814 发表于 2019-9-23 08:08 | 显示全部楼层
leo2002zhang 发表于 2019-9-16 10:30
学习一下,给楼主点个赞。软定时还是经常用到的。

32用的比较方便,51直接用标志位去完成软定时器功能了
回复

使用道具 举报

ID:130230 发表于 2020-9-10 00:13 | 显示全部楼层
把github地址贴出来好一点,这一个是有开源协议的。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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