本帖最后由 ningzhen 于 2018-8-24 19:50 编辑
完全新手,学习F407的HAL库例程时,串口打印时调用delay_ms(500);卡死。
于是看delay函数,也产生了疑问,即fac_us的取值问题。
在论坛查了下,第一个问题好像没人问,第二个有人问过,似乎没得到答案。
我就把自己的理解和答案发一下,各位帮忙看看有没什么问题。
下面是我对fac_us取值范围的理解:
在delay_init函数中,取的SysTick频率为系统时钟频率,即为168M,
fac_us是根据SysTick频率取的,所以取的也是168,表示SysTick每计数1us就计数168次。
最后贴的是例程中的程序,只截取了不用ucos的部分,我看注释里fac_us取22.5,这个值
应该是F429的片子180M并且SysTick频率取HCLK8分频时候的数值吧。
我理解fac_us取168,则delay_us函数中nus最大取值应该为2^32/168=4294967296/168=25565281,
该us级延时函数delay_us()最大延时时间为25秒多点。
////////////////////////////////////////////////////////////////////////////////
delay_init()函数以及delay_us()函数,剔除了ucos的部分后,都没有开启SysTick使能和设置
SysTick重装载值LOAD,导致一调用delay_us(),程序就会一直循环在while(1){}里面的tnow=SysTick->VAL;这句话。
不开启SysTick使能,或者不设置LOAD重装载值,可能是因为向下计数的原因,SysTick减无可减,也不动了,SysTick->VAL的值
永远是复位值0,told和tnow都为0,相等,永远也进入不了if(tnow!=told){}中,程序就此卡死。
在delay_init函数加上两句后,恢复正常。
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;
SysTick->LOAD=0xffff;
验证delay_us()最大延时时间:串口打印中调用delay_us(26000000);发现打印时间间隔为435ms,正好是
26000000-25565281=434719us.
////////////////////////////////////////////////////////////////////////////////
[mw_shl_code=applescript,true]static u32 fac_us=0; //us延时倍乘数
//初始化延迟函数
//当使用ucos的时候,此函数会初始化ucos的时钟节拍
//SYSTICK的时钟固定为AHB时钟
//SYSCLK:系统时钟频率
void delay_init(u8 SYSCLK)
{
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick频率为HCLK
fac_us=SYSCLK; //不论是否使用OS,fac_us都需要使用
// SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //要加上这两句才能用
// SysTick->LOAD=0xffff;
}
//延时nus
//nus为要延时的us数.
//nus:0~190887435(最大值即2^32/fac_us@fac_us=22.5)
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD; //LOAD的值
ticks=nus*fac_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; //时间超过/等于要延迟的时间,则退出.
}
};
}[/mw_shl_code]
[mw_shl_code=applescript,true]这是delay_us(26000000)的串口打印截图,延时约为435ms
t:12[2018-08-24 06:56:10.955]
t:13[2018-08-24 06:56:11.390]
t:14[2018-08-24 06:56:11.824]
t:15[2018-08-24 06:56:12.260]
t:16[2018-08-24 06:56:12.695]
t:17[2018-08-24 06:56:13.131]
t:18[2018-08-24 06:56:13.566]
[/mw_shl_code]
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
想请原子哥看看我一楼的自答有没有什么毛病的,我认为应该是我拿到的例程中delay_init漏了点东西。
delay_init()函数以及delay_us()函数,剔除了ucos的部分后,都没有开启SysTick使能和设置
SysTick重装载值LOAD,导致一调用delay_us(),程序就会一直循环在while(1){}里面的tnow=SysTick->VAL;这句话。
不开启SysTick使能,或者不设置LOAD重装载值,可能是因为向下计数的原因,SysTick减无可减,也不动了,SysTick->VAL的值
永远是复位值0,told和tnow都为0,相等,永远也进入不了if(tnow!=told){}中,程序就此卡死。
在delay_init函数加上两句后,恢复正常。
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;
SysTick->LOAD=0xffff;
一周热门 更多>