0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

简洁、小巧精干的软件定时器—microLite_timer

冬至子 来源:microLite裸机系统 作者:stevenLyan 2023-07-17 16:06 次阅读

01

扫描周期与时钟节拍

一般小型系统由Background和Foreground构成。Background称为任务区,Foreground称为中断区。对实时性要求很高的操作要由中断区的中断服务程序来完成。位于Background区域的任务响应时间取决于超级循环(Super-Loops)执行一次的时间,也称之为扫描周期ScanCycleTime。扫描周期并不固定,任务执行过程中扫描周期的最大值意味着任务最坏的响应时间。

图片

microLite裸机系统最小的时间单位是时钟节拍(Tick),时钟节拍是特定的周期性中断,这个中断可以看做是系统心跳,时钟节拍由硬件定时器产生,当中断到来时,将调用一次ml_tick_increase()。不同硬件定时器的中断实现不同,下面的中断函数以 STM32 定时器作为示例:

void SysTick_Handler(void)
{
    ml_tick_increase();
}

在中断函数中调用 ml_tick_increase()对全局变量 ml_tick 进行自加,代码如下:

void ml_tick_increase(void)
{
    ml_tick++;
}

通过调用 ml_tick_get会返回当前 ml_tick 的值,即可以获取到当前的时钟节拍值。此接口可用于获取系统的最大扫描周期,或者测量某任务运行的时间。接口函数如下:

ml_tick_t ml_tick_get(void)
{
    ml_tick_t t = 0;
    t = ml_tick;
    while (t != ml_tick) {
        t = ml_tick;
    }
    return t;
}

02

microLite_timer介绍

软件定时器microLite_timer提供两类定时器机制:

  • 第一类是周期触发定时器(MLPeriod),这类定时器会周期性的触发定时器,并且“一旦启动,永不停止”。
  • 第二类是单次触发定时器(MLShot),这类定时器在启动后只会触发一次定时器事件,然后定时器自动停止。

03

应用场景

周期触发定时器(MLPeriod),适用于对首次触发时间要求不严格的场合。比如,让LED以280ms周期性亮灭。这种情况下我们并不关心LED首次由灭到亮用了多长时间,我们只要求LED在以后的时间以准确的280ms周期性亮灭。

单次触发定时器(MLShot),适用于对首次触发时间要求严格的场合。另外MLshot定时器自动停止后,调用启动函数MLShot.start,亦可实现周期触发。

04

API接口

microLite_timer支持的MLPeriod接口主要包括:

  • MLPeriod.Init,初始化定时器;
  • MLPeriod.run;
  • MLPeriod.check,检查定时器是否超时。

microLite_timer支持的MLShot接口主要包括:

  • MLShot.start,启动定时器;
  • MLShot.stop,停止定时器;
  • MLShot.check,检查定时器是否超时。

05.1

MLPeriod编程范例

需求:让4个任务分别以1000ms、500ms、500ms、800ms周期性执行。

代码实现:

#include "microLite_timer.h"
#include "stdio.h"
void test1(void)
{
    MLPeriod.init();
    printf("microLite - Bare metal system, 2021 Copyright by stevenLyanrnrn");   
    printf("microLite timer sample, current tick is %d rn", ml_tick_get());
    while (1) {
        MLPeriod.run();
        if (MLPeriod.check(1000)) {
            printf("task1, current tick is %drn", ml_tick_get());
        }
        if (MLPeriod.check(500)) {
            printf("task2, current tick is %drn", ml_tick_get());
        }
        if (MLPeriod.check(500)) {
            printf("task3, current tick is %drn", ml_tick_get());
        }
        if (MLPeriod.check(800)) {
            printf("task4, current tick is %drn", ml_tick_get());
        }
    }
}

运行效果:

microLite - Bare metal system, 2021 Copyright by stevenLyan


microLite timer sample, current tick is 9 
task2, current tick is 513
task3, current tick is 515
task4, current tick is 813
task1, current tick is 1013
task2, current tick is 1015
task3, current tick is 1018
task2, current tick is 1513
task3, current tick is 1515
task4, current tick is 1613
task1, current tick is 2013
task2, current tick is 2015
task3, current tick is 2018
task4, current tick is 2413

05.2

MLShot编程范例

需求:见下面“代码实现”的注释。

代码实现:

#include "microLite_timer.h"
#include "stdio.h"
static ml_shotTimer_TypeDef test2_timer1 = {0};
static ml_shotTimer_TypeDef test2_timer2 = {0};
static ml_shotTimer_TypeDef test2_timer3 = {0};
void test2(void)
{ 
    printf("microLite - Bare metal system, 2021 Copyright by stevenLyanrnrn");
    printf("microLite timer sample, current tick is %d rn", ml_tick_get());
    MLShot.start(&test2_timer1, 800);
    MLShot.start(&test2_timer2, 500);
    while (1) {
        /*----------------------------------------------------------------------------*/
        /* Schedules the specified task for execution after the specified delay.
              [the specified delay]:  [timer1]800 ticks */
        if (MLShot.check(&test2_timer1)) {
            printf("timer1 stop(auto), current tick is %d!!!rn", ml_tick_get());
        }
        /*----------------------------------------------------------------------------*/
        /* Schedules the specified task for repeated fixed-delay execution, beginning
                 after the specified delay.
                    [the specified delay]:  [timer2]500 ticks
                [repeated fixed-delay]: [timer3]1000 ticks
            */
        if (MLShot.check(&test2_timer2)) {
            MLShot.start(&test2_timer3, 1000);
            printf("timer2 stop(auto) and timer3 start, current tick is %d!!!rn", ml_tick_get());
        }
        if (MLShot.check(&test2_timer3)) {
            MLShot.start(&test2_timer3, 1000);
            printf("timer3 timeout, current tick is %drn", ml_tick_get());
        }
    }
}

运行效果:

microLite - Bare metal system, 2021 Copyright by stevenLyan
microLite - Bare metal system, 2021 Copyright by stevenLyan


microLite timer sample, current tick is 9 
timer2 stop(auto) and timer3 start, current tick is 513!!!
timer1 stop(auto), current tick is 813!!!
timer3 timeout, current tick is 1514
timer3 timeout, current tick is 2515
timer3 timeout, current tick is 3516
timer3 timeout, current tick is 4517

06

注意事项

  • MLPeriod.run在一个扫描周期内,应被调用一次且仅一次;
  • 不建议将MLPeriod.check的参数设置为不固定值;
  • 不建议嵌套使用MLPeriod.check;
  • MLPeriod支持定时周期不同的定时器的个数为ML_PERIODTIMER_MAX;
  • MLShot触发后,定时器自动停止;
  • microLite_timer的定时精度由系统Tick时钟的周期以及扫描周期决定。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • led灯
    +关注

    关注

    22

    文章

    1592

    浏览量

    108157
  • 软件定时器
    +关注

    关注

    0

    文章

    18

    浏览量

    6776
  • 触发器
    +关注

    关注

    14

    文章

    2000

    浏览量

    61237
  • stm32定时器
    +关注

    关注

    0

    文章

    13

    浏览量

    2301
收藏 人收藏

    评论

    相关推荐

    GD32对Timer定时器原理的详细讲解

    GD32 Timr定时器看起来比较复杂啊。一看GD32E10x 的SPEC:一个高级定时器,三个通用定时器,还有一个基本定时器。 项目上想用来做分时处理程序都不知道用哪个? 就用通用的
    的头像 发表于 04-22 17:02 1.7w次阅读
    GD32对<b class='flag-5'>Timer</b><b class='flag-5'>定时器</b>原理的详细讲解

    为什么选择esp_timer定时器作为esp32首选软件定时器

    定时器(esp_imer)1、为什么选择esp_timer定时器作为esp32首选软件定时器2、esp_
    发表于 01-07 08:14

    51定时器计算软件

    MCS51_timer软件说明:快速计算MCS51系列单片机定时器时间常数。
    发表于 10-23 17:06 117次下载
    51<b class='flag-5'>定时器</b>计算<b class='flag-5'>软件</b>

    通用定时器(Timer)

    在 Stellaris 系列 ARM 内部通常集成有 2~4 个通用定时器模块(General-Purpose Timer Module,GPTM),分别称为 Timer0、Timer
    发表于 01-13 16:34 23次下载

    通用定时器(Timer

    通用定时器(Timer
    发表于 10-11 15:10 6次下载
    通用<b class='flag-5'>定时器</b>(<b class='flag-5'>Timer</b>

    通用定时器(Timer)总体特性的功能概述和详细的程序概述

    在Stellaris系列ARM内部通常集成有2~4个通用定时器模块(General-Purpose Timer Module,GPTM),分别称为Timer0、Timer1、
    发表于 05-09 10:32 8次下载
    通用<b class='flag-5'>定时器</b>(<b class='flag-5'>Timer</b>)总体特性的功能概述和详细的程序概述

    ESP8266的管脚的控制和软件定时器的使用

    先说定时器,ESP8266内部的定时器分为软件定时器和硬件定时器。手册中指出硬件定时器其实就跟单
    的头像 发表于 07-29 14:57 9546次阅读
    ESP8266的管脚的控制和<b class='flag-5'>软件</b><b class='flag-5'>定时器</b>的使用

    基于硬件定时器软件定时器

    概括硬件定时器很精确,软件定时器无论如何都有延迟,主要用在不需要精确定时的地方,而且软件定时比较
    发表于 11-25 09:51 8次下载
    基于硬件<b class='flag-5'>定时器</b>的<b class='flag-5'>软件</b><b class='flag-5'>定时器</b>

    ESP32 之 ESP-IDF 教学(三)——通用硬件定时器Timer

    ESP32 之 ESP-IDF 学习笔记(三)【通用硬件定时器Timer)】文章目录ESP32 之 ESP-IDF 学习笔记(三)【通用硬件定时器Timer)】通用硬件
    发表于 11-26 11:36 37次下载
    ESP32 之 ESP-IDF 教学(三)——通用硬件<b class='flag-5'>定时器</b>(<b class='flag-5'>Timer</b>)

    msp432快速入门第十节之timer32定时器

    纵观整个程序,主要是通过中断触发定时器来使LED亮1s(2)配置自己的函数第一步 配置定时器配置定时器Timer32: //配置timer3
    发表于 12-07 18:51 9次下载
    msp432快速入门第十节之<b class='flag-5'>timer</b>32<b class='flag-5'>定时器</b>

    FreeRTOS软件定时器的使用步骤

    FreeRTOS软件Timer有两种:重复性的和一次性的Timer软件定时器使用有3步。
    的头像 发表于 09-14 15:22 1920次阅读

    基础定时器实验

    STM32内部共有8个定时器,其中Timer1和Timer8属于高级定时器Timer2~Timer
    的头像 发表于 03-01 15:59 1223次阅读
    基础<b class='flag-5'>定时器</b>实验

    什么是软件定时器软件定时器的实现原理

    软件定时器是用程序模拟出来的定时器,可以由一个硬件定时器模拟出成千上万个软件定时器,这样程序在需
    的头像 发表于 05-23 17:05 2856次阅读

    STM32L4定时器(TIMER)介绍

    电子发烧友网站提供《STM32L4定时器(TIMER)介绍.pdf》资料免费下载
    发表于 08-01 14:24 0次下载
    STM32L4<b class='flag-5'>定时器</b>(<b class='flag-5'>TIMER</b>)介绍

    关于软件定时器的一些讨论

    这就是简单的软件定时器,是的,这就是特别简洁版本的软件定时器。当然它是有缺点的,比如systick_ms每1ms加1,所以
    的头像 发表于 10-13 16:14 580次阅读
    关于<b class='flag-5'>软件</b><b class='flag-5'>定时器</b>的一些讨论