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

电子说

1.3w人已加入

描述

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时钟的周期以及扫描周期决定。
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分