以下内容主要注重应用,对源码不做分析,对源码有兴趣的可参考官方具体文档,相关链接: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