代码拉取完成,页面将自动刷新
/*
* stimer.c
*
* Created on: 2021年12月1日
* Author: hello
*/
#include <stdio.h>
#include "stimer.h"
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
///
/// 移植修改区(互斥锁)
///
///
static void stimer_lock(void)
{
__disable_irq();
}
static void stimer_unlock(void)
{
__enable_irq();
}
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
///
/// 软件定时器实现区
///
///
volatile uint32_t _stimer_ticks = 0; ///< 定时器计数时基
stimer_t* _stimer_list = NULL; ///< 定时器列表
/**
* 定时器句柄
* @param timer 定时器句柄
* @param name 定时器名称
* @param timeout_callback 定时器定时到达回调函数
* @param arg 传入定时器的参数
* @param ticks 定时器超时时间,ticks的单位取决于时基函数stimer_ticks的调用间隔时间,如果stimer_ticks每1ms调用一次,那么ticks单位就为1ms
* @param opt 定时器属性,=STIMER_OPT_SINGLE:单次定时器 =STIMER_OPT_REPEAT:周期定时器
*/
void stimer_init(stimer_t* timer, const char* name, void (*timeout_callback)(void* arg), void* arg, uint32_t ticks, stimet_mode_t mode)
{
timer->arg = arg;
timer->mode = mode;
timer->name = name;
timer->next = NULL;
timer->startup_ticks = 0;
timer->timeout_ticks = ticks;
timer->callback = timeout_callback;
}
/**
* 启动定时器(根据超时时间顺序插入)
* @param timer 定时器句柄
*/
void stimer_start(stimer_t* timer)
{
stimer_t** p = &_stimer_list;
uint32_t current_ticks = _stimer_ticks;
stimer_lock();
while(*p != NULL)
{
if(*p == timer) goto __exit;
if((current_ticks + timer->timeout_ticks) < ((*p)->startup_ticks + (*p)->timeout_ticks)) // 当前定时器超时时间小于列表中定时器的超时时间,则将新定时器插在当前定时器前面
break;
p = &(*p)->next;
}
timer->startup_ticks = current_ticks;
timer->next = *p;
*p = timer;
__exit:
stimer_unlock();
}
#if 0
/**
* 启动定时器(头部插入)
* @param timer 定时器句柄
*/
void stimer_start(stimer_t* timer)
{
stimer_t* p = _stimer_list;
stimer_lock();
while(p != NULL) // 遍历链表检查当前定时器是否已经存在
{
if(p == timer) goto __exit;
p = p->next;
}
timer->startup_ticks = _stimer_ticks; // 记录当前时间
timer->next = _stimer_list; // 当前定时器连接到链表头所执行的定时器
_stimer_list = timer; // 将链表头指向当前定时器
__exit:
stimer_unlock();
}
/**
* 启动定时器((尾部插入))
* @param timer 定时器句柄
*/
void stimer_start(stimer_t* timer)
{
stimer_t** p = &_stimer_list;
stimer_t* entry = NULL;
stimer_lock();
while(*p != NULL) // 遍历链表检查当前定时器是否已经存在并定位到链表的最后
{
entry = *p;
if(entry == timer) goto __exit;
p = &entry->next;
}
timer->startup_ticks = _stimer_ticks; // 记录当前时间
*p = timer; // 当将前定时器连接到链表尾部
__exit:
stimer_unlock();
}
#endif
/**
* 停止定时器
* @param timer 定时器句柄
*/
void stimer_stop(stimer_t* timer)
{
stimer_t** p = &_stimer_list;
stimer_t* entry = NULL;
stimer_lock();
while(*p != NULL)
{
entry = *p;
if(*p == timer)
{
*p = entry->next;
break;
}
p = &entry->next;
}
stimer_unlock();
}
/**
* 重启定时器
* @param timer 定时器句柄
*/
void stimer_restart(stimer_t* timer)
{
if(timer != NULL)
{
stimer_stop(timer);
stimer_start(timer);
}
}
/**
* 获取当前定时器已定时时间
* @param timer 定时器句柄
* @return 当前定时时间
*/
uint32_t stimer_getticks(const stimer_t* timer)
{
return (uint32_t)((int)(_stimer_ticks - timer->startup_ticks));
}
/// 定时器轮训函数,放置于main函数的while死循环中
void stimer_poll(void)
{
uint32_t current_ticks = _stimer_ticks;
stimer_t** p = &_stimer_list;
stimer_t* entry = NULL;
stimer_lock();
while(*p != NULL)
{
entry = *p;
if(entry->timeout_ticks > ((uint32_t)((int)(current_ticks - entry->startup_ticks)))) // 未超时
break;
if(entry->mode == STIMER_MODE_REPEAT)
{
p = &entry->next; // 周期模式则检查下一个定时器
}
else
{
*p = entry->next; // 单次模式则将当前定时器删除
}
entry->callback(entry->arg);
entry->startup_ticks = current_ticks;
}
stimer_unlock();
}
/// 定时器时基函数
inline void stimer_ticks(void)
{
_stimer_ticks++;
}
////////////////////////////////////////////////////////////////////////////
///
/// 示例程序
///
#if 0
void Systick_Handler() /* 假设此函数一毫秒执行一次 */
{
stimer_ticks();
}
stimer_t UARTTimer;
stimer_t LED0Timer;
void LED0TimerCallback(void* arg)
{
printf("%s\r\n", __FUNCTION__);
fflush(stdout);
}
void UARTTimerCallback(void* arg)
{
printf("%s\r\n", __FUNCTION__);
fflush(stdout);
}
int main()
{
int i = 0;
stimer_init(
&LED0Timer, // 定时器句柄
"LED0Timer", // 定时器名称
LED0TimerCallback, // 定时器溢出回调函数(注意:不可在回调函数内启动或停止定时器)
&LED0Timer, // 参数
500, // 定时周期
STIMER_MODE_REPEAT // 周期模式
);
stimer_start(&LED0Timer); // 启动定时器
stimer_init(
&UARTTimer, // 定时器句柄
"UARTTimer", // 定时器名称
UARTTimerCallback, // 定时器溢出回调函数(注意:不可在回调函数内启动或停止定时器)
&UARTTimer, // 参数
1000, // 定时周期
STIMER_MODE_SINGLE // 单次模式
);
stimer_start(&UARTTimer); // 启动定时器
for(i = 0; i < 1100; i++) // 模拟时间走过来1001毫秒
Systick_Handler();
for(;;)
{
stimer_poll();
}
return 0;
}
#endif
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。