在uCOSIII下成功调试完成DS18b20,需要注意的是DS18b20的时序操作延时函数,由于需要us级精确延时,所以需要利用SysTick,延时函数参考正点原子的例程进行了修改,适配野火开发板例程,代码如下:
#include "delay.h"
static uint16_t fac_ms=1; //ms延时倍乘数,在ucos下,代表每个节拍的ms数
#ifdef OS_CRITICAL_METHOD //OS_CRITICAL_METHOD定义了,说明要支持UCOSII
#define delay_osrunning OSRunning //OS是否运行标记,0,不运行;1,在运行
#define delay_ostickspersec OS_TICKS_PER_SEC //OS时钟节拍,即每秒调度次数
#define delay_osintnesting OSIntNesting //中断嵌套级别,即中断嵌套次数
#endif
//支持UCOSIII
#ifdef CPU_CFG_CRITICAL_METHOD //CPU_CFG_CRITICAL_METHOD定义了,说明要支持UCOSIII
#define delay_osrunning OSRunning //OS是否运行标记,0,不运行;1,在运行
#define delay_ostickspersec OSCfg_TickRate_Hz //OS时钟节拍,即每秒调度次数
#define delay_osintnesting OSIntNestingCtr //中断嵌套级别,即中断嵌套次数
#endif
//调用OS自带的延时函数延时
//ticks:延时的节拍数
void delay_ostimedly(uint32_t ticks)
{
#ifdef CPU_CFG_CRITICAL_METHOD
OS_ERR err;
OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err); //UCOSIII延时采用周期模式
#else
OSTimeDly(ticks); //UCOSII延时
#endif
}
//延时nus
//nus为要延时的us数.
void delay_us(uint32_t nus)
{
uint32_t ticks;
uint32_t told,tnow,tcnt=0;
uint32_t reload=SysTick->LOAD;//LOAD的值
ticks=nus*(SystemCoreClock/1000000);//需要的节拍数
tcnt=0;
told=SysTick->VAL;//刚进入时的计数器值
for(;;)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told) tcnt += told-tnow;//这里注意一下SYSTICK是一个递减的计数器就可以了.
else tcnt += reload-tnow+told;
told = tnow;
if(tcnt>=ticks) break;//时间超过/等于要延迟的时间,则退出.
}
}
}
//延时nms
//nms:要延时的ms数
void delay_ms(uint16_t nms)
{
if(delay_osrunning&&delay_osintnesting==0) //如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度)
{
if(nms>=fac_ms)//延时的时间大于OS的最少时间周期
{
delay_ostimedly(nms/fac_ms);//OS延时
}
nms%=fac_ms;//OS已经无法提供这么小的延时了,采用普通方式延时
}
delay_us((uint32_t)(nms*1000));//普通方式延时
}
为了保证在系统开始运行前能够正确进行延时,将SysTick_Handler函数修改如下:
void SysTick_Handler(void)
{
if(OSRunning != 0)//系统没有运行,不进行任务调度
{
OSIntEnter(); //用于统计中断的嵌套层数,对对嵌套层数+1
OSTimeTick(); //统计时间,遍历任务,对延时任务计时减1
OSIntExit(); //对嵌套层数减1,在退出中断前启动任务调度
}
}
另外,由于DS18b20的延时操作是us级的,因此在读取温度数据时,应该将其设定一个较高的优先级或者关闭系统的任务调度:
//温度采集任务,每秒采集一次温度信息
void Task_DS18b20(void *p_arg)
{
OS_ERR err;
(void)p_arg; //'p_arg'并没有用到,防止编译器提示警告
while(1)
{
OSSchedLock(&err);//关闭系统任务调度
DS18b20_Data = DS18B20_Get_Temp();
OSTaskQPost((OS_TCB *)&LCD_TCB,
(void *)&DS18b20_Data,
(OS_MSG_SIZE)sizeof(float),
(OS_OPT )OS_OPT_POST_FIFO,
(OS_ERR *)&err);
OSSchedUnlock(&err);//恢复调度
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err);
}
}
这样就可以正确的读取DS18b20的温度信息。