03-C语言底层驱动:软件定时器驱动

03-C语言底层驱动:软件定时器驱动

​ 创建软件定时器,纯C语言,只依赖一个硬件定时器,现在每个单片机至少都有一个定时器吧,所以支持多平台单片机移植。最多可以创建65535个软件定时器,定时精度可以达到硬件定时器的水平,再也不用担心定时器不够用了!
​ 具体实现方法主要通过一个单链表。

头文件:
#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<<bits))
#define IS_BIT(dat,bits)		(dat & (1<<bits))
#define CLEAR_BIT(dat,bits)		(dat &= ~(1<<bits))



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<s_g_u16TimerCnt; 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<s_g_u16TimerCnt; 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 run\r\n");
    
}
void timer2Task(void *arg)
{
    printf("time1 run\r\n");

}

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);  
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值