STM32裸机软件定时器驱动代码

前言

之前接手的一个STM32项目里使用的,感觉写的挺好,用起来,比较的简单,适合裸机下的定时任务的实现。

软件定时器,可以设置时间,设置定时器超时函数,实现定时功能。可以开启,可以停止。

比不上操作系统RTOS里的定时器Timer,但可以用于简单的定时通知的实现。

代码

timer_drv.h

#ifndef __TIMER_DRV_H__
#define __TIMER_DRV_H__

#include "stm32f10x.h"

/* 软件定时器时钟节拍单位 */
#define TIME_BASE_1S        1 //1秒

/* 软件定时器数量 */
#define TIMER_NUM           5

typedef void TIMER_CALLBACK(void);

typedef struct softTimer
{
    uint8_t state;          //状态
    uint8_t mode;           //模式
    uint32_t match;         //到期时间
    uint32_t period;        //定时周期
    TIMER_CALLBACK *cb;     //回调函数指针
    void *argv;             //参数指针
    uint16_t argc;          //参数个数
}softTimer;

typedef enum tmrState
{
    SOFT_TIMER_STOPPED = 0,  //停止
    SOFT_TIMER_RUNNING,      //运行
    SOFT_TIMER_TIMEOUT       //超时
}tmrState;

typedef enum tmrMode
{
    MODE_ONE_SHOT = 0,       //单次模式
    MODE_PERIODIC,           //周期模式
}tmrMode;

void tickCnt_Update(void);
uint32_t tickCnt_Get(void);
void softTimer_Init(void);
void soft_timers_init(void);
uint8_t softTimer_GetState(uint16_t id);
void app_timer_create(uint16_t id, tmrMode mode, TIMER_CALLBACK *cb);
void app_timer_start(uint16_t id, uint32_t delay);
void app_timer_stop(uint16_t id);
void softTimer_Update(void);

#endif

timer_drv.c

#include "timer_drv.h"

static volatile uint32_t tickCnt = 0;   //软件定时器时钟节拍
static softTimer timer[TIMER_NUM];      //软件定时器数组

/*****************************************************
* function: 更新时钟节拍
* param:
* return:
* note:     需在定时器中断内执行
******************************************************/
void tickCnt_Update(void)
{
    tickCnt++;
}

/*****************************************************
* function: 获取时钟节拍
* param:
* return:   时钟节拍
* note:
******************************************************/
uint32_t tickCnt_Get(void)
{
  return tickCnt;
}

/*****************************************************
* function: 软件定时器初始化
* param:
* return:
* note:
******************************************************/
void softTimer_Init(void)
{
    uint16_t i;

    for(i=0; i<TIMER_NUM; i++)
    {
        timer[i].state = SOFT_TIMER_STOPPED;
        timer[i].mode = MODE_ONE_SHOT;
        timer[i].match = 0;
        timer[i].period = 0;
        timer[i].cb = NULL;
        timer[i].argv = NULL;
        timer[i].argc = 0;
    }
}

/*****************************************************
* function: 获取软件定时器状态
* param:    软件定时器ID
* return:   定时器状态
* note:
******************************************************/
uint8_t softTimer_GetState(uint16_t id)
{
    return timer[id].state;
}

void app_timer_create(uint16_t id, tmrMode mode, TIMER_CALLBACK *cb)
{
    assert_param(id < TIMER_NUM);
    assert_param(mode == MODE_ONE_SHOT || mode == MODE_PERIODIC);
    timer[id].state = SOFT_TIMER_STOPPED;
    timer[id].mode = mode;
    timer[id].cb = cb;
}

/*****************************************************
* function: 启动软件定时器
* param1:   软件定时器ID
* param2:   定时器模式
* param3:   延时时间(对周期定时器,亦是周期时间),单位TIME_BASE_1S
* param4:   回调函数指针
* param5:   回调函数参数:参数指针
* param6:   回调函数参数:参数长度
* return:   
* note:     
******************************************************/
void app_timer_start(uint16_t id, uint32_t delay)
{
    assert_param(id < TIMER_NUM);

    timer[id].match = tickCnt_Get() + delay;
    timer[id].period = delay;
    timer[id].state = SOFT_TIMER_RUNNING;
}

/*****************************************************
* function: 停止软件定时器
* param:    软件定时器ID
* return:   
* note:     
******************************************************/
void app_timer_stop(uint16_t id)
{
    assert_param(id < TIMER_NUM);
    timer[id].state = SOFT_TIMER_STOPPED;
}

/*****************************************************
* function: 更新软件定时器状态
* param:    
* return:   
* note:     
******************************************************/
void softTimer_Update(void)
{
    uint16_t i;

    for(i=0; i<TIMER_NUM; i++)
    {
        switch (timer[i].state)
        {
        case SOFT_TIMER_STOPPED:
            break;

        case SOFT_TIMER_RUNNING:
            if(timer[i].match <= tickCnt_Get())
            {
                timer[i].state = SOFT_TIMER_TIMEOUT;
                timer[i].cb();       //执行回调函数
            }
            break;

        case SOFT_TIMER_TIMEOUT:
            if(timer[i].mode == MODE_ONE_SHOT)
            {
                timer[i].state = SOFT_TIMER_STOPPED;
            }
            else
            {
                timer[i].match = tickCnt_Get() + timer[i].period;
                timer[i].state = SOFT_TIMER_RUNNING;
            }
            break;

        default:
            //printf("timer[%d] state error!\r\n", i);
            break;
        }
    }
}

 

运行条件

还需要定时执行:void tickCnt_Update(void);

我这里是整秒的定时,放在了RTC 中断里面。

void RTC_IRQHandler(void)
{
    if(RTC_GetITStatus(RTC_IT_SEC) != RESET)
    {
        RTC_ClearITPendingBit(RTC_IT_SEC);
        RTC_WaitForLastTask();
        tickCnt_Update();
    }
}

操作实例

首先需要初始化定时器,创建定时器,可以是单次,或周期性的

uint8_t g_sys_timers_flag; //系统软件定时
uint8_t SYS_TIMER_ID = 0x00;          //系统定时器ID


void soft_timers_init(void)
{
    softTimer_Init();
    app_timer_create(SYS_TIMER_ID, MODE_PERIODIC, sys_timer_update_handler);
}
void sys_timer_update_handler(void)
{
    timer_flag_update_handler(); //软件定时器超时回调函数
}

/**@brief Function for starting timers.
 */
void sys_timers_start(void)
{
    if(g_sys_timers_flag == 0x00)
    {
        app_timer_start(SYS_TIMER_ID, SYS_TIMER_INTERVAL);
        g_sys_timers_flag = 0x01;
    }
}

/**@brief Function for stop timers.
 */
void sys_timers_stop(void)
{
    if(g_sys_timers_flag == 0x01)
    {
        app_timer_stop(SYS_TIMER_ID);
        g_sys_timers_flag = 0x00;
    }
}

总结

使用比较的简单灵活,适合裸机下的定时消息的触发。

可以根据需求参考使用。

猜你喜欢

转载自blog.csdn.net/tcjy1000/article/details/113769339