软件定时器库

2023-05-16

前后台系统和多任务操作系统,在简单功能上差别不大,唯一不顺手的就是前后台系统没有合适的软件定时器。封装一层软件定时器接口,对后续功能开发事半功倍。

定义结构体数组,其基础成员如下:

static uint32_t hw_interrupt_timer_ticks = 0;//timer ticks
typedef void (*timer_callback)(void);
//软件定时器最大个数
#define SW_TIMER_MAX  10

typedef struct
{
    uint32 delay;                //延迟时间,实际是当前时间+期望延时的时间后的tick
    uint32 auto_repeat;    //执行后自动重载时间,为0表示只执行一次
    timer_callback callback;     //回调函数
} timer_struct;
timer_struct my_timer[SW_TIMER_MAX] = {0};    //定时器参数数组,最大支持10个

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

对应用提供的启动定时器接口实现可以参考如下:

static void timer_start(uint8 index, uint32 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;
}

使用硬件定时中断,例如1ms中断一次,每次中断hw_timer_ticks自增一次。主程序中查询hw_timer_ticks 大于delay表示当前定时器任务超时,执行callback。这种在8位单片机系统合适,如果硬件资源有限或者系统时钟太低,可以调整硬件定时中断的精度。这样多个定时器时事件的执行只需要一个硬件定时器。

static void timer_loop(void)
{
    uint8 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();
            }
        }
    }
}

实现基础框架后,应用层只需要简单的操作就是实现,例如定时每60秒读取一次ADC结果,和延时30秒后关闭LED显示。

static void timer_start(READ_ADC_TIMER_ID, 60*1000, TRUE, read_adc_callback);
static void timer_start(LED_ON_TIMEROUT_TIMER_ID, 30*1000, FALSE, led_on_timeout_callback);

这种方案的缺点是my_timer数组下标index与应用绑定,即使没有全部使用,主程序每次都要查询全部数组成员;11个定时任务即使明确最多只有9个同时在运行,该接口也无法满足需求。

增加申请定时器资源的接口,在10个定时器池中获取没有被使用的,将index下标返回,再传入timer_statrt,同样的定义,可以满足10个定时任务同时运行,提高了定时器的利用率。

因为主程序轮流查询定时器状态,加上前面的回调函数执行的时间,实际执行回调时间与期望的延时时间存在一定误差。在硬件资源充足的情况下,可以将数组改为链表,按delay从小到大排序,新启动的定时器按顺序插入到合适的位置,这样主程序查询速度会加快,在最近的软件定时器,也就是第一个软件定时器超时前可以休眠省电。或者分为多个数组映射不同的优先级和时间精度,这样提高回调函数执行的时间准确度。

工欲善其事,必先利其器,基础件完美才能支撑复杂多变的应用层。

已剪辑自: https://mp.weixin.qq.com/s?__biz=Mzg3OTQ3NDQ2Mg==&mid=2247483751&idx=1&sn=7f20c6527b60ad8b3eef6d913f9eb9db&chksm=cf02a316f8752a00fa901c26c0b187a49659d8f1bcbb55d84b354edc0c9c4a30ed2fb0b9cb51&scene=178&cur_album_id=1856108351068143619#rd

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

软件定时器库 的相关文章

随机推荐

  • 怎么做串口调试软件?

    嗯 说一下我自己写的串口助手吧 xff0c 名字叫 Bittly xff0c 样子呢长下面这个样子 Bittly 指令调试界面 1 需求确认 一开始使用的是类似于XCOM或者SSCOM之类的串口调试助手 xff0c 他们的优点是体积小 xf
  • 【需求专题】如何写好需求——INCOSE需求编写指南(1)

    已剪辑自 https mp weixin qq com s Z5VBTyV6j07JylDdOsFSxQ 编者按 如何写好需求是INCOSE 需求工作组编写的需求文本化表达指南 本指南是专门讲述如何在系统工程中对需求进行文本化表达 xff0
  • 怎么提高自己的系统设计和架构理论水平?

    文章目录 前言 1 无锁化 1 1 串行无锁 1 2 结构无锁 2 零拷贝 2 1 内存映射 2 2 零拷贝 3 序列化 3 1 分类 3 2 性能指标 3 3 选型考量 4 池子化 4 1 内存池 4 2 线程池 4 3 连接池 4 4
  • 30+男生程序员中年如何破局

    已剪辑自 https zhuanlan zhihu com p 596751971 1 最顶级的程序员根据自己的经验拼paper 拼专利 xff0c 成为不可替代的专家 最厉害的程序员拼的不是代码写的多牛逼 而是有多少paper多少顶尖专利
  • 为啥AI难落地?

    总在说AI落地难 xff0c 那为啥难落地 xff1f 以最典型的智慧城市业务来说 xff0c 就是接入网络摄像头 xff0c 然后识别里面的人 xff0c 判断是不是抽烟 打架 闯红灯 不带安全帽等 首先是连接网络摄像机 xff0c GB
  • 搞技术,如何写好技术文档?

    已剪辑自 https mp weixin qq com s OtSwtMyeifoc7ED35a vEA 嵌入式方案设计文档 xff0c 到底应该怎么写 xff1f 你是不是从来没有想过这个问题 xff1f 很多技术人自己非常轻视技术文档的
  • 用125行C语言编写一个简单的16位虚拟机

    已剪辑自 https mp weixin qq com s ikrpGtssoKpumHXhrQdh8Q 博文地址 xff1a 改博文用图文代码的方式详细描述了实现的具体过程 xff0c 包含每一条指令的含义 系统虚拟机 xff0c 可完全
  • RT-Thread操作系统的FreeRTOS兼容层

    已剪辑自 https mp weixin qq com s 2BjJyieMr97NQhO76DQ3hw Github地址 https github com RT Thread packages FreeRTOS Wrapper 本项目是2
  • 嵌入式开发既要代码小,又想速度快,该如何优化?

    已剪辑自 https mp weixin qq com s HaoPN0upS8OEheXpSHWBFA 素材来源 xff1a 网络素材 整理 xff1a 技术让梦想更伟大 李肖遥 对程序进行优化 xff0c 通常是指优化程序代码或程序执行
  • 小白学C语言编程(for语句无限制循环)

    问题 xff1a 怎么样无限制输出一个比1大的数 xff1f span class token macro property span class token directive keyword include span span clas
  • 嵌入式开发打印,我放弃了printf

    已剪辑自 https mp weixin qq com s GGZ38dUITlS6w9hnMbzsvg 对于printf xff0c 相信不用我过多介绍 xff0c 大家在初学C语言时用得最多的信息输出接口函数应该就是printf了 对于
  • 自动驾仿真测试平台干货内容梳理

    已剪辑自 https mp weixin qq com s Ftv2rgiGW6FGVQgMz4A9PQ 1 自动驾驶仿真平台的关键构成 自动驾驶仿真平台需支持车辆动力学仿真 环境感知传感器仿真 交通场景仿真等 xff1b 车辆动力学仿真
  • 自动驾驶域控制器开发和量产的挑战

    已剪辑自 https mp weixin qq com s Sh4ONJxrmvDbfWlcDnXYtQ 过去十多年的汽车智能化和信息化发展产生了一个显著结果就是ECU芯片使用量越来越多 从传统的引擎控制系统 安全气囊 防抱死系统 电动助力
  • STM32属于哈佛结构还是冯诺依曼结构?

    现代的CPU基本上归为冯诺伊曼结构 xff08 也称普林斯顿结构 xff09 和哈佛结构 我们常见的X86架构是冯 诺依曼结构 xff0c 而ARM架构是哈佛结构 一个广泛用于桌面端 xff08 台式 笔记本 服务器 工作站等 xff09
  • 2022年度复盘和2023年目标:在焦虑中探索,在体验中成长,在开放中升华

    文章目录 2022年度复盘工作 xff1a 焦虑 xff0c 认知 xff0c 提升个人工作 xff1a 工作态度需要提升团队工作 xff1a 尊重 真诚 准确清晰完善感悟 个人成长硬能力 xff1a 学习 博客软能力 xff1a 知乎 B
  • 技术部门Leader是不是一定要技术大牛担任?

    现在在腾讯做技术Leader xff0c 之前在阿里 xff0c 绿厂也带过技术团队 xff0c 每家的情况有共同点也有区别 现在总结下来 xff0c 除去特别通用的技术 责任心 沟通 主动性这些 xff0c 作为Leader很关键的个人素
  • 一个人该怎样找到自己真正热爱和擅长的事,并以此规划自己的人生?

    文章目录 一个人该怎样找到自己真正热爱和擅长的事 xff0c 并以此规划自己的人生 xff1f 一 有关擅长的4个错误认知 二 做好这3步 xff0c 拥有擅长之事 1 生成兴趣清单 2 缩小选择范围 3 练练看 三 写在最后 下面这张图
  • 一个适用于单片机的开源网络协议栈

    已剪辑自 https mp weixin qq com s Vpi4E9T5BUo cdCE692V A 移植及使用说明 协议栈支持主流的ARM Cortex系列MCU xff0c 支持Keil MDK IAR等常见IDE 移植的核心工作就
  • 嵌入式软件分层隔离的典范

    已剪辑自 https mp weixin qq com s T7EJEAuXo1CCJa5vPAPVvg 引言 xff1a 嵌入式软件开发分层 模块化是理想状态 xff0c 实际开发中因各种限制而有所取舍 xff0c 但这不妨碍学习参考优秀
  • 软件定时器库

    前后台系统和多任务操作系统 xff0c 在简单功能上差别不大 xff0c 唯一不顺手的就是前后台系统没有合适的软件定时器 封装一层软件定时器接口 xff0c 对后续功能开发事半功倍 定义结构体数组 xff0c 其基础成员如下 xff1a s