μC/OS-II系统中软件定时器的使用

以下内容主要注重应用,对源码不做分析,对源码有兴趣的可参考官方具体文档,相关链接:https://doc.micrium.com/display/ucos/

编译环境:Atollic TrueSTUDIO for STM32 9.3.0

硬件:基于STM32F103VET6单片机(使用HAL库)

一、介绍

  在os_tmr.c中可以找到处理定时器的代码。在os_cfg.h中将OS_TMR_EN设置为1时,将启用定时器服务。

  定时器是当计数器达到0时执行一个动作的计数器。用户通过回调函数(或简单地回调)提供操作。回调是一个用户声明的函数,当定时器到期时将被调用。回调可以用来打开或关闭灯,启动电机,或执行其他操作。但是,永远不要在回调函数内进行阻塞调用(例如,调用OSTimeDly()、OSTimeDlyHMSM()、OS?? Pend()或任何会导致定时器任务阻塞或被删除的调用),这一点很重要。

  应用程序可以有任意数量的计时器(仅受可用RAM的限制,当然也可以由用户在启动定时器服务的时候设定最大的定时器数量)。

  如果tick速率是1000 Hz,而所需的timer速率是10 Hz,那么timer任务将每100个tick中断一次被通知。

  定时器启动的三种模式:

  1、单次(One-Shot Timers)

  一次性定时器将从初始值开始倒数,当它达到0时调用回调函数,然后停止。下图显示了此操作的时序图。倒计时是通过调用OSTmrStart()来启动的。在时间延迟完成时,将调用回调函数,假设在创建定时器时提供了一个回调函数。一旦完成,定时器不会做任何事情,除非通过调用OSTmrStart()重新启动,此时进程将重新开始。

  可以通过调用OSTmrStop()来终止定时器的倒计时过程(在它达到0之前)。在这种情况下,可以指定是否调用回调函数。

  可以通过调用OSTmrStart()在计时器达到零之前重新触发一次性计时器。该特性可用于实现监视程序和类似的安全措施。

   2、周期,没有初始的延时(Periodic ,no initial delay)

  定时器可以配置为周期模式。当倒计时结束时,回调函数被调用,定时器被自动重新加载,并且这个过程被重复。如果在创建定时器时指定延迟为零(即,dly == 0),并且在启动时,计时器立即使用“period”作为重新加载值。可以在倒计时的任何时候调用OSTmrStart()来重新启动进程。

   3、周期,有最初的延时(Periodic ,with initial delay)

  定时器可以配置为周期模式,其初始延迟与其周期不同。第一个倒计时计数来自于在OSTmrCreate()调用中传递的“dly”参数,重载值是“period”。可以调用OSTmrStart()来重启进程,包括初始延迟。

二、创建并指定定时器的操作模式,OSTmrCreate()

  在使用定时器之前,需要先创建定时器。可以通过调用OSTmrCreate()来创建定时器,并根据定时器的操作方式为该函数指定大量参数。指定定时器操作后,除非删除并重新创建定时器,否则无法更改其操作模式。定时器一旦创建,就可以根据需要经常启动(或重新启动)和停止。定时器可以创建在三种模式中的一种:单次,周期(没有初始延时)和周期(有初始延时)。函数原型为:

OS_TMR OSTmrCreate (INT32U           dly,              /* Initial delay        */
                    INT32U           period,           /* Repeat period        */
                    INT8U            opt,              /* Options              */
                    OS_TMR_CALLBACK  callback,         /* Fnct to call at 0    */
                    void             *callback_arg,    /* Arg. to callback     */
                    CPU_CHAR         *pname,           /* Name of timer, ASCII */
                    INT8             *perr)
  • dly是初始延时。如果定时器配置为单次模式,这是使用的超时。如果定时器配置为周期模式,这是在定时器开始进入周期模式之前等待的第一个超时;
  • period是定时器周期模式下的超时值;
  • opt是定时器的模式。模式有两种:OS_TMR_OPT_ONE_SHOT 定时器只执行一次;OS_TMR_OPT_PERIODIC 定时器周期性执行;
  • callback是一个回调函数的指针,当定时器超时时将被调用。回调函数声明格式:void MyCallback (OS_TMR *ptmr, void *p_arg);
  • callback_arg是一个回调函数的指针,在定时器停止时会被用到。通常不指定要调用的函数
  • pname是定时器的名字;
  • perr是保存的错误类型;
  • 返回值是一个指向OS_TMR数据结构的指针,这是应用程序用来引用创建的定时器的句柄。

三、启动(或重新启动)定时器,OSTmrStart()

  启动定时器或者在定时器计时未结束前复位计时器,函数原型:

  1、BOOLEAN  OSTmrStart (OS_TMR   *ptmr, INT8U    *perr)

  • ptmr是指向OS_TMR数据结构的指针;
  • perr保存错误类型。

四、停止定时器的倒计时过程,OSTmrStop()

  停止定时器,函数原型:

  1、BOOLEAN  OSTmrStop (OS_TMR  *ptmr, INT8U    opt, void    *callback_arg, INT8U   *perr)

  • ptmr是指向OS_TMR数据结构的指针;
  • opt是停止定时器要进行的操作。操作方式有三种:OS_TMR_OPT_NONE 停止定时器什么也不做;OS_TMR_OPT_CALLBACK 停止定时器执行回调函数,将创建定时器时指定的回调函数传递给它;OS_TMR_OPT_CALLBACK_ARG 停止定时器执行回调函数,向它传递在此函数调用中指定的回调函数。
  • callback_arg 在OS_TMR_OPT_CALLBACK_ARG 模式下需要传递的回调函数;
  • perr保存错误类型。

五、示例代码

  1、启动定时器服务配置

#define OS_TMR_EN                 1    /* Enable (1) or Disable (0) code generation for TIMERS         */
#define OS_TMR_CFG_MAX           16    /*     Maximum number of timers                                 */
#define OS_TMR_CFG_NAME_EN        1    /*     Determine timer names                                    */
#define OS_TMR_CFG_WHEEL_SIZE     8    /*     Size of timer wheel (#Spokes)                            */
#define OS_TMR_CFG_TICKS_PER_SEC 10    /*     Rate at which timer management task runs (Hz)            */

  2、定义一个定时器指针:

/* 定义一个软件定时器 */
OS_TMR *SoftwareTmr;

  3、创建定时器(μC/OS系统的时钟节拍是1ms),第一次100ms后执行回调函数,之后以100ms为周期执行回调函数,如果创建成功就启动定时器:

    SoftwareTmr = OSTmrCreate(1, 1, OS_TMR_OPT_PERIODIC, TmrCallback, (void *)0, (INT8U *)"softwareTmr", &err);
    if(err == OS_ERR_NONE)
    {
        /* 启动软件定时器 */
        OSTmrStart(SoftwareTmr, &err);
    }

  4、定义定时器调用的回调函数,函数中执行LED灯闪烁:

static void TmrCallback(void *ptmr, void *callback_arg)
{
    HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);
}

#endif

原文地址:https://www.cnblogs.com/wenhao-Web/p/13870828.html