1. 前言:为什么选择单线串口?
在工业现场、家电板间通讯(如显示板与主控板)或舵机控制中,我们经常遇到 IO 资源紧张或布线成本敏感的场景。
-
传统 UART:TX + RX + GND(3线),全双工。
-
单线 UART:Data + GND(2线),半双工。
虽然少了一根线,但软件复杂度却呈指数级上升:由于收发共用物理通道,必须在物理层解决“打架”(总线冲突)的问题,在链路层解决“时序”(收发切换)的问题。
本系列将以高性价比的 STM32G0 系列为例,从底层电路到 RTOS 架构,彻底讲透单线串口的设计。
2. 三种物理层拓扑详解
要写驱动,首先得知道电路是怎么连的。单线串口主要有三种硬件实现方式:
方案 A:STM32 内部半双工 (Internal Half-Duplex) —— 推荐 G0 使用
这是 STM32 最“原生”的玩法。通过设置寄存器(HDSEL),芯片内部会将 TX 和 RX 信号在物理上短接,并自动处理输出驱动。
-
硬件连接:
-
仅使用 TX 引脚作为双向数据线。
-
RX 引脚被释放,可做普通 GPIO 用。
-
-
适用场景:板内短距离通讯、私有总线。
-
优点:无需外部元器件,节省 IO。
方案 B:GPIO 控制外部收发器 (External Control)
类似于 RS485 的 TTL 版本。使用三态缓冲器(如 74LVC1G125)来增强驱动能力。
-
硬件连接:需要额外的 GPIO 控制方向。
-
适用场景:长距离通讯、环境干扰大、需要强推挽驱动的场合。
-
缺点:软件需要处理繁琐的
DIR引脚切换时序(Turnaround Time)。
方案 C:开漏输出 + 上拉 (Open-Drain / Diode) —— 多机通讯经典
利用“线与”(Wired-AND)逻辑。所有设备的 TX 配置为开漏输出(Open-Drain),总线上挂一个上拉电阻。
-
硬件连接:STM32 的 TX 设为 Open-Drain,RX 内部连接到 TX(或外部短接)。
-
关键点:总线平时靠电阻拉高。任何一个设备拉低,总线即为低。
-
适用场景:多主(Multi-Master)通讯、低成本多机组网。
3. STM32G0 的实战配置 (CubeMX & HAL)
针对 STM32G0,我们重点演示最常用的 方案 A (内部半双工) 和 方案 C (开漏模式)。
3.1 STM32CubeMX 配置步骤
-
Pinout & Configuration:
-
进入
Connectivity->USARTx。 -
Mode: 选择
Single Wire (Half-Duplex)。 -
注意:此时你在引脚图上会看到只有 TX 引脚点亮,RX 引脚消失(或变灰)。
-
-
Parameter Settings (关键):
-
Baud Rate: 根据需求设置(如 115200)。
-
Word Length: 通常 8 Bits。
-
Parity: None。
-
Stop Bits: 1。
-
-
GPIO Settings (避坑点):
-
点击
GPIO Settings标签页。 -
GPIO Mode: 确认为
Alternate Function Open Drain(开漏复用) 还是Push Pull?-
如果总线上有外部上拉电阻(方案 C):必须选 Open Drain。
-
如果是点对点且无上拉(方案 A):可选 Push Pull,但建议 Open Drain 配合内部上拉以防冲突。
-
-
GPIO Pull-up/Pull-down: 建议选择 Pull-up (即使外部有电阻,内部上拉也能提供双重保障,防止初始化瞬间的干扰)。
-
3.2 STM32G0 特有的“黑科技”配置
G0 系列的 USART_CR2 和 USART_CR1 寄存器里藏着几个好用的功能,可以在 CubeMX 的 Advanced Settings 或代码中开启:
-
TX/RX Pin Swapping (
SWAP):-
场景:画 PCB 时手抖,把 TX 和 RX 线走反了,或者为了绕开过孔想互换引脚。
-
代码:
huart1.AdvancedInit.Swap = UART_ADVFEATURE_SWAP_ENABLE; -
效果:物理引脚定义互换,无需割线。
-
-
Logical Inversion (
TXINV/RXINV):-
场景:如果你用了简单的三极管做外部驱动,电平逻辑会反转(输入 1 变 0)。
-
代码:
huart1.AdvancedInit.TxPinLevelInvert = UART_ADVFEATURE_TXINV_ENABLE; -
效果:MCU 自动把发出去的数据取反,软件层看到的还是正常数据。
-
4. 物理层避坑指南 (必看)
这是无数工程师调试单线串口时“翻车”的地方。
4.1 上拉电阻与波形失真 (RC Time Constant)
在 开漏模式 (Open-Drain) 下,逻辑“0”是芯片内部 MOS 管强拉地的(下降沿很陡峭),但逻辑“1”是靠电阻拉上去的(上升沿是电容充电曲线)。
-
现象:如果你用示波器看,波形像“鲨鱼鳍”。
-
后果:如果电阻太大或线太长(电容大),上升沿太缓,导致采样点电平未达到阈值(VIH),数据出错。
工程推荐值表:
| 波特率 (Baud) | 推荐上拉电阻 (R) | 适用场景 |
| 9600 bps | 4.7kΩ - 10kΩ | 长距离,低功耗 |
| 115200 bps | 1kΩ - 2.2kΩ | 短距离,追求速度 |
| 1 Mbps+ | 330Ω - 680Ω | 极短距离,注意 MCU 灌电流限制 |
4.2 5V 容忍与电平转换
STM32G0 是 3.3V 器件,但很多单线传感器(如水温、超声波)是 5V 供电。
-
技巧:G0 的许多 IO 口是 FT (Five Volt Tolerant) 的。
-
操作:
-
查阅 Datasheet,确认所选 TX 引脚标有 FT 字样。
-
配置为 Open-Drain 模式。
-
上拉电阻拉到 5V(而不是 3.3V)。
-
-
结果:直接实现了双向 3.3V <-> 5V 电平转换,无需任何转换芯片!
4.3 总线空闲状态
-
UART 协议规定,空闲状态(Idle)必须是高电平。
-
初始化陷阱:在
HAL_UART_Init完成之前,GPIO 可能会浮动。务必在HAL_UART_MspInit中,尽早开启上拉(Pull-up),确保上电瞬间总线不会误产生“低电平毛刺”,否则从机会误以为那是 Start Bit。
5. 核心代码预览 (HAL 库)
以下是基于 HAL 库的初始化精简代码,展示了如何启用半双工模式。
/* UART1 Initialization Function */
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
// 关键:模式选择半双工
huart1.Init.Mode = UART_MODE_TX_RX; // 注意:部分HAL版本此处需配合下面的 HalfDuplex 调用
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
// G0 特性配置:如果需要单线且只用TX引脚
// HAL_HalfDuplex_Init 会自动处理 HDSEL 位
if (HAL_HalfDuplex_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
/* GPIO Configuration (在 stm32g0xx_hal_msp.c 中) */
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(huart->Instance==USART1)
{
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
// PA9 -> USART1_TX
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; // Open-Drain 模式,推荐!
GPIO_InitStruct.Pull = GPIO_PULLUP; // 内部上拉,双重保险
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 注意:在 Half-Duplex 模式下,通常不需要配置 RX 引脚 (PA10)
}
}
/*******************************************
* Description:
* 本文为作者《嵌入式开发基础与工程实践》系列文之一。
* 关注我即可订阅后续内容更新,采用异步推送机制。
* 转发本文可视为广播分发,有助于信息传播至更多节点。
*******************************************/
845

被折叠的 条评论
为什么被折叠?



