You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32G431 TIM2输入捕获与USART2调试共存问题排查及配置求助

问题解答与代码示例

1. TIM2输入捕获配置可能的遗漏点

你的问题大概率源于以下某一项配置缺失:

  • 捕获模式未正确切换:测量脉冲宽度需要交替捕获上升沿和下降沿,仅单次边沿触发会导致只捕获一次信号。
  • TIM2时钟未开启:TIM2属于APB1总线,需单独调用__HAL_RCC_TIM2_CLK_ENABLE()开启时钟,不能依赖其他定时器的时钟配置。
  • 未配置输入滤波:舵机测试仪信号可能存在噪声,未加滤波会导致中断异常,建议设置TIM_IC_FILTER_FDIV_8这类滤波参数。
  • 中断标志清除不彻底:仅清除CC1IF不够,需同时清除CC1OF(捕获溢出标志),或通过读取TIM2->CCR1寄存器利用硬件机制自动清除CC1IF。
  • 预分频设置不合理:50Hz信号周期20ms,若系统时钟为160MHz,需将TIM2预分频设置为160-1,得到1MHz计数时钟,确保计数器能覆盖20ms的周期范围。

2. TIM2与USART2的冲突排查

STM32G431中两者不存在冲突:

  • AF映射:PA0是TIM2_CH1(AF1),PA2/PA3是USART2_TX/RX(AF7),属于不同复用功能组,无引脚映射冲突。
  • 时钟总线:TIM2和USART2均挂载在APB1总线,只需分别开启各自时钟即可,互不干扰。

3. 极简可用示例代码

以下是PlatformIO环境下的完整代码,包含TIM2 CH1输入捕获(PA0)和USART2调试输出(PA2/PA3):

main.h

#include "stm32g4xx_hal.h"

extern TIM_HandleTypeDef htim2;
extern UART_HandleTypeDef huart2;

void Error_Handler(void);

main.c

#include "main.h"
#include <string.h>

TIM_HandleTypeDef htim2;
UART_HandleTypeDef huart2;

uint32_t pulse_width_us = 0;
uint8_t capture_ready = 0;

// USART2初始化
void MX_USART2_UART_Init(void) {
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK) {
    Error_Handler();
  }
}

// TIM2输入捕获初始化
void MX_TIM2_Init(void) {
  TIM_IC_InitTypeDef sConfigIC = {0};

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 160-1; // 160MHz系统时钟下,得到1MHz计数时钟
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 65535;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_IC_Init(&htim2) != HAL_OK) {
    Error_Handler();
  }

  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = TIM_IC_FILTER_FDIV_8;
  if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK) {
    Error_Handler();
  }

  HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
}

// TIM2 GPIO与中断配置
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef* tim_icHandle) {
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(tim_icHandle->Instance==TIM2) {
    __HAL_RCC_TIM2_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);
  }
}

// USART2 GPIO配置
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) {
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART2) {
    __HAL_RCC_USART2_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }
}

// TIM2中断服务函数
void TIM2_IRQHandler(void) {
  HAL_TIM_IRQHandler(&htim2);
}

// 捕获中断回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
  static uint32_t rising_edge = 0;
  static uint8_t edge_flag = 0;

  if(htim->Instance == TIM2 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
    if(edge_flag == 0) {
      rising_edge = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
      __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);
      edge_flag = 1;
    } else {
      pulse_width_us = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) - rising_edge;
      capture_ready = 1;
      __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
      edge_flag = 0;
      __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC1OF);
    }
  }
}

// 错误处理函数
void Error_Handler(void) {
  while(1) {
    // 可添加LED闪烁等错误提示
  }
}

int main(void) {
  HAL_Init();
  // 系统时钟配置(PlatformIO会自动生成适配代码,确保为160MHz)

  MX_USART2_UART_Init();
  MX_TIM2_Init();

  char uart_buf[32];
  while (1) {
    if(capture_ready) {
      sprintf(uart_buf, "Pulse: %d us\r\n", (int)pulse_width_us);
      HAL_UART_Transmit(&huart2, (uint8_t*)uart_buf, strlen(uart_buf), HAL_MAX_DELAY);
      capture_ready = 0;
    }
    HAL_Delay(100);
  }
}

注意事项

  • 确保系统时钟配置为160MHz,若使用其他时钟频率,需调整TIM2的预分频值。
  • 舵机测试仪输出信号需与STM32的3.3V电平兼容,5V信号需加电平转换电路。
  • 检查PA0引脚的硬件连接,确保地线连通、无虚焊。

内容的提问来源于stack exchange,提问作者Syahrul Afif

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 06:34:55