嵌入式开发之 UART 接口详解

目录

  1. [UART 简介](#UART 简介)
  2. [UART 工作原理](#UART 工作原理)
  3. [STM32 UART 硬件架构](#STM32 UART 硬件架构)
  4. [STM32 UART 软件配置(HAL 库)](#STM32 UART 软件配置(HAL 库))
  5. 常见应用场景
  6. 调试技巧与常见问题
  7. 参考资源

1. UART 简介

1.1 什么是 UART

UART (Universal Asynchronous Receiver/Transmitter,通用异步收发传输器)是一种串行、异步、全双工的通信协议,广泛应用于嵌入式系统中设备间的短距离数据传输。

1.2 UART vs USART

特性 UART USART
全称 Universal Asynchronous R/T Universal Synchronous/Asynchronous R/T
同步模式 不支持 支持(如 SPI 模式)
异步模式 支持 支持
常见用途 调试打印、模块通信 需要时钟同步的场景

STM32 的串口外设通常称为 USART,但默认工作于异步模式时即等效为 UART。

1.3 核心特点

  • 异步通信:无需共享时钟线,依靠双方约定的波特率同步
  • 全双工:可同时发送(TX)和接收(RX)
  • 点对点:典型连接为两根数据线(TX ↔ RX,RX ↔ TX)
  • 电平标准:TTL(3.3V/5V)、RS-232、RS-485 等

2. UART 工作原理

2.1 数据帧格式

UART 数据传输以**帧(Frame)**为单位,典型格式如下:

复制代码
| 起始位 | 数据位(5-9 bit)| 校验位(可选)| 停止位(1-2 bit)|
字段 说明
起始位 1 位低电平(0),标志帧开始
数据位 实际传输数据,通常为 8 位(1 Byte)
校验位 可选(奇校验 / 偶校验 / 无校验)
停止位 1 位或 2 位高电平(1),标志帧结束

2.2 波特率(Baud Rate)

波特率表示每秒传输的码元数,常见值:

  • 9600(低速、稳定)
  • 115200(高速、常用调试波特率)
  • 921600(高速下载/传输)

双方波特率必须一致,否则会出现乱码。

2.3 通信流程

复制代码
发送方:数据 → 并转串 → 按帧格式发送 → TX 引脚输出
接收方:RX 引脚采样 → 检测起始位 → 按波特率采样数据位 → 串转并

2.4 硬件连接

复制代码
设备 A          设备 B
TX  ──────────► RX
RX  ◄────────── TX
GND ────────── GND   (必须共地)

注意:TX 接 RX,RX 接 TX,GND 必须相连!


3. STM32 UART 硬件架构

3.1 主要寄存器

寄存器 功能
USART_SR 状态寄存器(TXE、RXNE、TC、ORE 等标志位)
USART_DR 数据寄存器(读写数据)
USART_BRR 波特率寄存器(设置分频系数)
USART_CR1/2/3 控制寄存器(使能、中断、模式配置)

3.2 波特率计算

STM32 波特率公式:

复制代码
BaudRate = fCK / (16 × USARTDIV)

其中:

  • fCK:USART 时钟频率(如 APB1/APB2 总线时钟)
  • USARTDIV:写入 BRR 寄存器的分频值

HAL 库会自动计算,通常无需手动干预。

3.3 中断与 DMA

方式 特点 适用场景
轮询(Polling) 简单、阻塞 CPU 简单收发、初始化阶段
中断(Interrupt) 非阻塞、响应快 中等数据量、实时性要求
DMA 不占用 CPU、大数据量 高速流、大量数据收发

4. STM32 UART 软件配置(HAL 库)

4.1 CubeMX 配置步骤

  1. 打开 STM32CubeMX,选择对应芯片型号
  2. 选择 USART 外设(如 USART1)
  3. 设置模式为 Asynchronous
  4. 配置参数:
    • Baud Rate: 115200
    • Word Length: 8 Bits
    • Stop Bits: 1
    • Parity: None
  5. 开启 NVIC 中断(如使用中断方式)
  6. 生成代码

4.2 轮询方式收发

复制代码
#include "stm32f1xx_hal.h"

UART_HandleTypeDef huart1;

// 初始化(CubeMX 自动生成)
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_UART_Init(&huart1);
}

// 发送数据
uint8_t tx_buf[] = "Hello STM32 UART!\r\n";
HAL_UART_Transmit(&huart1, tx_buf, sizeof(tx_buf), 1000);

// 接收数据
uint8_t rx_buf[64];
HAL_UART_Receive(&huart1, rx_buf, 10, 1000);  // 阻塞接收 10 字节

4.3 中断方式收发

复制代码
// 启动中断接收
HAL_UART_Receive_IT(&huart1, rx_buf, 1);  // 接收 1 字节触发中断

// 中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART1)
    {
        // 处理接收到的数据 rx_buf[0]
        HAL_UART_Receive_IT(&huart1, rx_buf, 1);  // 重新启动接收
    }
}

4.4 DMA 方式收发

复制代码
// 启动 DMA 发送
HAL_UART_Transmit_DMA(&huart1, tx_buf, len);

// 发送完成回调
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    // 发送完成处理
}

4.5 printf 重定向(调试必备)

复制代码
#include <stdio.h>

// 重定向 printf 到 UART
int _write(int file, char *ptr, int len)
{
    HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, HAL_MAX_DELAY);
    return len;
}

// 使用
printf("Temperature: %.2f C\r\n", temp);

5. 常见应用场景

5.1 调试打印(Debug)

最常用的场景,通过 UART 输出日志到 PC 串口助手。

复制代码
printf("[INFO] System initialized.\r\n");
printf("[ERROR] Sensor read failed!\r\n");

5.2 与蓝牙模块通信(如 HC-05/HC-06)

复制代码
STM32 UART ──► HC-05 ──► 手机蓝牙

配置波特率通常为 9600,通过 AT 指令或透传模式通信。

5.3 GPS 模块数据解析(如 NEO-6M)

GPS 模块通过 UART 输出 NMEA 协议数据:

复制代码
$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47

5.4 与 WiFi 模块通信(如 ESP8266/ESP32)

通过 AT 指令控制 WiFi 模块连接网络:

复制代码
HAL_UART_Transmit(&huart2, (uint8_t*)"AT+CWMODE=1\r\n", 15, 1000);
HAL_UART_Transmit(&huart2, (uint8_t*)"AT+CWJAP="SSID","PWD"\r\n", 30, 10000);

5.5 RS-485 工业通信

通过 UART + RS-485 收发器实现远距离(>1000m)、多节点通信,常用于 Modbus RTU 协议。


6. 调试技巧与常见问题

6.1 常见问题排查

现象 可能原因 解决方法
输出乱码 波特率不匹配 检查双方波特率设置
无输出 TX/RX 接反、未共地 检查接线,确保 GND 相连
数据丢失 缓冲区溢出 使用中断或 DMA,增加缓冲区
偶发错误 时钟不准、电磁干扰 检查晶振精度,增加屏蔽
只能发不能收 引脚复用未配置 检查 GPIO 复用功能设置

6.2 调试工具推荐

  • 串口助手:SSCOM、XCOM、Putty、SecureCRT
  • 逻辑分析仪:Saleae Logic、DSLogic(抓取 UART 波形)
  • 示波器:查看 TX/RX 波形,确认波特率和电平

6.3 波特率误差容忍

STM32 波特率发生器允许约 ±2% 的误差,建议实际误差控制在 ±1% 以内。


7. 参考资源

  • ST 官方文档 RM0008 - STM32F10xxx 参考手册
  • ST 官方文档 UM1725 - STM32Cube HAL 用户手册
  • ST 社区 https://community.st.com
  • 正点原子 STM32 开发指南
  • 野火 STM32 库开发实战指南

结语:UART 是嵌入式开发中最基础、最常用的通信接口。掌握其原理与 STM32 配置方法,是嵌入式开发的必备技能。建议从轮询方式入手,逐步过渡到中断和 DMA,以应对不同场景的需求。