F407和F429HAL库例程中delay函数的错误和fac_us的最大取值

2019-07-20 06:30发布

本帖最后由 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]
            



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
4条回答
ningzhen
2019-07-20 17:36
正点原子 发表于 2018-8-25 01:48
另外,试试寄存器版本吧

想请原子哥看看我一楼的自答有没有什么毛病的,我认为应该是我拿到的例程中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;

一周热门 更多>