软件定时器,利用链表结构来封装定时器。
1. 数据结构体
-
typedef struct softtimer_t
-
{
-
bool isRunning;
-
uint32_t currentTicksRemaining;
-
-
TimeOutCallbackPtr timeOutCallback;
-
uint32_t periodInTicks; // non-zero for periodic timer
-
-
struct softtimer_t* next;
-
} softtimer_t;
(1)isRunning: 标志timer是否处于允许状态
(2)currentTicksRemaining
: 表示还剩下多少tick需要运行
(3)timeOutCallback
:定时器时间到的处理函数
(4)periodInTicks: 设置定时器的重复周期
(5)* next: 软件定时器指针,指向下一个定时器,实现单向链表。
2. 相关配置
-
// 设置节拍的事件,这里设置每10ms产生一个节拍
-
#define TIMER_MILLISECONDS_PER_TICK 10
-
-
// 定时器初始化
-
#define TIMER_INIT { /*isRunning*/false, /*currentTicksRemaining*/0, /*timeOutCallback*/NULL, /*periodInTicks*/0, /*next*/NULL }
-
#define TIMER_DYNINIT(x) { (x).isRunning = false; (x).next=NULL; }
-
-
typedef void (*TimeOutCallbackPtr)(void* data);
3. 处理函数
3.1 启动定时器
-
static void Timer_StartTimer(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback)
-
{
-
Timer_StopTimer(timer);
-
timer->currentTicksRemaining = Timer_ConvertMillisecondsToTicks(periodInMilliseconds) + (uint32_t)timerTicks; // 计算出总的tick
-
timer->timeOutCallback = callback; // 设置时间到处理函数
-
timer->isRunning = true; // 启动定时器
-
if (timer->next == NULL) // 将timer加入到链表中
-
{
-
timer->next = timerList;
-
timerList = timer;
-
}
-
}
可以得出software timer链表结构图:
3.2 关闭定时器
-
void Timer_StopTimer(softtimer_t* timer)
-
{
-
timer->isRunning = false;
-
}
3.3 设置定时器为单次或者为周期性
-
void Timer_StartSingleShot(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback)
-
{
-
timer->periodInTicks = 0;
-
Timer_StartTimer(timer, periodInMilliseconds, callback);
-
}
-
-
void Timer_StartPeriodic(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback)
-
{
-
timer->periodInTicks = Timer_ConvertMillisecondsToTicks(periodInMilliseconds);
-
Timer_StartTimer(timer, periodInMilliseconds, callback);
-
}
3.4 获取定时器剩余的事件(ms)
-
uint32_t Timer_GetRemainingMs(softtimer_t* timer)
-
{
-
return (timer->isRunning ? timer->currentTicksRemaining * TIMER_MILLISECONDS_PER_TICK : 0);
-
}
3.5 定时器中断回调函数
-
void Callback_Timer_TickISR(void)
-
{
-
timerTicks++;
-
EventQueue_Enqueue(&hwTimerExpired);
-
}
这个函数由具体的定时器中断函数所调用,产生ticks事件,并且加入到事件队列中。
static event_t hwTimerExpired = EVENT_INIT(
OnTimerTicksEvent );
当事件:
hwTimerExpired
发生时,将调用其定义好的tick事件函数: OnTimerTicksEvent
-
static void OnTimerTicksEvent(void* data)
-
{
-
uint8_t elapsedTicks;
-
UNUSED_PARAMETER(data);
-
-
// atomically copy and reset timer ticks
-
Common_AtomicSection_Begin();
-
elapsedTicks = timerTicks;
-
timerTicks = 0;
-
Common_AtomicSection_End();
-
-
while ( elapsedTicks > 0 )
-
{
-
OnTimerTickPassed();
-
elapsedTicks--;
-
}
-
}
进一步调用: OnTimerTickPassed
(); 实现真正的定时器操作
-
static void OnTimerTickPassed(void)
-
{
-
softtimer_t* timer;
-
-
for (timer = timerList; timer != NULL; timer = timer->next) // 循环队列处理
-
{
-
if (timer->isRunning )
-
{
-
timer->currentTicksRemaining--;
-
-
if (timer->currentTicksRemaining == 0)
-
{
-
if (timer->periodInTicks == 0) // one shot timer
-
{
-
Timer_StopTimer(timer);
-
}
-
else // periodic timer
-
{
-
timer->currentTicksRemaining = timer->periodInTicks;
-
}
-
-
timer->timeOutCallback(NULL); // 调用回调函数
-
}
-
}
-
}
-
}
4. 完整代码:
-
#include "Timers.h"
-
#include "EventQueue.h"
-
-
#include "hal_time.h"
-
-
-
static void OnTimerTickPassed(void);
-
static void OnTimerTicksEvent(void* data);
-
-
static event_t hwTimerExpired = EVENT_INIT(OnTimerTicksEvent);
-
static volatile uint8_t timerTicks = 0;
-
-
static softtimer_t sentinelAtEnd = TIMER_INIT;
-
static softtimer_t* timerList = &sentinelAtEnd;
-
-
// Private functions
-
-
-
static uint32_t Timer_ConvertMillisecondsToTicks(uint32_t periodInMilliseconds)
-
{
-
return (periodInMilliseconds + TIMER_MILLISECONDS_PER_TICK - 1) / TIMER_MILLISECONDS_PER_TICK;
-
}
-
-
static void Timer_StartTimer(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback)
-
{
-
Timer_StopTimer(timer);
-
timer->currentTicksRemaining = Timer_ConvertMillisecondsToTicks(periodInMilliseconds) + (uint32_t)timerTicks; // add backlog
-
timer->timeOutCallback = callback;
-
timer->isRunning = true;
-
if (timer->next == NULL)
-
{
-
timer->next = timerList;
-
timerList = timer;
-
}
-
}
-
-
// Public functions
-
-
void Timer_Initialize(void)
-
{
-
#ifdef UNIT_TESTING
-
// to ease unit testing, deconstruct the timer list
-
// and reinitialize the timers that were in it.
-
// In production code, everything is initialized statically
-
// and Init must not be called more then once.
-
while(timerList != NULL)
-
{
-
softtimer_t* tmp = timerList;
-
timerList = timerList->next;
-
-
// re-initialize the timer object
-
TIMER_DYNINIT((*tmp));
-
}
-
timerList = &sentinelAtEnd;
-
timerTicks = 0;
-
#endif
-
}
-
-
void Timer_StartSingleShot(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback)
-
{
-
timer->periodInTicks = 0;
-
Timer_StartTimer(timer, periodInMilliseconds, callback);
-
}
-
-
void Timer_StartPeriodic(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback)
-
{
-
timer->periodInTicks = Timer_ConvertMillisecondsToTicks(periodInMilliseconds);
-
Timer_StartTimer(timer, periodInMilliseconds, callback);
-
}
-
-
void Timer_StopTimer(softtimer_t* timer)
-
{
-
timer->isRunning = false;
-
}
-
-
uint32_t Timer_GetRemainingMs(softtimer_t* timer)
-
{
-
return (timer->isRunning ? timer->currentTicksRemaining * TIMER_MILLISECONDS_PER_TICK : 0);
-
}
-
-
void Callback_Timer_TickISR(void)
-
{
-
timerTicks++;
-
EventQueue_Enqueue(&hwTimerExpired);
-
}
-
-
static void OnTimerTickPassed(void)
-
{
-
softtimer_t* timer;
-
-
for (timer = timerList; timer != NULL; timer = timer->next)
-
{
-
if (timer->isRunning )
-
{
-
timer->currentTicksRemaining--;
-
-
if (timer->currentTicksRemaining == 0)
-
{
-
if (timer->periodInTicks == 0) // one shot timer
-
{
-
Timer_StopTimer(timer);
-
}
-
else // periodic timer
-
{
-
timer->currentTicksRemaining = timer->periodInTicks;
-
}
-
-
timer->timeOutCallback(NULL);
-
}
-
}
-
}
-
}
-
-
static void OnTimerTicksEvent(void* data)
-
{
-
uint8_t elapsedTicks;
-
UNUSED_PARAMETER(data);
-
-
// atomically copy and reset timer ticks
-
Common_AtomicSection_Begin();
-
elapsedTicks = timerTicks;
-
timerTicks = 0;
-
Common_AtomicSection_End();
-
-
// if (elapsedTicks > 4)
-
{
-
// printf ("e: %d\n", elapsedTicks);
-
}
-
while ( elapsedTicks > 0 )
-
{
-
OnTimerTickPassed();
-
elapsedTicks--;
-
}
-
}
-
#ifndef TIMERS_H
-
#define TIMERS_H
-
-
#include "Common.h"
-
-
#define TIMER_MILLISECONDS_PER_TICK 10
-
-
#define TIMER_INIT { /*isRunning*/false, /*currentTicksRemaining*/0, /*timeOutCallback*/NULL, /*periodInTicks*/0, /*next*/NULL }
-
#define TIMER_DYNINIT(x) { (x).isRunning = false; (x).next=NULL; }
-
-
-
typedef void (*TimeOutCallbackPtr)(void* data);
-
-
/* A timer MUST be initialized with TIMER_INIT or TIMER_DYNINIT */
-
/* A timer MUST not not be a stack (auto) */
-
typedef struct softtimer_t
-
{
-
bool isRunning;
-
uint32_t currentTicksRemaining;
-
-
TimeOutCallbackPtr timeOutCallback;
-
uint32_t periodInTicks; // non-zero for periodic timer
-
-
struct softtimer_t* next;
-
} softtimer_t;
-
-
void Timer_Initialize(void);
-
-
void Timer_StartSingleShot(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback);
-
void Timer_StartPeriodic(softtimer_t* timer, uint32_t periodInMilliseconds, TimeOutCallbackPtr callback);
-
void Timer_StopTimer(softtimer_t* timer);
-
uint32_t Timer_GetRemainingMs(softtimer_t* timer);
-
void Callback_Timer_TickISR(void);
-
-
#endif /* TIMERS_H */
阅读(1409) | 评论(0) | 转发(0) |