C语言——软件定时器
都说程序设计 = 算法 + 数据结构。数据结构是挨踢必修课,不过好像学了数据结构之后也没用来做过啥。不知道做啥,就写个软件定时器。
软件定时器数据结构
typedef struct __software_timer{
u32 timeout; //初始化时间计数器
u32 repeat; //运行间隔:repeat > 0 :周期定时时间 repeat == 0 :只定时一次
void (*timeout_callback_handler)(void *para); //超时回调函数
struct __software_timer *next;
}software_timer_t;
判断软件定时器链表是否为空
/**
* @brief: Determine if the software timer list is empty
* @param[in]: None
* @retval[out]: None
* @note:
* @author: AresXu
* @github:
* @version: v1.0.0
*/
static u8 is_softtimer_list_empty(void)
{
if(software_timer_list_head.next == NULL)
return TRUE;
else
return FALSE;
}
插入定时器到软件定时器链表
链表使用单向链表。
/**
* @brief: Insert the software timer node into the linked list
* @param[in]: None
* @retval[out]: None
* @note:
* @author: AresXu
* @github:
* @version: v1.0.0
*/
static void insert_software_timer(software_timer_t *timer_handle)
{
software_timer_t *tmp;
software_timer_t *list_head = &software_timer_list_head;
if(is_softtimer_list_empty())
{
list_head->next = timer_handle;
}
else
{
tmp = list_head->next;
while(tmp->next)
{
if(timer_handle == tmp) //定时器已经存在
{
printf("The timer already exists\r\n");
return;
}
tmp = tmp->next;
}
tmp->next = timer_handle;
}
}
将定时器从软件定时器链表移除
/**
* @brief: Removes the software timer node from the list
* @param[in]: None
* @retval[out]: None
* @note:
* @author: AresXu
* @github:
* @version: v1.0.0
*/
static void remove_software_timer(software_timer_t *timer_handle)
{
software_timer_t *list_head = &software_timer_list_head;
software_timer_t *tmp = list_head;
if(is_softtimer_list_empty())
return;
while(tmp && tmp->next != timer_handle)
{
tmp = tmp->next;
}
if(tmp == NULL)
return;
tmp->next = timer_handle->next;
timer_handle->next = NULL;
}
初始化软件定时器
回调函数不能过长,执行时间不能超过定时时间。
/**
* @brief: Initializes the software timer
* @param[in]: None
* @retval[out]: None
* @note:
* @author: AresXu
* @github:
* @version: v1.0.0
*/
void software_timer_init(software_timer_t *timer_handle,u32 timeout,u32 repeat,void (*timerout_cb)(void *))
{
timer_handle->timeout = timeout;
timer_handle->repeat = repeat;
timer_handle->timeout_callback_handler = timerout_cb;
timer_handle->next = (void *)0;
}
启动定时器
/**
* @brief: Start timer
* @param[in]: None
* @retval[out]: None
* @note:
* @author: AresXu
* @github:
* @version: v1.0.0
*/
void software_timer_start(software_timer_t *timer_handle)
{
insert_software_timer(timer_handle);
}
停止定时器
/**
* @brief: stop timer
* @param[in]: None
* @retval[out]: None
* @note:
* @author: AresXu
* @github:
* @version: v1.0.0
*/
void software_timer_stop(software_timer_t *timer_handle)
{
remove_software_timer(timer_handle);
}
定时器处理函数(主函数调用)
/**
* @brief: Timer processing function
* @param[in]: None
* @retval[out]: None
* @note: Must be called by the main function
* @author: AresXu
* @github: https://github.com/EmbeddedXGJ
* @version: v1.0.0
*/
void software_timer_main_loop(void)
{
software_timer_t *tmp = &software_timer_list_head;
tmp = tmp->next;
while(tmp)
{
if(tmp->timeout <= 0)
{
tmp->timeout_callback_handler((void *)0);
if(tmp->repeat > 0)
{
tmp->timeout = tmp->repeat;
}
else
{
software_timer_stop(tmp);
}
}
tmp = tmp->next;
}
}
硬件定时器提供时基
1 ms硬件定时器调用函数。
/**
* @brief: Provide a heartbeat to the software timer
* @param[in]: void
* @retval[out]: void
* @note: Must be called by 1ms hardware timer
* @author: AresXu
* @github: https://github.com/EmbeddedXGJ
* @version: v1.0.0
*/
void software_timer_ticks(void)
{
software_timer_t *tmp = &software_timer_list_head;
tmp = tmp->next;
while(tmp)
{
if(tmp->timeout > 0)
{
tmp->timeout--;
}
tmp = tmp->next;
}
}
在STM32上测试
- software_timer_test.c:
software_timer_t timer1_t;
software_timer_t timer2_t;
software_timer_t timer3_t;
void timer1_cb(void *parm)
{
printf("1000ms >>> dyy\r\n");
}
void timer2_cb(void *parm)
{
printf("2000ms >>> dyy\r\n");
}
void timer3_cb(void *parm)
{
printf("500ms >>> dyy\r\n");
}
void SoftWareTimer_Init(void)
{
software_timer_init(&timer1_t,1000,1000,timer1_cb);
software_timer_init(&timer2_t,2000,2000,timer2_cb);
software_timer_init(&timer3_t,500,500,timer3_cb);
software_timer_start(&timer1_t);
software_timer_start(&timer2_t);
software_timer_start(&timer3_t);
串口助手打印信息