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
相关产品推荐
相关产品推荐

