STM32 UART串口通信协议与3种底层驱动实现(寄存器/标准库/HAL库)

STM32 UART串口通信协议与3种底层驱动实现(寄存器/标准库/HAL库)

串口通信是STM32与上位机(电脑、手机、串口调试助手等)交互的核心方式,其稳定性依赖标准化的帧结构、校验规则与配置参数。本文将从串口通信核心规范入手,详细讲解STM32下UART串口的3种核心底层驱动实现方式(直接操作寄存器、标准外设库、HAL库),并对比不同方案的核心差异。

一、串口通信核心规范

串口数据收发的稳定性完全依赖统一的通信规范,包含帧结构、校验方式、配置参数等核心要素。

1.1 串口数据包结构

完整的数据帧需包含固定格式,保障传输完整性与可校验性:
包头 + 命令 + 数据 + 校验 + 包尾

1.2 数据校验方式

数据传输过程中易受干扰,需通过校验机制验证数据完整性,工程中常用以下3种方式:

  • CR校验
  • 异或校验
  • 和校验(工程最常用)

1.3 串口配置核心参数

串口通信的基础参数需上下位机保持一致,核心配置如下:

  • 波特率:默认115200(可根据需求灵活调整)
  • 数据位:8位
  • 停止位:1位
  • 校验位:无校验
  • 通信模式:异步通信
  • 采样方式:16倍过采样

1.4 数据接收与校验逻辑

以接收缓冲区buf为例,典型的帧校验逻辑如下(工程常用):

  • 帧头判定:buf[0] == 0x55
  • 帧尾判定:buf[4] == 0xff
  • 校验逻辑:buf[1] + buf[2] == buf[3]
  • 异常处理:校验失败时需返回错误信息,避免脏数据被处理

二、STM32 UART 3种核心底层驱动实现

以下3种方式均为直接操作UART外设的硬件底层驱动方案,相互独立、同级并列,适用于不同开发场景。

2.1 直接操作寄存器(最底层)

跳过所有库封装,直接读写UART硬件寄存器,适合深入理解串口底层工作原理。

核心寄存器说明

UART的核心操作依赖状态寄存器(SR)和数据寄存器(DR):

  • SR(状态寄存器):位7(TXE)表示发送数据寄存器空;位5(RXNE)表示接收数据寄存器非空。
  • DR(数据寄存器) :串口收发数据的载体,写DR完成数据发送,读DR获取接收数据。
    (注:完整寄存器说明需参考对应STM32型号的数据手册)
代码实现(单字节收发+回显)
c 复制代码
// 单字节发送函数
void SendBit(uint8_t Bit)
{
    // 等待发送寄存器为空
	while(!(USART1->SR & (1<<7))){}
    // 写入数据到发送寄存器
	USART1->DR = Bit;
}

// 单字节接收函数
uint8_t ReciveBit(void)
{
	uint8_t Bit;
    // 等待接收寄存器非空
	while(!(USART1->SR & (1<<5))){}
    // 读取接收寄存器数据
	Bit = USART1->DR;
	return Bit;
}

// 主循环实现数据回显
while (1)
{
	uint8_t ch = ReciveBit();
	SendBit(ch);
}

2.2 标准外设库实现(STM32F1示例)

ST早期官方推出的标准外设库,封装了寄存器操作,兼顾底层可读性与开发效率(注:该库已停止官方维护)。

关键实现步骤
  1. 开启UART和对应GPIO的时钟;
  2. 配置TX引脚为复用推挽输出,RX引脚为浮空输入;
  3. 初始化UART通信参数(波特率、数据位、停止位等);
  4. 使能UART外设。
代码实现
c 复制代码
#include "stm32f10x.h"

// UART初始化函数
void UART_Init() {
    // 开启USART1和GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStruct;
    // 配置TX引脚(PA9)为复用推挽输出
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 配置RX引脚(PA10)为浮空输入
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 初始化UART参数
    USART_InitTypeDef USART_InitStruct;
    USART_InitStruct.USART_BaudRate = 9600;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    USART_Init(USART1, &USART_InitStruct);
    
    // 使能USART1
    USART_Cmd(USART1, ENABLE);
}

// 单字符发送函数
void UART_SendChar(USART_TypeDef* USARTx, char ch) {
    // 等待发送寄存器为空
    while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
    // 发送字符
    USART_SendData(USARTx, ch);
}

int main() {
    UART_Init();
    // 循环发送字符'H'
    while (1) {
        UART_SendChar(USART1, 'H');
    }
}

2.3 HAL库实现(CubeMX生成)

ST当前主推的开发方案,高度封装,配合CubeMX图形化配置工具可快速完成开发,适配新芯片。

前期配置(CubeMX)
  1. 选择对应STM32型号,开启USART1;
  2. 配置UART模式为"Asynchronous"(异步);
  3. 设置波特率、数据位、停止位等核心参数;
  4. 生成工程代码(本文以MDK-ARM为例)。
    (注:配置界面参考"串口cube配置"截图)
代码实现(循环发送字符串)
c 复制代码
#include "main.h"
#include "usart.h"
#include "gpio.h"

int main(void) {
    // 初始化HAL库
    HAL_Init();
    // 初始化GPIO
    MX_GPIO_Init();
    // 初始化USART1
    MX_USART1_UART_Init();

    uint8_t send_buf[] = "Hello, UART!\r\n";

    while (1) {
        // 发送字符串,超时时间100ms
        HAL_UART_Transmit(&huart1, send_buf, sizeof(send_buf)-1, 100); 
        // 延时1秒
        HAL_Delay(1000);
    }
}

三、标准库与HAL库核心差异对比

对比维度 标准外设库 HAL库
代码风格 接近寄存器操作,底层逻辑清晰 高度封装,代码简洁易移植
学习成本 适合学习底层原理 适合快速开发,上手快
官方支持 停止维护 主推方案,新芯片专属支持
开发效率 中等(需手动配置更多参数) 高(CubeMX一键生成)

四、总结

STM32 UART串口的3种底层驱动实现方式各有适用场景:

  • 直接操作寄存器:适合深入理解串口硬件原理,或对代码体积、执行效率有极致要求的场景;
  • 标准外设库:适合学习STM32外设驱动逻辑,兼容老项目维护;
  • HAL库:适合新项目开发、快速迭代,尤其是使用STM32新款芯片的场景。

无论选择哪种方式,串口通信的核心始终是统一的帧结构、校验规则和配置参数,这是保障通信稳定性的基础。

相关推荐
Heartache boy1 小时前
野火STM32_HAL库版课程笔记-I2C介绍
笔记·stm32·单片机
Deitymoon1 小时前
STM32——OLED显示汉字
stm32·单片机·嵌入式硬件
狮驼岭的小钻风1 小时前
单片机启动流程与 .s 文件详解
单片机·嵌入式硬件
金色光环1 小时前
【DSP学习笔记】 F28335中断系统理解-基于普中DSP28335开发攻略
笔记·单片机·学习·dsp开发
时光の尘1 小时前
【嵌入式大厂面经】·IIC常见考点(持续更新中···)
arm开发·单片机·嵌入式硬件·mcu·物联网·iot
三佛科技-187366133972 小时前
AIP7550GD893.TR是什么芯片?200mA/30V低压差线性稳压器芯片分析
单片机·嵌入式硬件
踏着七彩祥云的小丑2 小时前
嵌入式测试学习第 7 天:PCB电路板基础、走线、焊盘、贴片/直插
单片机·嵌入式硬件
LCG元3 小时前
STM32实战:基于STM32F103的Modbus RTU通信(从机实现)
stm32·单片机·嵌入式硬件
爱喝纯牛奶的柠檬3 小时前
【已验证】STM32 LoRa 环境监测与远程控制系统
arm开发·stm32·单片机·嵌入式硬件