[应用相关] 基于STM32CubeIDE搭建开发环境 --- 解决延时不准问题

[复制链接]
1202|14
 楼主| internally 发表于 2020-5-10 09:06 | 显示全部楼层 |阅读模式
本博客中示例代码下载路径: https://github.com/maziot-stm32/A1/releases/tag/v0.3




作者:mz8023yt
链接:https://www.jianshu.com/p/eb0d52ff0bb0
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 楼主| internally 发表于 2020-5-10 09:06 | 显示全部楼层
HAL_Delay 延时时间不准确
在上一篇**中有编写一个点灯的 demo 程序用于验证工程. 其中主函数测试代码如下:

  1. #define LED0_Pin        GPIO_PIN_8
  2. #define LED0_GPIO_Port  GPIOA
  3. #define LED1_Pin        GPIO_PIN_2
  4. #define LED1_GPIO_Port  GPIOD

  5. /**
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]  The application entry point.
  7. * @retval int
  8. */
  9. int main(void)
  10. {
  11.     HAL_Init();
  12.     SystemClock_Config();
  13.     MX_GPIO_Init();
  14.     led_init();

  15.     while (1)
  16.     {
  17.         HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, LED_ON);
  18.         HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, LED_ON);
  19.         HAL_Delay(200);
  20.         HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, LED_OFF);
  21.         HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, LED_OFF);
  22.         HAL_Delay(200);
  23.     }
  24. }
 楼主| internally 发表于 2020-5-10 09:07 | 显示全部楼层
这里的逻辑很简单, 200ms切换一次 LED 的状态. 但是烧写到板子上后, 发现 LED 闪烁的并没有想象的那么快. 因此便用逻辑分析仪抓了下 PA8 引脚波形.
255685eb753b6a6b6a.png
通过波形确认到 HAL_Delay(200) 实际延时了 400ms, 果然不对.
 楼主| internally 发表于 2020-5-10 09:07 | 显示全部楼层
晶振时钟配置不对
追了下代码, 最后发现是晶振频率代码和板子没有对应上, 板子上贴的是 8M 晶振, 代码中的配置却是 16M, 修正后, 延时正常.
 楼主| internally 发表于 2020-5-10 09:10 | 显示全部楼层
修改 diff 如下:

  1. Paul@DESKTOP-PUB20JQ MINGW64 /f/Workspaces/stm32/A1 (master)
  2. $ git diff
  3. diff --git a/MAZ_Applications/system_stm32f1xx.c b/MAZ_Applications/system_stm32f1xx.c
  4. index 7cacb32..40f4488 100644
  5. --- a/MAZ_Applications/system_stm32f1xx.c
  6. +++ b/MAZ_Applications/system_stm32f1xx.c
  7. @@ -120,7 +120,7 @@
  8.                 is no need to call the 2 first functions listed above, since SystemCoreClock
  9.                 variable is updated automatically.
  10.    */
  11. -uint32_t SystemCoreClock = 16000000;
  12. +uint32_t SystemCoreClock = 8000000;
  13. const uint8_t AHBPrescTable[16U] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
  14. const uint8_t APBPrescTable[8U] =  {0, 0, 0, 0, 1, 2, 3, 4};
 楼主| internally 发表于 2020-5-10 09:10 | 显示全部楼层
修正后重新用逻辑分析仪抓取波形确认延时就比较正常了, 201ms多一点.
871495eb75496900c0.png
 楼主| internally 发表于 2020-5-10 09:11 | 显示全部楼层
延时误差较大
讲道理, 硬件嘀嗒定时器延时, 应该比较精确, us级别可以理解, 不应该出现ms级别的误差. 找找原因.
  1. __weak void HAL_Delay(uint32_t Delay)
  2. {
  3.   uint32_t tickstart = HAL_GetTick();
  4.   uint32_t wait = Delay;

  5.   /* Add a freq to guarantee minimum wait */
  6.   if (wait < HAL_MAX_DELAY)
  7.   {
  8.     wait += (uint32_t)(uwTickFreq);               // 强制加1
  9.   }

  10.   while ((HAL_GetTick() - tickstart) < wait)
  11.   {
  12.   }
  13. }
 楼主| internally 发表于 2020-5-10 09:12 | 显示全部楼层
最后发现, 居然是在 HAL_Delay 函数内部对延时时间进行了强制加1动作. 该强制加1动作是为了防止延迟时间为设置0时卡死在后面的 while ((HAL_GetTick() - tickstart) < wait) 循环中.

 楼主| internally 发表于 2020-5-10 09:13 | 显示全部楼层
因此做出如下修正:

  1. Paul@DESKTOP-PUB20JQ MINGW64 /f/Workspaces/stm32/A1 (master)
  2. $ git diff
  3. diff --git a/MAZ_Vendors/ST/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_def.h b/MAZ_Vendors/ST/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_def.h
  4. index c287eb3..c8630f8 100644
  5. --- a/MAZ_Vendors/ST/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_def.h
  6. +++ b/MAZ_Vendors/ST/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_def.h
  7. @@ -57,6 +57,7 @@ typedef enum

  8. /* Exported macro ------------------------------------------------------------*/
  9. #define HAL_MAX_DELAY      0xFFFFFFFFU
  10. +#define HAL_NO_DELAY       0x0

  11. #define HAL_IS_BIT_SET(REG, BIT)         (((REG) & (BIT)) != 0U)
  12. #define HAL_IS_BIT_CLR(REG, BIT)         (((REG) & (BIT)) == 0U)
  13. diff --git a/MAZ_Vendors/ST/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c b/MAZ_Vendors/ST/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c
  14. index 252f973..aa3f5c5 100644
  15. --- a/MAZ_Vendors/ST/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c
  16. +++ b/MAZ_Vendors/ST/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c
  17. @@ -363,7 +363,8 @@ __weak void HAL_Delay(uint32_t Delay)
  18.    uint32_t wait = Delay;

  19.    /* Add a freq to guarantee minimum wait */
  20. -  if (wait < HAL_MAX_DELAY)
  21. +//  if (wait < HAL_MAX_DELAY)
  22. +  if (wait == HAL_NO_DELAY)
  23.    {
  24.      wait += (uint32_t)(uwTickFreq);
  25.    }
 楼主| internally 发表于 2020-5-10 09:13 | 显示全部楼层
修正后, 时间就在 200ms 左右, 误差为 us 级别, 波形如下:

471575eb75531efe12.png
guanjiaer 发表于 2020-6-2 16:12 | 显示全部楼层
非常感谢楼主分享
heimaojingzhang 发表于 2020-6-2 16:13 | 显示全部楼层
diff原来是多少来着
keaibukelian 发表于 2020-6-2 16:13 | 显示全部楼层
为什么需要这样修改呢
labasi 发表于 2020-6-2 16:14 | 显示全部楼层
这样修正的前提是时钟源是准确的 是吗
paotangsan 发表于 2020-6-2 16:15 | 显示全部楼层
改的很巧妙
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

315

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部