适合单片机裸机环境的运行的软件定时器框架

发布于:2025-04-15 ⋅ 阅读:(89) ⋅ 点赞:(0)

如下这篇文档介绍了一个适用于裸机环境的软件定时器模块,其核心功能和实现如下:

  1. 模块功能:该模块通过硬件定时器中断实现时基累加,适合用于裸机程序的调度处理。它使用硬件定时中断(如1ms一次)来增加hw_timer_ticks,当hw_timer_ticks大于设定的延迟时间时,执行回调函数。
  2. 数据结构:定义了一个`timer_struct 结构体,包含延迟时间delay自动重载时间auto_repeat和回调函数callback。
  3. 函数接口
    timer_start:启动定时器,设置延迟、循环模式和回调函数。
    timer_stop:停止定时器,清零延迟并置空回调函数。
    timer_is_running:检查定时器是否在运行。
    timer_loop:主循环,检查并执行到期的定时器任务。
  4. 实现细节
    hw_timer_ticks:全局变量,用于记录时基。
    my_timer:定时器参数数组,支持最多10个定时器。
  5. 应用示例:提供了一个应用示例,展示了如何使用该模块定时执行两个任务:每2秒执行一次func1,每6秒执行一次`func2。
  6. 适用场景:适用于8位单片机系统,如果硬件资源有限或系统时钟太低,可以调整硬件定时中断的精度。
  7. 优势:实现基础框架后,应用层只需要简单的操作即可实现定时任务,如定时读取ADC结果或延时关闭LED显示。
  8. 代码实现:文档提供了完整的代码实现,包括头文件和主程序,以及如何启动和停止定时器,以及定时器的主循环处理。

这个模块提供了一个简单而有效的软件定时器解决方案,适用于裸机环境,通过硬件定时器中断实现精确的定时任务调度。

该程序的hw_timer_ticks进行时基的累加,建议放在一个硬件的定时器中。主程序通过timer_loop 处理注册的定时器任务,该模块适合对裸机程序进行调度处理。使用硬件定时中断,例如1ms中断一次,每次中断hw_timer_ticks自增一次。主程序中查询hw_timer_ticks 大于delay表示当前定时器任务超时,执行callback。这种在8位单片机系统合适,如果硬件资源有限或者系统时钟太低,可以调整硬件定时中断的精度。这样多个定时器时事件的执行只需要一个硬件定时器。

#include <stdio.h>
#include <string.h>
typedef unsigned int uint32_t;
typedef unsigned char uint8_t;
typedef enum {true=1,false=0}bool;
extern uint32_t hw_timer_ticks ;

typedef void (*timer_callback)(void);
#define SW_TIMER_MAX  10

typedef struct
{
    uint32_t delay;                //延迟时间,实际是当前时间+期望延时的时间后的tick
    uint32_t auto_repeat;    //执行后自动重载时间,为0表示只执行一次
    timer_callback callback;     //回调函数
} timer_struct;

//启动定时器,index可按需求定为枚举类型,必须小于SW_TIMER_MAX
void timer_start(uint8_t index, uint32_t delay, bool loop, timer_callback callback);
void timer_stop(uint8_t index);//停止定时器,delay清零,回调函数置为NULL
bool timer_is_running(uint8_t index);//当前定时器是否在计时运行中,判断delay是否非0
void timer_loop(void);


#include "mytimer.h"

uint32_t hw_timer_ticks = 0;//timer ticks
timer_struct my_timer[SW_TIMER_MAX] = {0};    //定时器参数数组,最大支持10个


void timer_start(uint8_t index, uint32_t delay, bool loop, timer_callback callback)
{
    
    if((index >= SW_TIMER_MAX) || (delay == 0) || (callback == NULL))
    {
        return;
    }

    my_timer[index].delay = hw_timer_ticks + delay;
    if(loop)//自动重载
    {
        my_timer[index].auto_repeat = delay;
    }
    else
    {
        my_timer[index].auto_repeat = 0;
    }

    my_timer[index].callback = callback;
}
void timer_stop(uint8_t index)
{
    my_timer[index].delay=0;
    my_timer[index].callback=NULL;
}

bool timer_is_running(uint8_t index)
{
    if(my_timer[index].delay==0)
    {
        return false ;
    }
    return true;
}

void timer_loop(void)
{
    uint8_t i = 0, n = 0, min = 0;
    for(i = 0 ; i < SW_TIMER_MAX ; i++)
    {
        if(my_timer[i].delay > 0 && my_timer[i].callback != NULL)
        {
            if(hw_timer_ticks >= my_timer[i].delay)
            {
                if(( my_timer[i].auto_repeat) > 0)
                {
                    my_timer[i].delay = hw_timer_ticks + my_timer[i].auto_repeat;
                }
                else
                {
                    my_timer[i].delay = 0; //stop
                }
                (*my_timer[i].callback)();
            }
        }
    }
}

应用Demo:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "mytimer.h"

void func1(void)
{
    printf("task1\r\n");
}
void func2(void)
{
    printf("task2\r\n");
}

int main(void)
{
timer_callback   pFunc;
pFunc=  &func1;
timer_start(0,2,true,pFunc);
pFunc=  &func2;
timer_start(1,6,true,pFunc);
while (1)
{
timer_loop();
usleep(100000);
hw_timer_ticks++;//如果有硬件定时器这个地方放定时器中
}
}