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

STM32F407 UART3转RS-485通信异常:Rx状态持续忙碌问题求助

让我帮你分析一下你遇到的问题,从代码和逻辑来看,有几个关键的地方需要修正,这应该就是导致Rx状态异常和回调后触发Error_Handler()的原因:

问题分析与修正方案

1. RS485方向控制逻辑错误

你在HAL_UART_RxCpltCallback里把RS485的DE/RE引脚(PB9)设为SET(发送模式),这是核心错误之一。接收完成后,RS485应该保持接收模式(PB9置RESET),只有在准备发送数据时才切换到发送模式。现在接收完成就切回发送模式,不仅会导致外设后续的响应无法被接收,还可能干扰总线状态,间接影响UART的状态判断。

2. 主循环中多余且错误的RxState等待

在HAL_UART_Transmit_IT之后,你添加了while(huart3.RxState != HAL_UART_STATE_READY)的等待逻辑,但RxState是接收状态,和发送操作完全无关。发送完成后RxState本来就是READY状态(除非之前有未完成的接收任务),这个等待完全多余,一旦出现异常导致RxState非READY,就会直接触发错误处理。

3. UartReady标志位的重置时机遗漏

接收完成后UartReady被设为SET,但主循环处理完接收数据后没有重置这个标志,导致下一轮循环时UartReady已经是SET,会跳过接收等待环节直接进入发送,造成时序混乱。


修正后的代码示例

主循环代码修正

#include "main.h"
#include "stm32f4xx_hal.h"
UART_HandleTypeDef huart3;
uint8_t Ocular_1_RxBuffer[4];
uint8_t Ocular_1_TxBuffer[2] = {0x01,0x86};
__IO ITStatus UartReady = RESET; // 初始化标志位

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART3_UART_Init(void);

int main(void) {
 HAL_Init();
 SystemClock_Config();
 MX_GPIO_Init();
 MX_USART3_UART_Init();

 while (1) {
  int Timeout = 1000000;

  // 等待UART全局状态就绪
  while(huart3.gState != HAL_UART_STATE_READY) {
   Timeout--;
   if(Timeout == 0) Error_Handler();
  }

  // 切换到发送模式,启动发送中断
  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
  if(HAL_UART_Transmit_IT(&huart3, Ocular_1_TxBuffer, 2) != HAL_OK) {
   Error_Handler();
  }

  // 等待发送完成(检查TxState而非RxState)
  Timeout = 1000000;
  while(huart3.TxState != HAL_UART_STATE_READY) {
   Timeout--;
   if(Timeout == 0) Error_Handler();
  }

  // 启动接收中断(此时已经处于接收模式)
  Timeout = 1000000;
  if(HAL_UART_Receive_IT(&huart3, Ocular_1_RxBuffer, 4) != HAL_OK) {
   Error_Handler();
  }

  // 等待接收完成
  Timeout = 1000000;
  while(UartReady == RESET) {
   Timeout--;
   if(Timeout == 0) Error_Handler();
  }

  // 这里可以添加你的接收数据处理逻辑
  // ...

  // 重置接收标志,为下一轮循环做准备
  UartReady = RESET;
 }
}

回调函数修正

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle) {
 // 发送完成后,立即切换到接收模式
 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) {
 // 接收完成,设置标志位通知主循环
 UartReady = SET;
 // 保持接收模式,无需切换到发送模式
}

额外检查项

  1. 确认RS485芯片的DE/RE引脚是否短接后连接到PB9,且电平逻辑正确(高电平发送,低电平接收);
  2. 检查MX_USART3_UART_Init()中是否正确开启了USART3的NVIC中断(HAL_NVIC_EnableIRQ(USART3_IRQn););
  3. 确保UART的波特率、数据位、停止位、奇偶校验参数和外设完全一致;
  4. 不需要修改HAL_UART_IRQHandler,HAL库默认实现已经正确处理了收发中断的状态切换逻辑。

内容的提问来源于stack exchange,提问作者V.CHR.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:44:46