3. 基于STM32CubeIDE搭建开发环境 --- 解决延时不准问题

本博客中示例代码下载路径: https://github.com/maziot-stm32/A1/releases/tag/v0.3

HAL_Delay 延时时间不准确

在上一篇文章中有编写一个点灯的 demo 程序用于验证工程. 其中主函数测试代码如下:

#define LED0_Pin        GPIO_PIN_8
#define LED0_GPIO_Port  GPIOA
#define LED1_Pin        GPIO_PIN_2
#define LED1_GPIO_Port  GPIOD

/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    led_init();

    while (1)
    {
        HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, LED_ON);
        HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, LED_ON);
        HAL_Delay(200);
        HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, LED_OFF);
        HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, LED_OFF);
        HAL_Delay(200);
    }
}

这里的逻辑很简单, 200ms切换一次 LED 的状态. 但是烧写到板子上后, 发现 LED 闪烁的并没有想象的那么快. 因此便用逻辑分析仪抓了下 PA8 引脚波形.

PA8波形

通过波形确认到 HAL_Delay(200) 实际延时了 400ms, 果然不对.

晶振时钟配置不对

追了下代码, 最后发现是晶振频率代码和板子没有对应上, 板子上贴的是 8M 晶振, 代码中的配置却是 16M, 修正后, 延时正常.

修改 diff 如下:

Paul@DESKTOP-PUB20JQ MINGW64 /f/Workspaces/stm32/A1 (master)
$ git diff
diff --git a/MAZ_Applications/system_stm32f1xx.c b/MAZ_Applications/system_stm32f1xx.c
index 7cacb32..40f4488 100644
--- a/MAZ_Applications/system_stm32f1xx.c
+++ b/MAZ_Applications/system_stm32f1xx.c
@@ -120,7 +120,7 @@
                is no need to call the 2 first functions listed above, since SystemCoreClock
                variable is updated automatically.
   */
-uint32_t SystemCoreClock = 16000000;
+uint32_t SystemCoreClock = 8000000;
 const uint8_t AHBPrescTable[16U] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
 const uint8_t APBPrescTable[8U] =  {0, 0, 0, 0, 1, 2, 3, 4};

修正后重新用逻辑分析仪抓取波形确认延时就比较正常了, 201ms多一点.

修改晶振频率后PA8波形

延时误差较大

讲道理, 硬件嘀嗒定时器延时, 应该比较精确, us级别可以理解, 不应该出现ms级别的误差. 找找原因.

__weak void HAL_Delay(uint32_t Delay)
{
  uint32_t tickstart = HAL_GetTick();
  uint32_t wait = Delay;

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

  while ((HAL_GetTick() - tickstart) < wait)
  {
  }
}

最后发现, 居然是在 HAL_Delay 函数内部对延时时间进行了强制加1动作. 该强制加1动作是为了防止延迟时间为设置0时卡死在后面的 while ((HAL_GetTick() - tickstart) < wait) 循环中.
因此做出如下修正:

Paul@DESKTOP-PUB20JQ MINGW64 /f/Workspaces/stm32/A1 (master)
$ git diff
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
index c287eb3..c8630f8 100644
--- a/MAZ_Vendors/ST/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_def.h
+++ b/MAZ_Vendors/ST/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_def.h
@@ -57,6 +57,7 @@ typedef enum

 /* Exported macro ------------------------------------------------------------*/
 #define HAL_MAX_DELAY      0xFFFFFFFFU
+#define HAL_NO_DELAY       0x0

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

   /* Add a freq to guarantee minimum wait */
-  if (wait < HAL_MAX_DELAY)
+//  if (wait < HAL_MAX_DELAY)
+  if (wait == HAL_NO_DELAY)
   {
     wait += (uint32_t)(uwTickFreq);
   }

修正后, 时间就在 200ms 左右, 误差为 us 级别, 波形如下:

修改延时函数后PA8波形

你可能感兴趣的:(3. 基于STM32CubeIDE搭建开发环境 --- 解决延时不准问题)