裸机中实现时间片轮转之软件定时器

裸机中定时执行任务一般是在定时器中断中更新自定义的计时变量,在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*****************************/

欢迎使用,提出宝贵意见!


  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值