STM32裸机UART通信异常求助:跨设备无接收、同设备数据乱码
问题排查与修正方案
核心问题分析
从现象(跨设备无接收、同设备接收数据乱码)来看,问题集中在GPIO配置错误、波特率计算/寄存器赋值问题以及可能的硬件连接或参数不匹配。
1. GPIO模式赋值错误
配置RX引脚时直接使用GPIOA_MODER = REP_BITS(...),会覆盖之前TX引脚的模式配置,导致TX引脚无法工作在复用功能模式:
// 错误写法:覆盖TX引脚的配置 GPIOA_MODER = REP_BITS(GPIOA_MODER, RX*2, 2, GPIO_MODER_ALT); // 正确写法:保留原有配置,仅修改RX对应位 GPIOA_MODER |= REP_BITS(GPIOA_MODER, RX*2, 2, GPIO_MODER_ALT);
TX引脚的配置同理,建议用|=而非直接赋值,避免覆盖其他引脚的默认配置。
2. USART BRR寄存器初始化问题
直接用USART1_BRR |= ...赋值会残留寄存器默认值,导致波特率计算错误。正确做法是先清零再赋值:
// 9600波特率(假设APB2时钟为42MHz) USART1_BRR = 0; // 先清除寄存器残留值 USART1_BRR = (273 << 4) | 7; // 直接写入计算好的波特率值
务必确认APB2总线时钟频率:
- 若系统时钟为168MHz、APB2预分频为2,则APB2时钟为84MHz,此时9600波特率的BRR应为
(546 << 4) | 14(对应0x22C)。 - 波特率不匹配是乱码的最常见诱因,需先确认时钟树配置正确。
3. 硬件与参数匹配检查
- 交叉连接与共地:STM32的TX(PA9)必须接ESP32C3的RX,STM32的RX(PA10)接ESP32C3的TX,且两台设备必须共地,否则会出现数据混乱或无接收。
- 串口参数一致:ESP32C3的Arduino代码需明确指定与STM32匹配的参数:
STM32的USART1_CR1默认是8位数据位(void setup() { Serial.begin(9600, SERIAL_8N1); // 8位数据位、1停止位、无校验 }M位为0),无需额外配置,确保参数完全对齐即可。
4. 代码细节优化
- 将写函数改为可传入参数的形式,方便测试不同数据:
void uart_write(uint8_t data) { while (!(USART1_SR & USART_SR_TXE)); // 等待发送寄存器空 USART1_DR = data; while (!(USART1_SR & USART_SR_TC)); // 等待发送完成 } - 确认
printf已正确重定向到输出设备(如调试串口或工具),否则无法看到读函数的输出结果。
排查步骤
- 修正GPIO配置的赋值方式,重新编译下载到STM32。
- 用示波器或逻辑分析仪测量PA9的输出波形,确认波特率符合预期(9600波特率下,每个位时长约104μs)。
- 确保设备共地且交叉连接TX/RX,再次测试STM32与ESP32C3的通信。
- 若仍有问题,先在两台STM32间测试,确保波特率、参数完全一致,逐步缩小问题范围。
内容的提问来源于stack exchange,提问作者Heliam
相关产品推荐
相关产品推荐

