鸿蒙Hi3861学习六-Huawei LiteOS(软件定时器)

news2024/11/15 10:36:15

一、简介

        软件定时器,是基于系统Tick时钟中断且由软件来模拟的定时器。当经过设定的Tick时钟计数值后,会触发用户定义的回调函数。定时精度与系统Tick时钟周期有关。

        硬件定时器受硬件的限制,数量上不足以满足用户的实际需求。因此,为了满足用户需求,提供更多的定时器,LiteOS提供软件定时器功能。

        软件定时器扩展了定时器的数量,允许创建更多的定时业务。

        软件定时器功能上支持:

  • 静态裁剪:能通过宏关闭软件定时器功能。
  • 软件定时器创建
  • 软件定时器启动
  • 软件定时器停止
  • 软件定时器删除
  • 软件定时器剩余Tick数获取

        更多概念可以参考:FreeRTOS学习六(软件定时器)_freertos 执行定时器回调函数的内存消耗将是在定时器任务堆栈上动态分配_t_guest的博客-CSDN博客

二、运作机制

        软件定时器使用了系统的一个队列一个任务资源,软件定时器的触发遵循队列规则,先进先出。定时时间短的定时器总是比定时时间长的靠近队列头,满足优先被触发的准则。

        软件定时器以Tick为基本计时单位,当用户创建并启动一个软件定时器时,LiteOS会根据当前系统Tick时间寄用户设置的定时间隔确定该定时器的到期Tick时间,并将该定时器控制结构挂入计时全局链表。

        当Tick中断到来时,在Tick中断处理函数中扫描软件定时器的计时全局链表,看是否有定时器超时,若有则将超时的定时器记录下来。

        Tick中断处理函数结束后,软件定时器任务(优先级最高)被唤醒,在该任务中调佣之前记录下来的定时器的超时回调函数

三、API介绍

      osTimerNew

        函数功能

        创建一个软件定时器

        函数原型

osTimerId_t osTimerNew(osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr)

        参数

        func:超时回调函数

        type:运行模式

osTimerOnce0,单次
osTimerPeriodic1,周期

        argument:传给定时器的参数。没有填NULL

        attr:定时器相关属性。自定义地址的时候会用到。大部分情况用不到,填NULL。

        返回值

        NULL:失败

        其他值:osTimerId_t类型的定时器ID。该ID给其他函数使用

        实例

osTimerPeriodic
char timer1_param[] = "timer1 param";
g_timer1_id = osTimerNew(Timer1_Callback, osTimerPeriodic, timer1_param, NULL);

      osTimerStart

        函数功能

        软件定时器启动

        函数原型

osStatus_t osTimerStart(osTimerId_t timer_id, uint32_t ticks)

        参数

        timer_id:软件定时器ID,创建时osTimerNew获得

        ticks:软件定时器的定时周期。对于Hi3861,定时器单位为10ms

        返回值

        osOK:成功

        其他值:失败

typedef enum {
  /** Operation completed successfully */
  osOK                      =  0,
  /** Unspecified error */
  osError                   = -1,
  /** Timeout */
  osErrorTimeout            = -2,
  /** Resource error */
  osErrorResource           = -3,
  /** Incorrect parameter */
  osErrorParameter          = -4,
  /** Insufficient memory */
  osErrorNoMemory           = -5,
  /** Service interruption */
  osErrorISR                = -6,
  /** Reserved. It is used to prevent the compiler from optimizing enumerations. */
  osStatusReserved          = 0x7FFFFFFF
} osStatus_t;

        实例

osTimerId_t g_timer1_id;
timerDelay = 100U;
status = osTimerStart(g_timer1_id, timerDelay);

      osTimerStop

        函数功能

        软件定时器停止

        函数原型

osStatus_t osTimerStop(osTimerId_t timer_id)

        参数

        timer_id 定时器ID

        返回值

        osOK:成功

        其他值:失败

        实例

osTimerId_t g_timer1_id;
osTimerStop(g_timer1_id);

      osTimerDelete

        函数功能

        软件定时器删除

        函数原型

osStatus_t osTimerDelete(osTimerId_t timer_id)

        参数

        timer_id 定时器ID

        返回值

        osOK:成功

        其他值:失败

        实例

osTimerId_t g_timer1_id;
osTimerDelete(g_timer1_id);

四、代码实例

        此代码创建两个软件定时器,定时器1为循环定时器,定时器2为单次定时器

#define LOG_I(fmt, args...)   printf("<%8ld> - [TIMER]:"fmt"\r\n",osKernelGetTickCount(),##args);
#define LOG_E(fmt, args...)   printf("<%8ld>-[TIMER_ERR]>>>>>>>>>>>>:"fmt"\r\n",osKernelGetTickCount(), ##args);

osTimerId_t g_timer1_id;
osTimerId_t g_timer2_id;

/***** 定时器1 回调函数 *****/
void Timer1_Callback(void *arg)
{
    static uint8_t cnt = 0;
    LOG_I("timer1 callback,cnt:%d,param:%s",cnt,arg);
    if(cnt++ > 10)
    {
        osTimerDelete(g_timer1_id);
        LOG_I("timer1 delete");
    }
    else if(cnt == 3)
    {
        osTimerStop(g_timer1_id);
        LOG_I("timer1 stop and restart timer2");
        osTimerStart(g_timer2_id, 500);
    }
}

/***** 定时器2 回调函数 *****/
void Timer2_Callback(void *arg)
{
    LOG_I("timer2 callback,param:%d",*(uint32_t *)arg);

    osTimerStart(g_timer1_id, 100);
    LOG_I("start timer1");
}

char timer1_param[] = "timer1 param";
uint32_t timer2_param = 1024;

void Hello_World(void)
{
    LOG_I("Test software Timer");

    uint32_t timerDelay;
    osStatus_t status;

/*timer 1*/
    g_timer1_id = osTimerNew(Timer1_Callback, osTimerPeriodic, timer1_param, NULL);
    if (g_timer1_id != NULL)
    {
        // Hi3861 1U=10ms,100U=1S
        timerDelay = 100U;

        status = osTimerStart(g_timer1_id, timerDelay);
        if (status != osOK)
        {
            LOG_E("timer1 start error");        
        }
        else
        {
            LOG_I("timer1 start success,cycle:%dms",timerDelay * 10);
        }
    }
    else
    {
        LOG_E("timer1 create fail!!!");
    }

/*timer 2*/
    g_timer2_id = osTimerNew(Timer2_Callback, osTimerOnce, (void *)&timer2_param, NULL);
    if (g_timer2_id != NULL)
    {
        // Hi3861 1U=10ms,100U=1S
        timerDelay = 500U;

        status = osTimerStart(g_timer2_id, timerDelay);
        if (status != osOK)
        {
            LOG_E("timer2 start error");
        }
        else
        {
            LOG_I("timer2 start success,cycle:%dms",timerDelay * 10);
        }
    }
    else
    {
        LOG_E("timer2 create fail!!!");
    }
}

        定时器1为循环定时器,循环周期为1秒,定时器2为单次定时器,超时时间为5秒。两个定时器同时启动。在定时器1第三秒的时候,会停止自己,并且重新启动定时器2。定时器2超时后会重新启动定时器1。定时器1在第10次时会删除自己。

        看运行结果:

         可以看到,虽然定时器2在运行,但是如果此时再次调用osTimerStart来启动定时器2,会刷新定时器的超时时间

        这里我们用软件打印当前的时间戳,来看一下1秒的定时周期是否准确。

         可以看到1秒的定时还是很准的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/494408.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【算法】什么是离散化

作者&#xff1a;指针不指南吗 专栏&#xff1a;算法篇 &#x1f43e;人类做题的过程&#xff0c;就是个暴搜的过程&#x1f43e; 文章目录 1.引入2.思路3.模板题 1.引入 特指有序、整数的离散化。 离散化&#xff0c;本质上是一种哈希&#xff0c;它在保持原序列大小关系的前…

肝一肝设计模式【六】-- 装饰器模式

系列文章目录 肝一肝设计模式【一】-- 单例模式 传送门 肝一肝设计模式【二】-- 工厂模式 传送门 肝一肝设计模式【三】-- 原型模式 传送门 肝一肝设计模式【四】-- 建造者模式 传送门 肝一肝设计模式【五】-- 适配器模式 传送门 文章目录 系列文章目录前言一、什么是装饰器模…

PLSQL Developer远程连接Oracle报错提示:“ORA-12541:TNS:无监听程序”的解决方案及思路

环境&#xff1a; 1、Windows Server 2、远程Oracle数据库&#xff1a;Oracle11g R2 3、PL/SQL程序&#xff1a;PL/SQL Developer Version 11.0.5.1790 (64 bit) 一、思路拆解&#xff1a; 此现象一般定位到远端的监听服务来找问题&#xff0c;在远端查看监听服务状态&#x…

DolphinScheduler 3.1.4详细教程

文章目录 第一章 DolphinScheduler介绍1.1 关于DolphinScheduler1.2 特性1.3 名词解释1.3.1 名词解释1.3.2 模块介绍 第二章 DolphinScheduler系统架构2.1 系统架构图2.2 架构说明该服务包含&#xff1a; 2.3 启动流程活动图2.4 架构设计思想2.4.1 去中心化vs中心化2.4.1.1 中心…

制作帮助中心过程中常见的误区与解决方法?

制作帮助中心是为了帮助用户了解产品和解决问题的重要手段。然而&#xff0c;在制作的过程中&#xff0c;我们可能会遇到一些误区&#xff0c;这些误区可能会导致我们的帮助中心无法达到预期的效果。因此&#xff0c;在本文中&#xff0c;我们将探讨制作帮助中心过程中常见的误…

今年产品经理这么卷,大家怎么面试的呢?

随着互联网行业的快速发展&#xff0c;产品经理这个职位变得越来越重要。产品经理需要具备多方面的能力&#xff0c;如市场调研、用户需求分析、产品设计、项目管理等等。因此&#xff0c;对于企业来说&#xff0c;招聘一名合适的产品经理是非常关键的。 而对于求职者来说&…

中国奇人周兴和——记四川星河建材有限公司董事长周兴和(中)

经商送礼 关押收审 从10多岁就开始闯荡社会的周兴和&#xff0c;可以说是社会大熔炉锻炼出来的奇人。他仅有小学文化程度&#xff0c;但是他的社会经验和社会知识却相当丰富&#xff0c;可以称得上是一个“社会学专家”。他口才超常&#xff0c;其处事能力、应变能力和综合能力…

ASEMI代理ADUM1250ARZ-RL7原装ADI车规级ADUM1250ARZ-RL7

编辑&#xff1a;ll ASEMI代理ADUM1250ARZ-RL7原装ADI车规级ADUM1250ARZ-RL7 型号&#xff1a;ADUM1250ARZ-RL7 品牌&#xff1a;ADI/亚德诺 封装&#xff1a;SOIC-8-150mil 批号&#xff1a;2023 引脚数量&#xff1a;8 工作温度&#xff1a;-40C~105C 安装类型&#…

4.7亿加元!爱立信和加拿大政府巨额投资量子计算

​ &#xff08;图片来源&#xff1a;网络&#xff09; 爱立信与加拿大政府的研发合作为期五年&#xff0c;项目价值超过4.7亿加元&#xff08;约合23.9亿元人民币&#xff09;&#xff0c;主要投入在爱立信位于安大略省渥太华和魁北克省蒙特利尔的工厂。预计将创造数百个工作…

三十岁成功入职京东啦!

我是小九小九不爱喝酒&#xff1a; 自己工作5年后&#xff0c;我成功拿到了京东的offer。下面说下我是如何从传统行业到京东的经历&#xff0c;希望能对你有所帮助。 本科我学的是机械电子工程专业&#xff0c;2013年本科毕业后&#xff0c;同学们大多到各研究所从事智能机器人…

真题详解(归纳法)-软件设计(六十七)

真题详解(关系模型)-软件设计&#xff08;六十六)https://blog.csdn.net/ke1ying/article/details/130495791 1、2018上半年 将小阶向大阶对奇&#xff0c;尾数右移动 解析&#xff1a; 0.23 * 10的2次方 0.22 *10的3次方 第一步&#xff1a;0.023*10的3次方&#xff0c;…

2022年收入增长23%,23年Q1大涨85%,上市后英方软件交出了一份亮眼的答卷

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 2023年4月26日&#xff0c;英方软件&#xff08;688435&#xff09;公布了上市后首个业绩报告&#xff0c;包括2022年度财报和2023年第一季度财报。披露财报显示&#xff0c;英方软件在2022年实现营业收入1.97亿元&#xff…

ZC706P试验PL_DDR3内存条的步骤方法

ZC706P 板卡完全兼容XILINX官方的ZC706,当然也支持PL外挂的1G的DDR3内存条&#xff0c;这个片BLOG我提供从官方下载的一个文档和一个项目&#xff0c;演示一下验证DDR3的步骤。 步骤1&#xff1a;准备好板子&#xff0c;安装好软件。 链接&#xff1a;https://pan.baidu.com/s…

《创造》人生旅程

上个月读完的这本《创造》&#xff0c;发现作者是iPod的创造者&#xff0c;让我回想起我刚工作时买的iPod。iPod确是惊艳之作&#xff0c;那时我一个月挣1000元&#xff0c;竟毫不犹豫花了2000就买了&#xff0c;并一直伴随我直到进入智能手机时代。《创造》会写什么&#xff1…

日志项目之——将kafka数据存入hbase中

目录 1.添加依赖 2.在hbase shell界面中分别输入下面的语句&#xff0c;创建namespace和表 3.UserFriendToHB 4.UsersToHB 5.TrainToHB 6.EventsToHB 7.EventAttendeToHb 1.添加依赖 <dependencies><dependency><groupId>junit</groupId><a…

软考信管高级——成本管理

成本管理内容 成本基准 成本基准是经过批准的&#xff0c;不包括管理储备&#xff0c;只有正式变更流程才能变更成本基准成本基准管理储备项目预算&#xff0c;有必要动用管理储备变更时&#xff0c;获变更批准后&#xff0c;把适量管理储备移入成本基准中 应急储备和管理储备…

Map接口以及Collections工具类

文章目录 1.Map接口概述1.1 Map的实现类的结构1.2 Map中存储的key-value结构的理解1.3 HashMap的底层实现原理(以JDK7为例)1.4 Map接口的常用方法1.5 TreeMap1.6 Map实现类之五: Properties 1.Collections工具类1.1方法1.1.1 排序操作(均为static方法)1.1.2 查找、替换 1.Map接…

PMP项目管理-[第八章]质量管理

质量管理知识体系&#xff1a; 规划质量管理&#xff1a; 管理质量&#xff1a; 控制质量 &#xff1a; 8.1 质量和等级的区别 质量定义&#xff1a;作为实现的性能或成果&#xff0c;是一系列内在特性满足要求的程度 等级定义&#xff1a;作为设计意图&#xff0c;是对用途相同…

Android 历代版本主要变化

这里只站在开发者的角度&#xff0c;谈论一下 Android 5.0 之后的版本的主要变化 Android 5.0 L 开始支持64位的处理器开始全面由 Dalvik 虚拟机转成ART虚拟机 Android 6.0 M 增加全新的动态权限机制&#xff08;运行时权限&#xff09;取消支持 Apache HTTP 客户端 Andro…

队列,双端队列,栈结构

java.util.Queue接口.队列 Queue继承自Collection. 队列可以保存一组元素,但是存取元素必须遵循先进先出原则:FIFO(First Input First Output) 常用实现类:LinkedList 双端队列 java.util.Deque Deque继承自Queue 双端队列是队列两端都可以做出入对操作的队列. 常用实现类…