OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3885|回复: 4

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

[复制链接]

7

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
205
金钱
205
注册时间
2018-6-20
在线时间
45 小时
发表于 2018-8-24 19:51:18 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 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]
            



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2018-8-25 01:38:40 | 显示全部楼层
建议用标准库例程,试试。dealy 500ms不可能死机才对。
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2018-8-25 01:48:38 | 显示全部楼层
另外,试试寄存器版本吧
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

7

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
205
金钱
205
注册时间
2018-6-20
在线时间
45 小时
 楼主| 发表于 2018-8-27 10:37:09 | 显示全部楼层
正点原子 发表于 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;
回复

使用道具 举报

35

主题

560

帖子

2

精华

资深版主

Rank: 8Rank: 8

积分
17769
金钱
17769
注册时间
2018-3-3
在线时间
523 小时
发表于 2018-8-27 11:43:17 | 显示全部楼层
ningzhen 发表于 2018-8-27 10:37
想请原子哥看看我一楼的自答有没有什么毛病的,我认为应该是我拿到的例程中delay_init漏了点东西。
dela ...

HAL库是在 HAL_Init()里面初始化滴答定时器的
/*
*
*
*
*
*
*/
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-7 22:31

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表