[TOC]

UCOS-Ⅲ:软件定时器

一、定时器基本概念

​ 软件定时器是建立在硬件定时器的基础上,软件定时器只要设置一个硬件的定时器,通过软件分频和系统的管理即可得到多个软件定时器,理论上只要单片机内存足够,可以扩展到无限多个,不过精度会下降(原因:软件定时器的定时过程中是极有可能被其它中断所打断)

​ 他与硬件定时器的运行区别如下:硬件定时器时,每次在定时时间到达之后就会自动触发一个中断,用户在中断中处理信息;而使用软件定时器时,需要我们在创建软件定时器时指定时间到达后要调用的函数(也称超时函数/回调函数,为了统一,下文均用回调函数描述),在回调函数中处理信息

软件定时器回调函数的上下文是任务,其回调函数类似硬件的中断服务函数,所以回调函数要快进快出,而且回调函数中不能有任何阻塞任务运行的情况

​ 软件定时器的精度( 分辨率) 决定于系统时基频率, 也就是变量OS_CFG_TMR_TASK_RATE_HZ 的值,而且定时器所定时的数值必须是这个定时器任务精度的整数倍,例如,定时器任务的频率为10HZ,那么上层软件定时器定时数值只能是100ms,200ms,1000ms 等,而不能取值为150ms

二、调用API

创建函数OSTmrCreate()

函数OSMutexCreate 用来创建mutex

1
2
3
4
5
6
7
8
void  OSTmrCreate (OS_TMR               *p_tmr,          //定时器控制块指针
CPU_CHAR *p_name, //命名定时器,有助于调试
OS_TICK dly, //初始定时节拍数
OS_TICK period, //周期定时重载节拍数
OS_OPT opt, //选项
OS_TMR_CALLBACK_PTR p_callback, //定时到期时的回调函数
void *p_callback_arg, //传给回调函数的参数
OS_ERR *p_err) //返回错误类型

函数参数功能:

参数 作用
p_tmr 用户自定义的定时器变量。
p_name 用户给定时器起的名字,方便调试。
opt 可以为OS_OPT_TMR_ONE_SHOT 或者OS_OPT_TMR_PERIODIC,OS_OPT_TMR_PERIODIC 为定时器到定时时间后重复调用回调函数,OS_OPT_TMR_ONE_SHOT 则只调用一次回调函数就停止
dly 如果上面的选项是OS_OPT_TMR_ONE_SHOT,那么dly 就是这个定时器定时的时间。如果是OS_OPT_TMR_PERIODIC,而且dly 不为0,则第一次延时的时间就是dly(为0为0延时初始化定时器,为其他则为延时对应时间启动)
period 如果选项是OS_OPT_TMR_PERIODIC,那么第一次过后每次定时的时间都是period 这么长。而且如果选项是OS_OPT_TMR_PERIODIC 且dly 是0 的话,那么定时器第 一次延时的时间也是period。
p_callback 回调函数指针。定时器每次到期的时候都可以执行指定的回调函数,可以在创建的时候设置,回调函数跟钩子函数有很大的相似。回调函数一个很好的定义如下。“回调函数是由用户撰写,而由操作系统调用的一类函数,回调函数可以把调用者和被调用者分开,调用者(例如操作系统)不需要关心被调用者到底是哪个函数,它所知道的就是有这么一类函数,这类满足相同的函数签名(函数原型,参数,返回值等),由用户书写完毕后在被调用就可以了。一般来讲:回调函数都是基于某种消息驱动,在获取相应消息时调用该函数你只要把你的函数写好并把地址传过去就行,至于如何调用你的函数,那你不需要管,调用部分的代码不是你写。
p_callback_arg 回调函数传递的参数。
p_err 指向返回错误类型的指针,主要有以下几种类型。

返回错误类型

错误类型 作用
OS_ERR_NONE 没有错误。
OS_ERR_ILLEGAL_CREATE_RUN_TIME 在定义OSSafetyCriticalStartFlag 为DEF_TRUE 后 就不运行创建任何内核对象,包括软件定时器。
OS_ERR_OBJ_CREATED 该软件定时器已经被创建过了,但是函数中没有这 个错误相关代码。
OS_ERR_OBJ_PTR_NULL 参数p_tmr 是个空指针。
OS_ERR_OPT_INVALID 参数opt 没有在规定的范围内。
OS_ERR_TMR_INVALID_DLY 创建的是一次性定时器,但是参数dly 为0。
OS_ERR_TMR_INVALID_PERIOD 创建的是周期性定时器,但是参数peroid 为0。
OS_ERR_TMR_ISR 在中断中创建定时器。

使用实例:

1
2
3
4
5
6
7
8
9
10
OS_TMR      my_tmr;   //声明软件定时器对象
/* 创建软件定时器 */
OSTmrCreate ((OS_TMR *)&my_tmr, //软件定时器对象
(CPU_CHAR *)"MySoftTimer", //命名软件定时器
(OS_TICK )10, //定时器初始值,依10Hz时基计算,即为1s
(OS_TICK )10, //定时器周期重载值,依10Hz时基计算,即为1s
(OS_OPT )OS_OPT_TMR_PERIODIC, //周期性定时
(OS_TMR_CALLBACK_PTR )TmrCallback, //回调函数
(void *)"Timer Over!", //传递实参给回调函数
(OS_ERR *)err); //返回错误类型

启动软件定时器函数OSTmrStart()

除了要创建定时器之外,还需要调用启动定时器的函数OSTmrStart,启动函数OSTmrStart 的使用只要输入创建的定时器的变量的指针就能启动

1
2
CPU_BOOLEAN  OSTmrStart (OS_TMR  *p_tmr,  //定时器控制块指针
OS_ERR *p_err) //返回错误类型

参数

参数 功能z
p_tmr 指向定时器对象的指针。
p_err 指向返回错误类型的指针,主要有以下几种类型。(只包含部分)

返回错误类型

错误类型 功能
OS_ERR_NONE 没有错误。
OS_ERR_OBJ_TYPE 参数p_tmr 没有指向一个定时器类型的变量。
OS_ERR_TMR_INVALID 参数p_tmr 是空指针。
OS_ERR_TMR_INACTIVE 使用定时器没有先初始化,即没有先创建定时器,也可能 是定时器已经被删除
OS_ERR_TMR_INVALID_STATE 定时器的状态不可用。
OS_ERR_TMR_ISR 企图在中断中启动定时器。 创建完必须要再使用这个函数才可以运行定时器。如果是正在运行中的定时器再调用 启动函数,就会达到重启的效果。下面首先介绍下定时器的状态。
OS_TMR_STATE_UNUSED 定时器已经被删除
OS_TMR_STATE_STOPPED 停止一个定时器,刚刚创建完也是这个状态
OS_TMR_STATE_RUNNING 正常运行
OS_TMR_STATE_COMPLETED 定时完成,一次性地定时器才会有这种状态,因为重复性的 定时器不可能自然地停止,用启动函数可以重新启动。

使用实例:

1
2
3
/* 启动软件定时器 */						 
OSTmrStart ((OS_TMR *)&my_tmr, //软件定时器对象
(OS_ERR *)err); //返回错误类型

停止定时器函数OSTmrStop()

OSTmrStop() 函数用于停止一个软件定时器。软件定时器被停掉之后可以调用OSTmrStart()函数重启,但是重启之后定时器是从头计时,而不是接着上次停止的时刻继续计时,函数入口如下:

1
2
3
4
CPU_BOOLEAN  OSTmrStop (OS_TMR  *p_tmr,          //定时器控制块指针
OS_OPT opt, //选项
void *p_callback_arg, //传给回调函数的新参数
OS_ERR *p_err) //返回错误类型

参数

参数 功能
p_tmr 定时器变量指针。
opt 停止定时器时候的设置,主要有以下的几个选项。
p_err 指向返回错误类型的指针。
p_callback_arg 若上面的选项设置是OS_OPT_TMR_CALLBACK_ARG,则这个函数将作为回调函数的用户参数,即使创建定时器的时候设置了用户参数。其他的选项,这个变量可以随便设置。

OPT配置

选项 功能
OS_OPT_TMR_CALLBACK 停止的时候调用回调函数,并且回调函数的用户参数是创建 定时器设置的。
OS_OPT_TMR_CALLBACK_ARG 停止的时候调用回调函数,回调函数的用户参数是根据输 入参数callback_arg 设置的。
OS_OPT_TMR_NONE: 停止的时候不执行回调函数。

错误类型

错误类型 含义
OS_ERR_TMR_INACTIVE 定时器已经被删除
OS_ERR_TMR_INVALID 参数p_tmr 是空指针
OS_ERR_TMR_INVALID_STATE 定时器状态不可用
OS_ERR_TMR_ISR 在中断中调用了这个函数
OS_ERR_TMR_NO_CALLBACK 回调函数的指针p_fnct 是空指针
OS_ERR_TMR_STOPPED 定时器已经停止了

使用实例

1
2
3
4
OSTmrStop(&my_tmr,
OS_OPT_TMR_CALLBACK_ARG ,
0,
&err);

删除软件定时器函数OSTmrDel()

OSTmrDel()用于删除一个已经被创建成功的软件定时器,删除之后就无法使用该定时
器,并且定时器相应的信息也会被系清空

1
2
CPU_BOOLEAN  OSTmrDel (OS_TMR  *p_tmr, //定时器控制块指针
OS_ERR *p_err) //返回错误类型

参数

参数 功能
p_tmr 指向定时器变量的指针。
p_err 指向返回错误类型的指针,主要有以下几种类型。

错误类型

错误 功能
OS_ERR_NONE 没有错误
OS_ERR_OBJ_TYPE 参数p_tmr 没有指向一个定时器变量
OS_ERR_TMR_INVALID 参数p_tmr 是个空指针
OS_ERR_TMR_ISR 企图再中断中删除定时器
OS_ERR_TMR_INACTIVE 定时器还没有被创建或者已经被删除
OS_ERR_TMR_INVALID_STATE 定时器的状态不可用

使用实例

1
2
OSTmrDel(&my_tmr,
&err);

获得定时器的剩余期限值OSTmrRemainGet()

调用OSTmrRemainGet 这个函数来获取定时器剩下的定时时间

1
OS_TICK  OSTmrRemainGet (OS_TMR  *p_tmr,                         OS_ERR  *p_err)

使用方式

1
OS_TICK time;time= OSTmrRemainGet(&my_tmr					 &err);

获得定时器当前的状态OSTmrStateGet()

获取定时器状态的函数OSTmrStateGet 同样是输入定时器变量指针和指向存放错误类型的指针就可以返回定时器的状态。

1
OS_STATE  OSTmrStateGet (OS_TMR  *p_tmr,                         OS_ERR  *p_err)

定时器状态有如下几种

状态 含义
OS_TMR_STATE_UNUSED 定时器未被创建
OS_TMR_STATE_STOPPED 定时器创建但未开启或者已经停止
OS_TMR_COMPLETED 定时器出于只执行一次状态,并且已经执行完成
OS_TMR_RUNNING 定时器当前正在运行

软件定时器任务

软件定时器的回调函数的上下文是在任务中,所有,系统中必须要一个任务来管理所有的软件定时器,等到定时时间到达后就调用定时器对应的回调函数,那么软件定时器任务就是系统提供的一个任务,它在系统初始化的时候,系统就帮我们创建的一个任务,用来管理定时器的回调函数,该任务在uC/OS初始化时就创建(前提是将定时器的裁剪宏定义打开),不需要我们自己进行创建,写在这用来提示一下他的运作流程,有兴趣可以扒源码研究

wechat