赞
踩
我将ld3320的标准库工程移植到hal库工程中,程序运行时会卡死在HAL_delay函数,通过查阅了多方资料,深挖工程的底层配置,最终确定了卡死的原因。
HAL_DELAY函数代码如下,从注释中我们可以提取一些关键字:
milliseconds:毫秒级延迟
SysTick timer:滴答时钟
interrupt:中断
- /**
- * @brief This function provides minimum delay (in milliseconds) based
- * on variable incremented.
- * @note In the default implementation , SysTick timer is the source of time base.
- * It is used to generate interrupts at regular time intervals where uwTick
- * is incremented.
- * @note This function is declared as __weak to be overwritten in case of other
- * implementations in user file.
- * @param Delay: specifies the delay time length, in milliseconds.
- * @retval None
- */
- __weak void HAL_Delay(__IO uint32_t Delay)
- {
- uint32_t tickstart = HAL_GetTick();
- uint32_t wait = Delay;
-
- /* Add a period to guarantee minimum wait */
- if (wait < HAL_MAX_DELAY)
- {
- wait++;
- }
-
- while((HAL_GetTick() - tickstart) < wait)
- {
- }
-
- }
可见HAL_delay函数是一个毫秒级的延迟函数,通过调用滴答时钟sysTick定时器进行延时,而有涉及到了中断,那从中断优先级的角度出发,查询滴答时钟sysTick的抢占优先级默认最低。因此,需要考虑是否是有其他外设的优先级与滴答时钟定时器的优先级设置了相同。
两个抢占优先级相同的外设,彼此间不能中断,只能根据响应优先级大小来确定执行的顺序。
起因找到了,但是有一个疑惑
在工程中,滴答时钟sysTick设置的抢占优先级和响应优先级都是0,怎么会是最低的呢?
后面我在工程中看到这么一行:
注释翻译过来就是:Tick中断优先级0(默认为最低)
好吧,你说是最低那就是最低吧.....
我重新查看我的CubeMX配置发现,我在设置优先级的时候,USART2、RCC和滴答时钟sysTick设置的抢占优先级和响应优先级都相同,我想这也是我程序卡死的一个原因之一,没有具体核实,但大家在设置优先级的时候尽量避免这种情况。
因为在CubeMX中滴答时钟sysTick的优先级是不能改变的,所以这种方法我不推荐,更建议大家选择更改其他外设的优先级。
其实在上面的HAL_DELAY函数我们可以看到函数名前面有一个__weak,意思就是可以自定义一个同名函数。我因为是需要在LD3320中使用到延时函数,我干脆直接写一个静态函数在LD3320的c文件中,这样更简单直接。
附上ld3320的延时函数
- static void LD3320_delay(unsigned long uldata)
- {
- unsigned int i = 0;
- unsigned int j = 0;
- unsigned int k = 0;
- for (i=0;i<5;i++)
- {
- for (j=0;j<uldata;j++)
- {
- k = 200;
- while(k--);
- }
- }
- }
不同的外设在抢占优先级和响应优先级的设置避免出现相同的情况,进而可能导致后面程序运行时出现卡死的情况。
一查发现好多人也遇到了HAL_DELAY函数的坑,虽然延时的问题解决了,程序也不会卡死了,可我的LD3320模块却不能识别到声音,又是用例码又是换杜邦线也没起作用,最后暂落的定论是:模块坏了....等新模块到了再做进一步的测试了。
好了先到这吧,希望这篇文章对你有帮助。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。