☰
STM32F030 USART回环测试不发报文?从时钟到GPIO复用逐一排查
2026/10/27 14:34:06 网站建设 项目流程

这块板子其实不是第一次用,但“USART 回环测试不发报文”这个坑,我确确实实踩了一整个下午。STM32F030 的 USART1,PA9 和 PA10 用杜邦线短接,程序里循环发送HelloLoopback,逻辑分析仪抓 PA9 却只有一个空闲高电平,串口助手更是干干净净。连关键词都搜到歪路上去了,什么 appcontainer loopback exemption utility,那是 Windows 下 UWP 网络回环的工具,跟我们调串口完全不沾边。如果你也正在被标题里这几个字折磨,这篇文章就是照着我的排查过程写的,从硬件接线、时钟 GPIO 初始化、HAL 返回值判断到波形观察,全部按可复现的方式列出来。

先声明一下使用对象。本文基于 STM32F030 系列(以 F030C8T6 为例),HAL 库,CubeMX 生成的工程结构。核心目标就一个:把 USART 回环这条数据通路彻底打通,并在之后接入串口助手时能稳定看到报文。无论是做串口驱动验证、还是给量产板写自检程序,这套流程都适用。

1. 回环不发报文:先把“回环”做成闭环,再把信号链拆开

1.1 我踩到的是哪一种回环问题

很多人一说“回环”,脑子里想的是同一个东西,但实际上有两种完全不同的测试方式。

第一种是硬件短接回环。单片机自己的 TX 引脚通过杜邦线短接回自己的 RX 引脚,比如 PA9-PA10 直连。程序发一个字节,理论上这个字节会立刻从这个 UART 自己的接收寄存器里读到。这种测法验证的是 MCU 内部 USART 外设、引脚复用在硬件上通不通。

第二种是软件回显回环。单片机的 TX 接 USB 转串口工具的 RXD,串口工具的 TXD 接单片机的 RX。PC 串口助手发一个字节,单片机在中断或轮询里收到这个字节,再原样从 TX 发回去,PC 端看到一个“自己发出去又被弹回来”的字符。这种测法验证的是 MCU 与外部工具之间的完整链路。

我一开始栽的坑是第一种,但判断标准却用了第二种的观察方式。硬件短接后,我以为串口助手里一定能看到报文,实际上 PA9-PA10 短接只保证数据进了 MCU 内部 RX,PC 那头的 USB 转串口要是没有接在 PA9 这根线上,当然什么都不会显示。所以先搞清楚你要验证哪一段,再谈“不发报文”。

1.2 排查主线:发送、接收、显示三条链路分别验证

“回环不发报文”这句话太笼统,它可能藏了三个完全不同的故障点:

  • 发送链路断了:代码根本没有驱动 TX 引脚产生电平变化,逻辑分析仪抓不到波形。
  • 接收链路断了:TX 确实输出了,但 RX 引脚没有收到数据,程序读不到 RXNE 标志。
  • 显示链路断了:单片机发送和接收都正常,但 PC 串口助手没显示,可能是接线交叉、COM 口选错、USB 转串口驱动问题。

常规做法是从发送链路开始。因为如果 TX 端根本没波形,后面讨论接收和显示都没有意义。在上一节那个场景里,我先把 USB 转串口从 RX 线上断开,只留逻辑分析仪夹住 PA9,结果波形干净得吓人,说明发送链路才是真正的问题。顺着这条线往下查,才挖到时钟和 GPIO 复用配置这两处隐患。

1.3 排错工具准备

做这类问题排查,手边至少要有逻辑分析仪,不需要多高级,采样率 1MHz 以上的 8 通道逻辑分析仪就够用。USB 转 TTL 模块建议准备两个,一个用于自环验证,一个用于连接目标板。没有逻辑分析仪时,也可以用示波器,但示波器抓低速串口波形不如逻辑分析仪直观。不要只依赖串口助手的显示结果,那是最终表现,不是中间证据。

2. STM32F030 上最容易被忽略的 USART 初始化细节

2.1 时钟源配错:48MHz 和 8MHz 下波特率完全是两码事

STM32F030 上电复位默认是内部 HSI 8MHz 时钟,没有 PLL,没有外部晶振。很多人用 CubeMX 生成工程时,时钟树配置成了 48MHz,但老项目或手写寄存器工程很容易漏掉 PLL 配置,导致实际 SYSCLK 仍然是 8MHz。

USART 外设时钟和波特率的关系非常直接。如果 USART1 挂在 APB2 总线上,且 APB 分频器保持默认 1,那么 USART1 的时钟就等于 SYSCLK。SYSCLK 是 48MHz 时,115200 波特率的 BRR 计算值是 26.04,取整后误差只有 0.16%,完全没问题。但 SYSCLK 是 8MHz 时,115200 波特率的 BRR 计算值是 4.34,硬件取整后实际波特率变成 125000,误差高达 8.5%,PC 端必然解码失败。

在 CubeMX 里检查System Clock页面,确认 HCLK 是 48MHz,然后确认RCC->CFGR中 APB 分频系数是 1。手写寄存器时,可以用HAL_RCC_GetSysClockFreq()把实际系统时钟读出来,再对比 BRR 寄存器的值。我在排查中就是先打印了这两个数字,才发现板子跑在 8MHz 而非 48MHz。这个现象在“回环不发报文”里很典型——发送链路看起来是好的,但 PC 收不到正确数据,或只能收到乱码和残缺帧。

2.2 GPIO 复用功能 AF:寄存器或 CubeMX 少配一个都发不出去

USART1 默认引脚是 PA9-TX、PA10-RX,复用功能编号是 AF1。这个 AF 编号非常关键,它决定了引脚内部信号线是连接到 USART 还是连接到其他外设。

CMSIS 寄存器写法中,PA9 对应GPIOA->AFR[1]寄存器里 bit[11:8],PA10 对应 bit[15:12]。AF1 就是0x01。如果只设置了 MODER 复用模式,却没有往 AFR 寄存器里写 AF1,引脚虽然处于复用模式,但内部信号根本没有接进 USART,发送自然无声无息。正确写法如下:

__HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_USART1_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF1_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

这里最容易犯的错是把Mode写成GPIO_MODE_OUTPUT_PP,或者把Alternate留空。CubeMX 勾选 USART1 异步模式后会自动生成正确代码,但如果你手改过引脚或从旧工程复制代码,这两个地方是重点检查对象。

2.3 HAL 结构体里的几个隐藏开关

再看 UART 初始化结构体。USART1 的Instance指向USART1

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询