hal库定时器输出不正常分析,铁头山羊hal库教学笔记35集

hal库定时器输出不正常分析,铁头山羊hal库教学笔记35集_第1张图片
问题分析
最初的问题:

PWM捕获值能获取到(CCR1:999 CCR2:199)
但最终显示结果没有数值
导致问题的原因:

浮点数计算可能存在精度问题
printf格式化字符串与数据类型不匹配
单位换算计算复杂化了问题
解决方案
数据获取:

简化计算:

移除复杂的浮点运算
使用整数运算代替浮点运算
直接使用计数值作为微秒值
格式化输出:

使用%lu替代%.1f
直接输出原始计数值
技术要点
时钟配置:

系统时钟:HSI/8 = 8MHz
定时器预分频:8
最终定时器时钟:1MHz(1计数 = 1微秒)
硬件设置:

TIM3:生成PWM(Period=999, Pulse=200)
TIM1:输入捕获模式
通道1上升沿触发,通道2下降沿触发
调试技巧:

添加全局调试变量
使用超时机制避免死循环
串口打印原始值进行验证
这次的解决过程很好地展示了:有时候简单直接的方法比复杂的计算更可靠。通过去除不必要的浮点运算和单位转换,我们成功实现了稳定的PWM测量功能。

修改后的代码

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MPU Configuration--------------------------------------------------------*/
  MPU_Config();

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_TIM3_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
  // HAL_UART_Transmit(&huart1, (const uint8_t *)"你好世界", 12, HAL_MAX_DELAY);
  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    __HAL_TIM_CLEAR_FLAG(&htim1, TIM_FLAG_CC1);
    
    // 启动输入捕获
    HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_1);
    HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_2);
    
    // 等待第一次捕获,添加超时检测
    uint32_t timeoutStart = HAL_GetTick();
    while(__HAL_TIM_GET_FLAG(&htim1, TIM_FLAG_CC1) == 0)
    {
        if(HAL_GetTick() - timeoutStart > 1000)
        {
            UART_Printf("Capture timeout!\r\n");
            goto capture_end;
        }
    }
    __HAL_TIM_CLEAR_FLAG(&htim1, TIM_FLAG_CC1);

    // 等待第二次捕获
    timeoutStart = HAL_GetTick();
    while(__HAL_TIM_GET_FLAG(&htim1, TIM_FLAG_CC1) == 0)
    {
        if(HAL_GetTick() - timeoutStart > 1000)
        {
            UART_Printf("Capture timeout!\r\n");
            goto capture_end;
        }
    }

    // 停止捕获
    HAL_TIM_IC_Stop(&htim1, TIM_CHANNEL_1);
    HAL_TIM_IC_Stop(&htim1, TIM_CHANNEL_2);

    // 使用正确的函数获取捕获值
    uint32_t ccr1 = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_1);
    uint32_t ccr2 = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_2);

    debug_ccr1 = ccr1;
    debug_ccr2 = ccr2;

    // 直接使用整数计算以避免浮点数问题
    uint32_t duty = (ccr2 * 100) / ccr1;  // 先乘100再除以总数,避免浮点数

    UART_Printf("CCR1:%lu CCR2:%lu 脉宽:%lu us 周期:%lu us 占空比:%lu%%\r\n", 
                ccr1, ccr2,
                ccr2,   // 直接使用整数值
                ccr1,   // 直接使用整数值
                duty);  // 直接使用整数值

capture_end:
    HAL_Delay(500);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

修改前的代码

#include 
#include 
#include 
 
static void UART_Printf(const char *format, ...)
{
    char tmp[128];
     
    va_list argptr;
    va_start(argptr, format);
    vsprintf((char* )tmp, format, argptr);
    va_end(argptr);
     
    HAL_UART_Transmit(&huart1, (const uint8_t *)&tmp, strlen(tmp), HAL_MAX_DELAY);
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MPU Configuration--------------------------------------------------------*/
  MPU_Config();

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_TIM3_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
  // HAL_UART_Transmit(&huart1, (const uint8_t *)"你好世界", 12, HAL_MAX_DELAY);
  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    //1
    __HAL_TIM_CLEAR_FLAG(&htim1, TIM_FLAG_CC1);

    //2
    HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_1);
    HAL_TIM_IC_Start(&htim1, TIM_CHANNEL_2);
    
    //3
    while(__HAL_TIM_GET_FLAG(&htim1, TIM_FLAG_CC1) == 0);
    __HAL_TIM_CLEAR_FLAG(&htim1, TIM_FLAG_CC1);

    //4
    while(__HAL_TIM_GET_FLAG(&htim1, TIM_FLAG_CC1) == 0);

    //5
    HAL_TIM_IC_Stop(&htim1, TIM_CHANNEL_1);
    HAL_TIM_IC_Stop(&htim1, TIM_CHANNEL_2);

    //6
    uint16_t ccr1 = __HAL_TIM_GET_COMPARE(&htim1, TIM_CHANNEL_1);
    uint16_t ccr2 = __HAL_TIM_GET_COMPARE(&htim1, TIM_CHANNEL_2);

    float period = ccr1*1e-6f;
    float pluseWidth = ccr2*1e-6f;
    float duty = pluseWidth/period;

    UART_Printf("脉宽: %.1f us, 周期: %.1f us, 占空比: %.1f%%\r\n", period*1e6f, pluseWidth*1e6f, duty*100.0f);

    HAL_Delay(500);

    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

你可能感兴趣的:(笔记)