我本身也是个初学者,喜欢嵌入式而自学ucos系统,ucos是个开源的代码,短小而又简单,这是我学习的笔记,希望能对喜欢ucos的人有一点帮助,因本人也是初学者,如有错误迎指点。一般的书多是2.5版本,没有os_tmr.c,所以我写了关于这部分代码的分析。
我读ucos.中的os_tmr.c:
我想这个文件里就是为了写一个建立在操作系统的定时器,原来我们学的时钟节拍就像cpu总线时钟脉冲一样。我们建立的是定时器结构体,在os_tmr.c中有一个函数OSTmr_Task()这个函数对定时器结构体的信息进行处理,在定时时间到了时候,该定时器中的一个指向回调函数的指针就调用这个回调节器函数进行工作,当然,你要写回调函数,不然就什么也不做,以前做过ucos移植的人知道要写一个硬件定时器中断函数,这回要加个OSTmrSignal()这里有个发送信号。我们学硬件时知道,用到硬件定时器时要给它一个计算脉冲。这个软件定时器也要一个计算脉冲。我们建立的定时器结构体都会挂到OSTmrWheelTbl[OS_TMR_CFG_WHEEL_SIZE]上面,OS_TMR_CFG_WHEEL+SIZE是要自己定义的,至于挂到OSTmrWheelTbl[0] 到OSTmrWheelTbl[OS_TMR_CFG_WHEEL_SIZE-1]哪一个上,只要看一下OSTmr_Link (OS_TMR *ptmr, INT8U type)就明白了,而且一个OSTmrWheelTbl[n]上可以挂很多个定时器结构体。
一、定时器的建立:
定时器是在我们的应用程序中建立的,
OS_TMR *OSTmrCreate (INT32U dly,
INT32U period,
INT8U opt,
OS_TMR_CALLBACK callback,
void *callback_arg,
INT8U *pname,
INT8U *perr)
想使用定时器那些函数要在os_cfg.h中定义 OS_TMR_EN。
返回值是os_tmr结构体(定义在ucos_ii.h中)。
typedef struct os_tmr {
INT8U OSTmrType;
OS_TMR_CALLBACK OSTmrCallback;
void *OSTmrCallbackArg;
void *OSTmrNext;
void *OSTmrPrev;
INT32U OSTmrMatch; 当 OSTmrTime == OSTmrMatch 定时器到时间了。
INT32U OSTmrDly;
INT32U OSTmrPeriod;
#if OS_TMR_CFG_NAME_EN > 0u
INT8U *OSTmrName;
#endif
INT8U OSTmrOpt;
INT8U OSTmrState;
} OS_TMR;
OSTmrType类型定义在ucos_ii.h中:OS_TMR_TYPE
OS_ARG_CHK_EN要在os_cfg.h中定义一下,来确定要不要一些功能。
OS_TMR_CFG_NAME_EN要你自己在os_cfg.h中定义,来控制要不要用OSTmrName
OSTmrState在ucos_ii.h中有以下几种类型:
OS_TMR_STATE_UNUSED 不存在这个定时器
OS_TMR_STATE_RUNNING 这个定时器正在运行
OS_TMR_STATE_COMPLETED这个定时器已经跑完了
OS_TMR_STATE_STOPPED 这个定时器停止了
参数:
- Dly 定时时间,如果是这个定时器只用一次,那么就用这个,如果定时器要反复用那么它是第一次时用,以后用period。
- Period 定时器从复用时会用到这个作定时时间。
- Opt 这里有两种选项,告诉我们是只用一次还是反复使用。只用一次OS_TMR_OPT_ONE_SHOT,反复使用OS_TMR_OPT_PERIODIC。这些定义在ucos_ii.h中。
定时器选项有五种
#define OS_TMR_OPT_NONE 0u 没有选择
#define OS_TMR_OPT_ONE_SHOT 1u 定时器不会自动重复使用
#define OS_TMR_OPT_PERIODIC 2u 定时器会自动重装
#define OS_TMR_OPT_CALLBACK 3u OSTmrStop()中使用,调用回调函数,但不带参数
#define OS_TMR_OPT_CALLBACK_ARG 4u 也是OSTmrStop()中使用,调用回调函数,但有参数。
- Callback 指向回调函数的指针,这个函数这样声明,void mycallback(OS_TMR *ptmr, void p_arg );
- Callback_arg 参数给callback的。
- Pname 定时器的名字
- Perr 错误指针* OS_ERR_NONE 没有错误
OS_ERR_TMR_INVALID_DLY 无效的定时时间
OS_ERR_TMR_INVALID_PERIOD 无效的周期
OS_ERR_TMR_INVALID_OPT 无效的选项
OS_ERR_TMR_ISR 在中断中调用
OS_ERR_TMR_NON_AVAIL 空的定时器用光了,这个和task一样意思。
用到的函数OSTmr_Alloc()得到一个定时器结构体。
二、删除一个定时器,也是在我们的功能函数中使用,返回为是否成功删除。
BOOLEAN OSTmrDel (OS_TMR *ptmr,
INT8U *perr)
- Ptmr 指向定时器结构体。
- Perr 指向错误的指针。
这里用到这两个函数OSTmr_Unlink(ptmr);
如果是定时器在工作时,要用它解除 OSTmrState= OS_TMR_STATE_STOPPED。
OSTmr_Free(ptmr);
释放这个定时器结构体。
三、得到定时器名字的函数,返回名字的长度。
INT8U
OSTmrNameGet (OS_TMR
*ptmr,
INT8U
**pdest,
指向了一个指向定时器名字地址指针的指针。
INT8U
*perr)
四、定时器还有多长时间溢出。返回还有多长时间溢出。
INT32U
OSTmrRemainGet (OS_TMR
*ptmr,
INT8U
*perr)
五、获得定时器状态的函数,返回状态。
INT8U
OSTmrStateGet (OS_TMR
*ptmr,
INT8U
*perr)
六、启动你的定时器,返回是否成功启动。
你的应用程序使用它
BOOLEAN
OSTmrStart (OS_TMR
*ptmr,
要用到OSTmr_Unlink()和OSTmr_Link()先
INT8U
*perr)散
解除,再重新用这个定时器
七、停止定时器,返回是否成功停止。
你的应用程序使用它
BOOLEAN
OSTmrStop (OS_TMR
*ptmr,
INT8U
opt,
void
*callback_arg,
这个也是个函数
INT8U
*perr)
回调函数在这里使用,callback()。
Opt 为OS_TMR_OPT_NONE不使用回调函数。
OS_TMR_OPT_CALLBACK使用回调函数不用参数。
OS_TMR_OPT_CALLBACK_ARG要使用参数。
八、发送信号,这个是在timer tick中使用要您写到ISR中
INT8U
OSTmrSignal (void)返回