1. 串口基础概念
1.1 USART 和 UART 的区别
- USART(Universal Synchronous/Asynchronous Receiver/Transmitter)
- 既支持 同步(带时钟线)也支持 异步(无时钟线)通信模式。
- 在 STM32 上,一般用作异步通信,所以常称作 UART。
- UART(Universal Asynchronous Receiver/Transmitter)
- 只支持异步通信,不需要额外的时钟信号,常用于与 PC 串口、传感器等通信。
在 STM32 中,USART 可以配置为 UART 模式,因此一般不区分二者,统一称为 UART。
2. 串口通信原理
2.1 串口通信特性
- 异步通信:没有时钟信号,依靠双方约定的波特率(Baud Rate)进行数据传输。
- 数据格式:包括起始位、数据位、校验位(可选)、停止位。
- 全双工:TX(发送)、RX(接收)两条独立的通信线。
- 波特率(Baud Rate):常见波特率有 9600、115200 等。
- 电平:单端。
- 双工类型:全双工。
单端信号 以地(GND)为参考,使用一根信号线传输数据,简单易用但抗干扰能力差,常用于 UART、GPIO、I2C 等短距离低速通信。差分信号 通过两根极性相反的信号线传输数据,接收端检测电压差,从而提高抗干扰能力,适用于 USB、RS-485、CAN、LVDS 等高速远距离通信。
2.2 串口通信时序
一个标准的 8N1(8 位数据,无校验,1 位停止位)格式的串口数据帧结构如下:
- 起始位:1 位,低电平(0)。
- 数据位:一般 8 位(可选 5~9 位)。
- 校验位:可选(奇偶校验)。
- 停止位:1 或 2 位,高电平(1)。
3. STM32 串口(USART/UART)硬件
3.1 硬件框图
STM32 串口硬件模块包含:
- TX/RX:发送与接收引脚。
- 波特率发生器:用于生成 UART 传输速率。
- 发送/接收 FIFO:提高吞吐量,避免丢包。
- 中断/DMA:支持中断和 DMA 方式,提高效率。
3.2 STM32 常见串口引脚
不同 STM32 芯片的 USART 可能占用不同的 GPIO 端口。以 STM32F103C8T6 为例:
串口 | TX | RX |
---|---|---|
USART1 | PA9 | PA10 |
USART2 | PA2 | PA3 |
USART3 | PB10 | PB11 |
在 STM32F4、F7、H7 等系列中,串口可能多达 6 个甚至更多。
4. STM32 串口编程
4.1 初始化步骤
- 配置 GPIO 端口
- TX 设为 复用推挽输出(AF_PP)。
- RX 设为 浮空输入 或 上拉输入。
- 初始化 USART 外设
- 设定波特率(Baud Rate)。
- 设定数据格式(8 位数据位、无校验、1 个停止位)。
- 使能 UART。
- 配置中断或 DMA(可选)
- 使能 UART 中断(如接收中断)。
- 或者使用 DMA 传输数据,提高效率。
5. STM32 串口编程示例
5.1 使用 HAL 库
① 配置串口(HAL_UART_Init)
UART_HandleTypeDef huart1;
void USART1_UART_Init(void) {
__HAL_RCC_USART1_CLK_ENABLE(); // 使能串口时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能 GPIO 时钟
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 配置 PA9 为 USART1 TX
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置 PA10 为 USART1 RX
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200; // 波特率
huart1.Init.WordLength = UART_WORDLENGTH_8B; // 8 位数据
huart1.Init.StopBits = UART_STOPBITS_1; // 1 个停止位
huart1.Init.Parity = UART_PARITY_NONE; // 无校验
huart1.Init.Mode = UART_MODE_TX_RX; // 发送和接收模式
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 无流控
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart1); // 初始化 UART
}
② 发送数据
uint8_t data[] = "Hello, UART!\r\n";
HAL_UART_Transmit(&huart1, data, sizeof(data) - 1, HAL_MAX_DELAY);
③ 接收数据
uint8_t rxData;
HAL_UART_Receive(&huart1, &rxData, 1, HAL_MAX_DELAY);
6. 高级功能
6.1 使用中断方式
- 在数据接收时触发中断,提高 CPU 响应速度。
HAL_UART_Receive_IT(&huart1, &rxData, 1);
- 实现回调函数:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART1) {
HAL_UART_Transmit(&huart1, &rxData, 1, HAL_MAX_DELAY); // 回显
HAL_UART_Receive_IT(&huart1, &rxData, 1); // 继续接收
}
}
6.2 使用 DMA 方式
- 适用于大数据传输,降低 CPU 占用率。
HAL_UART_Transmit_DMA(&huart1, txBuffer, sizeof(txBuffer));
HAL_UART_Receive_DMA(&huart1, rxBuffer, sizeof(rxBuffer));
7. 调试技巧
- 串口助手:使用 PC 端串口调试工具(如 SecureCRT、SSCOM、PUTTY)。
- 逻辑分析仪:查看 TX、RX 波形,确认波特率是否正确。
- 检查硬件连接:确保 TX 接 RX,RX 接 TX,GND 连接。
波形图参考:
8. 总结
- STM32 串口通信广泛应用于嵌入式调试、外设通信等。
- 可以使用 轮询、中断 或 DMA 方式进行数据传输。
- 使用 HAL 库 或 寄存器 编程都能实现串口通信,HAL 库较为方便。