UCOS III中系统延时实现方式:
void OSTimeDly (OS_TICK dly, //指定延时的时间长度,为时间节拍为单位
OS_OPT opt,
OS_ERR *p_err)
其中的opt包括:
#define OS_OPT_TIME_DLY DEF_BIT_NONE 相对模式
#define OS_OPT_TIME_TIMEOUT ((OS_OPT)DEF_BIT_01) 和OS_OPT_TIME_DLY一样
#define OS_OPT_TIME_MATCH ((OS_OPT)DEF_BIT_02) 绝对模式
#define OS_OPT_TIME_PERIODIC ((OS_OPT)DEF_BIT_03) 周期模式
void OSTimeDlyHMSM (CPU_INT16U hours,
CPU_INT16U minutes,
CPU_INT16U seconds,
CPU_INT32U milli,
OS_OPT opt,
OS_ERR *p_err)
其中的OS_OPT opt相较OSTimeDly()函数的opt多了两个选项:OS_OPT_TIME_HMSM_STRICT和OS_OPT_TIME_HMSM_NON_STRICT,其他一样。
#define OS_OPT_TIME_HMSM_STRICT ((OS_OPT)DEF_BIT_NONE)
#define OS_OPT_TIME_HMSM_NON_STRICT ((OS_OPT)DEF_BIT_04)
使用OS_OPT_TIME_HMSM_STRICT选项的话将会检查延时参数:hours的范围[0,99]、minutes的范围[0,59]、seconds 的范围[0,59]、milli的范围[0,999]。
使用OS_OPT_TIME_HMSM_NON_STRICT选项:hours的范围[0,999]、minutes的范围[0,9999]、seconds 的范围[0,65535], mili的范围[0,4294967259]。
opt_time = opt & OS_OPT_TIME_MASK; //其他的各种模式在函数中的分类实现
switch (opt_time)
{
case OS_OPT_TIME_DLY: //在各种延时模式中,并没有具体定义行为,我们可以在函数中自定义各种行为
case OS_OPT_TIME_TIMEOUT:
case OS_OPT_TIME_PERIODIC:
if (milli == (CPU_INT32U)0u) {
if (seconds == (CPU_INT16U)0u) {
if (minutes == (CPU_INT16U)0u) {
if (hours == (CPU_INT16U)0u) {
*p_err = OS_ERR_TIME_ZERO_DLY;
return;
}
}
}
}
break;
case OS_OPT_TIME_MATCH:
break;
default:
*p_err = OS_ERR_OPT_INVALID;
return;
} 这个结构体执行完就是一些具体行为了
上述系统延时实现中,首先判断中断嵌套层数是否为0,若在中断中退出;然后判断OSSchedLockNestingCtr是否为0(调度是否上锁,若上锁退出),为了保证调用此函数后系统会在延时过程中切换到下一优先级的任务。延时的目的就是降低自己的优先级交出处理器资源。
延时的实际时间和设置的时钟节拍频率OS_CFG_TICK_RATE_HZ有关,例如该频率为200那么延时的最小单位就是5ms。
void OSTimeDlyResume (OS_TCB *p_tcb, //需要恢复的任务的任务控制块
OS_ERR *p_err)
通过该函数可以释放通过上述两个延时函数进入等待状态的任务
OSTimeGet()函数用来获取当前时钟节拍计数器的值
OSTimeSet()函数可以设置当前时钟节拍计数器的值 //慎用
OS_TS_GET()获得当前的系统时间戳
在使用UCOS III的过程中发现,调用systick延时函数延时2us,实际延时有十几us,在做数据采集的时候回出现数据错误或者根本无法通信,延时30ms级别会慢5ms,也很不准。用户自定义的阻塞式延时函数应尽量在us级别,不影响系统任务的调度,若使用SysTick实现的延时,更不能占用太多时间,UCOS也需要使用SysTick的寄存器。