新手上路
- 积分
- 20
- 金钱
- 20
- 注册时间
- 2017-10-20
- 在线时间
- 3 小时
|
5金钱
上UCOSII系统,代码未进ucos系统时,delay_ms()的最大延时为什么能超过5ms(原子哥的例程中用的delay_ms(100);都可以)?
上UCOS系统后,未进入系统时,delay_ms(u16 nms)中只执行delay_us((u32)(nms*1000));,但是SysTick->LOAD=105000=(1000000/200)*168/8;这个重载值为5ms,delay_us()是按照数节拍数来进行的延时,这样应该是做不到大于5ms的延时的,那为什么能用delay_ms(100);呢?
下面贴下代码:(红色是相关代码)
void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS //如果需要支持OS.
u32 reload;
#endif
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us=SYSCLK/8; //不论是否使用OS,fac_us都需要使用
#if SYSTEM_SUPPORT_OS //如果需要支持OS.
reload=SYSCLK/8; //每秒钟的计数次数 单位为M
reload*=1000000/delay_ostickspersec; //根据delay_ostickspersec设定溢出时间
//reload为24位寄存器,最大值:16777216,在168M下,约合0.7989s左右
fac_ms=1000/delay_ostickspersec; //代表OS可以延时的最少单位
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断
SysTick->LOAD=reload; //每1/delay_ostickspersec秒中断一次
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
#else
fac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数
#endif
}
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD; //LOAD的值
ticks=nus*fac_us; //需要的节拍数
delay_osschedlock(); //阻止OS调度,防止打断us延时
told=SysTick->VAL; //刚进入时的计数器值
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了.
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.
}
};
delay_osschedunlock(); //恢复OS调度
}
void delay_ms(u16 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((u32)(nms*1000)); //普通方式延时
}
|
最佳答案
查看完整内容[请看2#楼]
UCOSII没运行之前delay_ms()为什么一定要小5ms?看delay_ms()函数源码,UCOSII没有运行起来之前调用的是delay_us()来实现延时的!delay_us()通过统计SYSTICK的计数值来实现延时的,这里面会处理SYSTICK溢出这个情况的,仔细分析delay_us()里面的told,tcnt,tnow,reload是用来干嘛的
|