裸机中定时执行任务一般是在定时器中断中更新自定义的计时变量,在main中判读时间到达后执行相关任务。这种方法代码可读性差,不利于代码的模块化,容易导致代码混乱。通过使用软件定时器,可将多个定时任务放到定时器回调函数中执行,实现类似RTOS的时间片轮转功能。
一、软件定时器
占用一个硬件定时器,通过定义数据结构和一定的算法,虚拟出多个软件定时器。定时器时间更新放入定时器中断,定时器处理函数放入main循环中即可。
二、代码实现
soft_timer.h:
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SOFT_TIMER_H_
#define __SOFT_TIMER_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stddef.h>
/* Exported types ------------------------------------------------------------*/
typedef void (*callback)(uint32_t param);
typedef enum SoftTmrState
{
SOFT_TMR_STATE_IDLE = 0, //未注册
SOFT_TMR_STATE_STOPPED, //停止
SOFT_TMR_STATE_RUNNING, //运行
}SOFT_TMR_STATE;
typedef struct SoftTimer
{
SOFT_TMR_STATE state; //状态
uint32_t count; //执行次数
uint32_t match; //到期时间
uint32_t period; //定时周期
callback cb; //回调函数指针
uint32_t param; //回调函数参数
}SOFT_TIMER;
typedef enum SoftTmrId
{
SOFT_TMR_ID_NULL = -1,
SOFT_TMR_ID_MIN = 0,
SOFT_TMR_ID_MAX = 6, //支持同时运行的最大数量
}SOFT_TMR_ID;
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
#define SOFT_TMR_RUN_FORVER 0xFFFFFFFF
/* Exported functions ------------------------------------------------------- */
void SoftTimerUpdate(void);
void SoftTimerInit(void);
void SoftTimerExec(void);
SOFT_TMR_ID SoftTimerRegister(uint32_t period, callback cb, uint32_t param);
void SoftTimerUnregister(SOFT_TMR_ID id);
void SoftTimerStart(SOFT_TMR_ID id, uint32_t count);
void SoftTimerStop(SOFT_TMR_ID id);
SOFT_TMR_STATE SoftTimerGetState(SOFT_TMR_ID id);
#ifdef __cplusplus
}
#endif
#endif
/*********************************END OF FILE*****************************/
soft_timer.c:
/**
******************************************************************************
* @file
* @author dave
* @version
* @date 2021-1-7
* @brief
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "soft_timer.h"
/* Private typedef -----------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static volatile uint32_t tickCnt = 0; //时钟节拍
SOFT_TIMER timer[SOFT_TMR_ID_MAX];
/* Private functions ---------------------------------------------------------*/
/**
* @brief 在1ms定时器中断内执行
* @param None
* @retval None
*/
void SoftTimerUpdate(void)
{
tickCnt++;
}
/**
* @brief
* @param None
* @retval None
*/
static uint32_t tickCnt_Get(void)
{
return tickCnt;
}
/**
* @brief
* @param None
* @retval None
*/
void SoftTimerInit(void)
{
for(SOFT_TMR_ID i = SOFT_TMR_ID_MIN; i<SOFT_TMR_ID_MAX; i++)
{
timer[i].state = SOFT_TMR_STATE_IDLE;
timer[i].count = 0;
timer[i].match = 0;
timer[i].period = 0;
timer[i].cb = NULL;
timer[i].param = 0;
}
}
/**
* @brief
* @param None
* @retval None
*/
SOFT_TMR_ID SoftTimerRegister(uint32_t period, callback cb, uint32_t param)
{
for(SOFT_TMR_ID i = SOFT_TMR_ID_MIN; i < SOFT_TMR_ID_MAX; i++)
{
if(timer[i].state == SOFT_TMR_STATE_IDLE)
{
timer[i].state = SOFT_TMR_STATE_STOPPED;
timer[i].period = period;
timer[i].cb = cb;
timer[i].param = param;
return i;
}
}
return SOFT_TMR_ID_NULL;
}
/**
* @brief
* @param None
* @retval None
*/
void SoftTimerUnregister(SOFT_TMR_ID id)
{
if((id > SOFT_TMR_ID_NULL) && (id < SOFT_TMR_ID_MAX))
{
if(timer[id].state != SOFT_TMR_STATE_IDLE)
{
timer[id].state = SOFT_TMR_STATE_IDLE;
}
}
}
/**
* @brief
* @param None
* @retval None
*/
void SoftTimerStart(SOFT_TMR_ID id, uint32_t count)
{
if((id > SOFT_TMR_ID_NULL) && (id < SOFT_TMR_ID_MAX))
{
if(count > 0)
{
if(timer[id].state == SOFT_TMR_STATE_STOPPED)
{
timer[id].count = count;
timer[id].match = tickCnt_Get() + timer[id].period;
timer[id].state = SOFT_TMR_STATE_RUNNING;
}
}
}
}
/**
* @brief 在main循环内执行
* @param None
* @retval None
*/
void SoftTimerExec(void)
{
SOFT_TMR_ID i;
for(i = SOFT_TMR_ID_MIN; i < SOFT_TMR_ID_MAX; i++)
{
switch (timer[i].state)
{
case SOFT_TMR_STATE_IDLE:
break;
case SOFT_TMR_STATE_STOPPED:
break;
case SOFT_TMR_STATE_RUNNING:
if(timer[i].match <= tickCnt_Get())
{
//执行回调函数
timer[i].cb(timer[i].param);
//回调中未注销或停止
if(timer[i].state == SOFT_TMR_STATE_RUNNING)
{
//次数递减
if(timer[i].count != SOFT_TMR_RUN_FORVER)
{
if(timer[i].count > 0)
{
timer[i].count--;
}
else
{
timer[i].state = SOFT_TMR_STATE_STOPPED;
break;
}
}
//超时重装
timer[i].match = tickCnt_Get() + timer[i].period;
}
}
break;
default:
break;
}
}
}
/**
* @brief
* @param None
* @retval None
*/
void SoftTimerStop(SOFT_TMR_ID id)
{
if((id > SOFT_TMR_ID_NULL) && (id < SOFT_TMR_ID_MAX))
{
if (timer[id].state != SOFT_TMR_STATE_STOPPED)
{
timer[id].state = SOFT_TMR_STATE_STOPPED;
}
}
}
/**
* @brief
* @param None
* @retval None
*/
SOFT_TMR_STATE SoftTimerGetState(SOFT_TMR_ID id)
{
if((id > SOFT_TMR_ID_NULL) && (id < SOFT_TMR_ID_MAX))
{
return timer[id].state;
}
return SOFT_TMR_STATE_IDLE;
}
/*****************************END OF FILE*****************************/
欢迎使用,提出宝贵意见!