创建软件定时器,纯C语言,只依赖一个硬件定时器,现在每个单片机至少都有一个定时器吧,所以支持多平台单片机移植。最多可以创建65535个软件定时器,定时精度可以达到硬件定时器的水平,再也不用担心定时器不够用了!
具体实现方法主要通过一个单链表。
之前发帖过一个1.0版本的,现在增加一些功能,欢迎讨论。
头文件:
- #ifndef __BSP_SOFTtiMER_H
- #define __BSP_SOFTTIMER_H
- #ifndef uint32_t
- #define uint32_t unsigned long
- #endif
- #ifndef uint16_t
- #define uint16_t unsigned int
- #endif
- #ifndef uint8_t
- #define uint8_t unsigned char
- #endif
- /* 开关全局中断的宏 */
- #define ENABLE_INT() __set_PRIMASK(0) /* 使能全局中断 */
- #define DISABLE_INT() __set_PRIMASK(1) /* 禁止全局中断 */
- #define SET_BIT(dat,bits) (dat |= (1<
- #define IS_BIT(dat,bits) (dat & (1<
- #define CLEAR_BIT(dat,bits) (dat &= ~(1<
- typedef enum _en_typeTimer{
- HARD_TIMER=0,
- SOFT_TIMER,
- }en_typeTimer;
- typedef enum _en_timerRunStatus{
- RUNNING = 0,
- STOP,
- }en_timerRunStatus;
- typedef void (*timerFunction) (void *arg);
- typedef struct st_timer_ts
- {
- struct st_timer_ts *nextNode; /*下一定时器结点的地址*/
- uint32_t u32DurationTicks; /*定时的时间,一个u32DurationTicks就是周期调用bsp_timerLoop_ToIrq()函数的中断时长*/
- uint32_t u32DelayTicks; /*当前定时递减计数值*/
- timerFunction timerFunc; /*回调函数地址*/
- void * arg; /*传递给回调函数的参数*/
- en_typeTimer en_typeTime; /*定时器类型,HARD_TIMER=硬定时器,在定时器中断中执行回调函数,时间精度高。
- SOFT_TIMER=软定时器,在main while()大循环中执行回调函数。
- */
- en_timerRunStatus en_runSta; /*定时器的运行状态*/
- uint8_t u8TimerCtr; /*bit0:1=定时时间到,0=时间未到
- bit1:1=循环定时器,0=一次性定时器
- */
- }st_timer_t;
- void bsp_createTimer(st_timer_t *st_timer, en_typeTimer en_typeTime, timerFunction func, void *arg);
- void bsp_timerLoop_ToIrq (st_timer_t *headTimer);
- void bsp_softRunTimer(st_timer_t *headTimer);
- void bsp_startTime(st_timer_t *st_timer, uint32_t u32DurationTicks);
- void bsp_startAutoTime(st_timer_t *st_timer, uint32_t u32DurationTicks);
- void bsp_stopTime(st_timer_t *st_timer);
- #endif
复制代码
c文件:
- /*
- *********************************************************************************************************
- *
- * 模块名称 : 软件定时器
- * 文件名称 : bsp_softTimer.c
- * 版 本 : V2.0
- * 说 明 : 本文件可以创建65535个软件定时器。定时器的回调函数可以在定时器中断中执行,这种方式定时时间精度高。
- * 也可以在main主函数大循环中调用,可以执行一些对时间要求不高的功能。每个定时器的回调函数执行方式可
- * 以二选一。
- *
- * 修改记录 :
- * 版本号 日期 作者 说明
- * V1.0 2017-09-07 徐
- * V2.0 2019-08-17 徐 增加创建一次性和循环定时器函数,增加停止函数。
- *********************************************************************************************************
- */
- #include "bsp.h"
- static uint16_t s_g_u16TimerCnt = 0;//创建的定时器数量
- /*
- *********************************************************************************************************
- * 函 数 名: bsp_createTimer
- * 功能说明: 创建一个软件定时器,此时软件定时器是停止状态。
- * 形 参: *st_timer:定时器结构体地址。 en_typeTime:回调函数的执行方式
- * func :回调函数地址。 *arg :回调函数的形参。
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void bsp_createTimer(st_timer_t *st_timer, en_typeTimer en_typeTime, timerFunction func, void *arg)
- {
- static st_timer_t *st_pPreTimer = (st_timer_t*)0;
- if(s_g_u16TimerCnt != 0) /*第一次进入,nextNode不赋值*/
- {
- st_pPreTimer->nextNode = st_timer; //上次定时器的nextNode赋值
- }
- st_pPreTimer = st_timer; //记录本次定时器的地址
- s_g_u16TimerCnt++;
- st_timer->u32DurationTicks = 0;
- st_timer->u32DelayTicks = 0;
- st_timer->timerFunc = func;
- st_timer->arg = arg;
- st_timer->en_typeTime = en_typeTime;
- st_timer->en_runSta = STOP;
- st_timer->u8TimerCtr = 0;
- }
- /*
- *********************************************************************************************************
- * 函 数 名: bsp_startTime
- * 功能说明: 启动一个一次性软件定时器。
- * 形 参: *st_timer:定时器结构体地址。 u32DurationTicks: 定时时长,单位多少个中断周期。
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void bsp_startTime(st_timer_t *st_timer, uint32_t u32DurationTicks)
- {
- if(st_timer == 0)
- return ;
- DISABLE_INT(); /*关总中断*/
- st_timer->en_runSta = RUNNING;
- st_timer->u32DurationTicks = u32DurationTicks;
- st_timer->u32DelayTicks = u32DurationTicks;
- CLEAR_BIT(st_timer->u8TimerCtr,1);
- ENABLE_INT();
- }
- /*
- *********************************************************************************************************
- * 函 数 名: bsp_startAutoTime
- * 功能说明: 启动一个循环软件定时器。
- * 形 参: *st_timer:定时器结构体地址。 u32DurationTicks: 定时时长,单位多少个中断周期。
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void bsp_startAutoTime(st_timer_t *st_timer, uint32_t u32DurationTicks)
- {
- if(st_timer == 0)
- return ;
- DISABLE_INT(); /*关总中断*/
- st_timer->en_runSta = RUNNING;
- st_timer->u32DurationTicks = u32DurationTicks;
- st_timer->u32DelayTicks=u32DurationTicks;
- SET_BIT(st_timer->u8TimerCtr,1);
- ENABLE_INT();
- }
- /*
- *********************************************************************************************************
- * 函 数 名: bsp_stopTime
- * 功能说明: 停止一个软件定时器。
- * 形 参: *st_timer:定时器结构体地址。
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void bsp_stopTime(st_timer_t *st_timer)
- {
- st_timer->en_runSta = STOP;
- }
- /*
- *********************************************************************************************************
- * 函 数 名: bsp_timerLoop_ToIrq
- * 功能说明: 软件定时器逻辑具体实现的函数,必须放在硬件定时器中断中循环调用。
- * 形 参: *headTimer:创建的第一个定时器结构体地址。
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void bsp_timerLoop_ToIrq(st_timer_t *headTimer)
- {
-
- uint16_t j=0;
- st_timer_t *timer=headTimer;
- for(; j
- {
- if(timer->en_runSta == RUNNING)
- {
- if ((timer->u32DelayTicks == 0) || (--timer->u32DelayTicks == 0))
- {
- if(timer->en_typeTime == HARD_TIMER)//硬件定时器,执行回调函数
- {
- timer->timerFunc(timer->arg);
- }
- else
- {
- SET_BIT(timer->u8TimerCtr,0);//软件定时器,在while中执行
- }
- if(IS_BIT(timer->u8TimerCtr,1)) /*循环定时器重装载计数值*/
- {
- timer->u32DelayTicks = timer->u32DurationTicks;
- }
- else /*一次性定时器*/
- {
- timer->en_runSta = STOP;
- }
- }
- }
- timer=timer->nextNode;
- }
-
- }
- /*
- *********************************************************************************************************
- * 函 数 名: bsp_softRunTimer
- * 功能说明: 遍历软定时器,查询定时时间是否到了,在main.c while{}中执行
- * 形 参: *headTimer:创建的第一个定时器结构体地址。
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void bsp_softRunTimer(st_timer_t *headTimer)
- {
- uint16_t j=0;
- st_timer_t *timer=headTimer;
- for(; j
- {
- if(IS_BIT(timer->u8TimerCtr,0))
- {
- CLEAR_BIT(timer->u8TimerCtr,0);
- timer->timerFunc(timer->arg);
- }
- timer=timer->nextNode;
- }
- }
复制代码
最后来个简单的例子:
- #include "bsp.h"
- st_timer_t timer1;
- st_timer_t timer2;
- void timer1Task(void *arg)
- {
- printf("time1 runrn");
-
- }
- void timer2Task(void *arg)
- {
- printf("time1 runrn");
- }
- int main(void)
- {
- SysTick_Config(SystemCoreClock / 1000); /*1ms滴答中断定时器*/
- bsp_createTimer(&timer1,SOFT_TIMER,timer1Task,(void*)0);
- bsp_createTimer(&timer2,HARD_TIMER,timer2Task,(void*)0);
- bsp_startTime(&timer1,100); /*100个定时器中断执行一次*/
- bsp_startAutoTime(&timer2,500);
- while(1)
- {
- bsp_softRunTimer(&timer1);
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: SysTick_Handler
- * 功能说明: 系统嘀嗒定时器中断服务程序。启动文件中引用了该函数。建议中断时间1ms。
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void SysTick_Handler(void)
- {
- bsp_timerLoop_ToIrq(&timer1);
- }
复制代码
|