STM32 的串口通信

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 为例:

串口TXRX
USART1PA9PA10
USART2PA2PA3
USART3PB10PB11

在 STM32F4、F7、H7 等系列中,串口可能多达 6 个甚至更多。


4. STM32 串口编程

4.1 初始化步骤

  1. 配置 GPIO 端口
    • TX 设为 复用推挽输出(AF_PP)。
    • RX 设为 浮空输入上拉输入
  2. 初始化 USART 外设
    • 设定波特率(Baud Rate)。
    • 设定数据格式(8 位数据位、无校验、1 个停止位)。
    • 使能 UART。
  3. 配置中断或 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. 调试技巧

  1. 串口助手:使用 PC 端串口调试工具(如 SecureCRT、SSCOM、PUTTY)。
  2. 逻辑分析仪:查看 TX、RX 波形,确认波特率是否正确。
  3. 检查硬件连接:确保 TX 接 RX,RX 接 TX,GND 连接。

波形图参考:


8. 总结

  • STM32 串口通信广泛应用于嵌入式调试、外设通信等。
  • 可以使用 轮询中断DMA 方式进行数据传输。
  • 使用 HAL 库寄存器 编程都能实现串口通信,HAL 库较为方便。
上一篇
下一篇