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

一、简介

        软件定时器,是基于系统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:运行模式

osTimerOnce 0,单次
osTimerPeriodic 1,周期

        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秒的定时还是很准的。

猜你喜欢

转载自blog.csdn.net/qq_26226375/article/details/130519584