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

news/2024/11/9 10:07:36/

一、简介

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

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

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

        软件定时器功能上支持:

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

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

        Timer Management

二、运作机制

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

        软件定时器以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=1StimerDelay = 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=1StimerDelay = 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.ppmy.cn/news/82144.html

相关文章

PyTorch实战4:猴痘病识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f366; 参考文章&#xff1a;365天深度学习训练营-第P4周&#xff1a;猴痘病识别&#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 目录 一、搭建CNN网络结构1、原文网络结构1.1、网络…

python自动化(一)基础能力:9.yaml文件详解

一、什么是yaml文件 yaml 是专门用来写配置文件的语言——可以用例作为自动化框架的配置文件yaml文件其实也是一种配置文件类型&#xff0c;后缀名是.yaml或.yml都可以个人认为比yaml比json格式更方便 二、yaml语法规则 YAML 语言&#xff08;发音 /ˈjməl/ &#xff09;的设…

java版鸿鹄工程项目管理系统 Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统源代码

鸿鹄工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离构建工程项目管理系统 1. 项目背景 一、随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性&#xff0c;公司对内部工程管…

【每日一题Day217】LC2451差值数组不同的字符串 | 枚举+变量记录

差值数组不同的字符串【LC2451】 给你一个字符串数组 words &#xff0c;每一个字符串长度都相同&#xff0c;令所有字符串的长度都为 n 。 每个字符串 words[i] 可以被转化为一个长度为 n - 1 的 差值整数数组 difference[i] &#xff0c;其中对于 0 < j < n - 2 有 dif…

微签助力中融基金电子文件安全高效签章

中融基金重安全&#xff0c;炼丹炉里炼微签 这次讲一个微签在炼丹炉里炼出了火眼金睛的故事。 先看一个数字。 金融隐私泄露事件大约以每年35&#xff05;的数据在增长。 数字来自《中国银行保险报》与亚信网络安全产业技术研究院发布的《金融行业网络安全白皮书》。 大数据时…

Ubuntu TDengine集群搭建

我这里用三台服务器搭建集群 1、如果搭建集群的物理节点上之前安装过TDengine先卸载清空&#xff0c;直接执行以下4条命令 rmtaos rm -rf /var/lib/taos rm -rf /var/log/taos rm -rf /etc/taos2、确保集群中所有主机开放端口 6030-6043/tcp&#xff0c;6060/tcp&#xff0c;…

Java 远程连接 SQLite 数据库

Java 可以使用 JDBC API 来连接 SQLite 数据库。但是&#xff0c;SQLite 不支持远程连接&#xff0c;因为它是一种文件数据库&#xff0c;需要直接访问数据库文件。 如果您需要从远程位置访问 SQLite 数据库&#xff0c;可以将 SQLite 数据库文件放在共享文件夹中&#xff0c;…

高精度加法

给定两个正整数&#xff08;不含前导 0&#xff09;&#xff0c;计算它们的和。 输入格式 共两行&#xff0c;每行包含一个整数。 输出格式 共一行&#xff0c;包含所求的和。 数据范围 1≤整数长度≤100000 输入样例&#xff1a; 12 23 输出样例&#xff1a; 35 代码: #incl…