Chinaunix首页 | 论坛 | 博客
  • 博客访问: 830972
  • 博文数量: 281
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2770
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 19:45
个人简介

邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛

文章分类
文章存档

2020年(1)

2018年(1)

2017年(56)

2016年(72)

2015年(151)

分类: 嵌入式

2015-12-10 15:18:13

软件定时器,利用链表结构来封装定时器。

1. 数据结构体

点击(此处)折叠或打开

  1. typedef struct softtimer_t
  2. {
  3.     bool isRunning;
  4.     uint32_t currentTicksRemaining;

  5.     TimeOutCallbackPtr timeOutCallback;
  6.     uint32_t periodInTicks;    // non-zero for periodic timer

  7.     struct softtimer_t* next;
  8. } softtimer_t;
(1)isRunning: 标志timer是否处于允许状态
(2)currentTicksRemaining: 表示还剩下多少tick需要运行
(3)timeOutCallback:定时器时间到的处理函数
(4)periodInTicks: 设置定时器的重复周期
(5)* next:  软件定时器指针,指向下一个定时器,实现单向链表。

2. 相关配置

点击(此处)折叠或打开

  1. // 设置节拍的事件,这里设置每10ms产生一个节拍
  2. #define TIMER_MILLISECONDS_PER_TICK 10

  3. // 定时器初始化
  4. #define TIMER_INIT { /*isRunning*/false, /*currentTicksRemaining*/0, /*timeOutCallback*/NULL, /*periodInTicks*/0, /*next*/NULL }
  5. #define TIMER_DYNINIT(x) { (x).isRunning = false; (x).next=NULL; }

  6. typedef void (*TimeOutCallbackPtr)(void* data);

3. 处理函数

3.1 启动定时器

点击(此处)折叠或打开

  1. static void Timer_StartTimer(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback)
  2. {
  3.     Timer_StopTimer(timer);
  4.     timer->currentTicksRemaining = Timer_ConvertMillisecondsToTicks(periodInMilliseconds) + (uint32_t)timerTicks; // 计算出总的tick
  5.     timer->timeOutCallback = callback;  // 设置时间到处理函数
  6.     timer->isRunning = true;            // 启动定时器
  7.     if (timer->next == NULL)            // 将timer加入到链表中
  8.     {
  9.         timer->next = timerList;
  10.         timerList = timer;
  11.     }
  12. }
可以得出software timer链表结构图:


3.2 关闭定时器

点击(此处)折叠或打开

  1. void Timer_StopTimer(softtimer_t* timer)
  2. {
  3.     timer->isRunning = false;
  4. }

3.3 设置定时器为单次或者为周期性

点击(此处)折叠或打开

  1. void Timer_StartSingleShot(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback)
  2. {
  3.     timer->periodInTicks = 0;
  4.     Timer_StartTimer(timer, periodInMilliseconds, callback);
  5. }

  6. void Timer_StartPeriodic(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback)
  7. {
  8.     timer->periodInTicks = Timer_ConvertMillisecondsToTicks(periodInMilliseconds);
  9.     Timer_StartTimer(timer, periodInMilliseconds, callback);
  10. }

3.4 获取定时器剩余的事件(ms)

点击(此处)折叠或打开

  1. uint32_t Timer_GetRemainingMs(softtimer_t* timer)
  2. {
  3.     return (timer->isRunning ? timer->currentTicksRemaining * TIMER_MILLISECONDS_PER_TICK : 0);
  4. }

3.5 定时器中断回调函数

点击(此处)折叠或打开

  1. void Callback_Timer_TickISR(void)
  2. {
  3.     timerTicks++;
  4.     EventQueue_Enqueue(&hwTimerExpired);
  5. }
这个函数由具体的定时器中断函数所调用,产生ticks事件,并且加入到事件队列中。
static event_t hwTimerExpired = EVENT_INIT( OnTimerTicksEvent );

当事件:hwTimerExpired 发生时,将调用其定义好的tick事件函数: OnTimerTicksEvent

点击(此处)折叠或打开

  1. static void OnTimerTicksEvent(void* data)
  2. {
  3.     uint8_t elapsedTicks;
  4.     UNUSED_PARAMETER(data);

  5.     // atomically copy and reset timer ticks
  6.     Common_AtomicSection_Begin();
  7.     elapsedTicks = timerTicks;
  8.     timerTicks = 0;
  9.     Common_AtomicSection_End();

  10.     while ( elapsedTicks > 0 )
  11.     {
  12.         OnTimerTickPassed();
  13.         elapsedTicks--;
  14.     }
  15. }
进一步调用: OnTimerTickPassed(); 实现真正的定时器操作

点击(此处)折叠或打开

  1. static void OnTimerTickPassed(void)
  2. {
  3.     softtimer_t* timer;

  4.     for (timer = timerList; timer != NULL; timer = timer->next)    // 循环队列处理
  5.     {
  6.         if (timer->isRunning )
  7.         {
  8.             timer->currentTicksRemaining--;

  9.             if (timer->currentTicksRemaining == 0)
  10.             {
  11.                 if (timer->periodInTicks == 0) // one shot timer
  12.                 {
  13.                     Timer_StopTimer(timer);
  14.                 }
  15.                 else // periodic timer
  16.                 {
  17.                     timer->currentTicksRemaining = timer->periodInTicks;
  18.                 }

  19.                 timer->timeOutCallback(NULL);   // 调用回调函数
  20.             }
  21.         }
  22.     }
  23. }







4. 完整代码:

点击(此处)折叠或打开

  1. #include "Timers.h"
  2. #include "EventQueue.h"

  3. #include "hal_time.h"


  4. static void OnTimerTickPassed(void);
  5. static void OnTimerTicksEvent(void* data);

  6. static event_t hwTimerExpired = EVENT_INIT(OnTimerTicksEvent);
  7. static volatile uint8_t timerTicks = 0;

  8. static softtimer_t sentinelAtEnd = TIMER_INIT;
  9. static softtimer_t* timerList = &sentinelAtEnd;

  10. // Private functions


  11. static uint32_t Timer_ConvertMillisecondsToTicks(uint32_t periodInMilliseconds)
  12. {
  13.     return (periodInMilliseconds + TIMER_MILLISECONDS_PER_TICK - 1) / TIMER_MILLISECONDS_PER_TICK;
  14. }

  15. static void Timer_StartTimer(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback)
  16. {
  17.     Timer_StopTimer(timer);
  18.     timer->currentTicksRemaining = Timer_ConvertMillisecondsToTicks(periodInMilliseconds) + (uint32_t)timerTicks; // add backlog
  19.     timer->timeOutCallback = callback;
  20.     timer->isRunning = true;
  21.     if (timer->next == NULL)
  22.     {
  23.         timer->next = timerList;
  24.         timerList = timer;
  25.     }
  26. }

  27. // Public functions

  28. void Timer_Initialize(void)
  29. {
  30. #ifdef UNIT_TESTING
  31.     // to ease unit testing, deconstruct the timer list
  32.     // and reinitialize the timers that were in it.
  33.     // In production code, everything is initialized statically
  34.     // and Init must not be called more then once.
  35.     while(timerList != NULL)
  36.     {
  37.         softtimer_t* tmp = timerList;
  38.         timerList = timerList->next;

  39.         // re-initialize the timer object
  40.         TIMER_DYNINIT((*tmp));
  41.     }
  42.     timerList = &sentinelAtEnd;
  43.     timerTicks = 0;
  44. #endif
  45. }

  46. void Timer_StartSingleShot(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback)
  47. {
  48.     timer->periodInTicks = 0;
  49.     Timer_StartTimer(timer, periodInMilliseconds, callback);
  50. }

  51. void Timer_StartPeriodic(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback)
  52. {
  53.     timer->periodInTicks = Timer_ConvertMillisecondsToTicks(periodInMilliseconds);
  54.     Timer_StartTimer(timer, periodInMilliseconds, callback);
  55. }

  56. void Timer_StopTimer(softtimer_t* timer)
  57. {
  58.     timer->isRunning = false;
  59. }

  60. uint32_t Timer_GetRemainingMs(softtimer_t* timer)
  61. {
  62.     return (timer->isRunning ? timer->currentTicksRemaining * TIMER_MILLISECONDS_PER_TICK : 0);
  63. }

  64. void Callback_Timer_TickISR(void)
  65. {
  66.     timerTicks++;
  67.     EventQueue_Enqueue(&hwTimerExpired);
  68. }

  69. static void OnTimerTickPassed(void)
  70. {
  71.     softtimer_t* timer;

  72.     for (timer = timerList; timer != NULL; timer = timer->next)
  73.     {
  74.         if (timer->isRunning )
  75.         {
  76.             timer->currentTicksRemaining--;

  77.             if (timer->currentTicksRemaining == 0)
  78.             {
  79.                 if (timer->periodInTicks == 0) // one shot timer
  80.                 {
  81.                     Timer_StopTimer(timer);
  82.                 }
  83.                 else // periodic timer
  84.                 {
  85.                     timer->currentTicksRemaining = timer->periodInTicks;
  86.                 }

  87.                 timer->timeOutCallback(NULL);
  88.             }
  89.         }
  90.     }
  91. }

  92. static void OnTimerTicksEvent(void* data)
  93. {
  94.     uint8_t elapsedTicks;
  95.     UNUSED_PARAMETER(data);

  96.     // atomically copy and reset timer ticks
  97.     Common_AtomicSection_Begin();
  98.     elapsedTicks = timerTicks;
  99.     timerTicks = 0;
  100.     Common_AtomicSection_End();

  101. // if (elapsedTicks > 4)
  102.     {
  103. // printf ("e: %d\n", elapsedTicks);
  104.     }
  105.     while ( elapsedTicks > 0 )
  106.     {
  107.         OnTimerTickPassed();
  108.         elapsedTicks--;
  109.     }
  110. }

点击(此处)折叠或打开

  1. #ifndef TIMERS_H
  2. #define    TIMERS_H

  3. #include "Common.h"

  4. #define TIMER_MILLISECONDS_PER_TICK 10

  5. #define TIMER_INIT { /*isRunning*/false, /*currentTicksRemaining*/0, /*timeOutCallback*/NULL, /*periodInTicks*/0, /*next*/NULL }
  6. #define TIMER_DYNINIT(x) { (x).isRunning = false; (x).next=NULL; }


  7. typedef void (*TimeOutCallbackPtr)(void* data);

  8. /* A timer MUST be initialized with TIMER_INIT or TIMER_DYNINIT */
  9. /* A timer MUST not not be a stack (auto) */
  10. typedef struct softtimer_t
  11. {
  12.     bool isRunning;
  13.     uint32_t currentTicksRemaining;

  14.     TimeOutCallbackPtr timeOutCallback;
  15.     uint32_t periodInTicks;    // non-zero for periodic timer

  16.     struct softtimer_t* next;
  17. } softtimer_t;

  18. void Timer_Initialize(void);

  19. void Timer_StartSingleShot(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback);
  20. void Timer_StartPeriodic(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback);
  21. void Timer_StopTimer(softtimer_t* timer);
  22. uint32_t Timer_GetRemainingMs(softtimer_t* timer);
  23. void Callback_Timer_TickISR(void);

  24. #endif    /* TIMERS_H */


阅读(1409) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~