恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

STM32开发之UART串口编程从入门到实战:协议与标准外设库实现详解

  • 首页
  • 资讯中心
  • /
  • STM32开发之UART串口编程从入门到实战:协议与标准外设库实现详解

相关资讯

STM32开发之IIC通信详解:从协议基础到FM24CL04实战 2026/10/12 4:49:00
一篇文章教会你:用“经纬度思维”看懂比特币链上所有数据 2026/10/12 4:49:00
CS2卡顿掉帧闪退黑屏?从硬件到游戏的全方位排查优化指南 2026/10/12 4:49:00

最新资讯

在 Halcon 中,**形态学处理是 Blob 分析的“前置净化”步骤**,而 Blob 分析本身则是在净化后的区域上做“连通域分解与特征筛选”
C++代码实现MATLAB中的fitcsvm函数功能
8GB显存跑通125B MoE大模型:Qwen3.8-Flash-next轻量化部署实战
基尼系数能跨国比较,却不能无条件拿来做城市或高频研究
【AI大模型接入SDK】ChatServer 整体初始化概述
SenseNova sn-infographic 提示词质量评估标准详解:R01–R08 必答项与 O01–O12 选答项实战指南

今日推荐

Debian新手入门:从部署到日常操作的完整指南
MongoDB复制集扩缩容实战:从rs.add到选主事故复盘
条形码目标检测数据集实战:从YOLOv8训练到部署

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

STM32开发之UART串口编程从入门到实战:协议与标准外设库实现详解

发布时间:2026/10/12 4:49:00
STM32开发之UART串口编程从入门到实战:协议与标准外设库实现详解 1. 什么是串口UART串口是嵌入式开发中最常用的通信接口之一。UARTUniversal Asynchronous Receiver/Transmitter通用异步收发传输器是一种异步串行通信协议它通过一根数据线逐位bit地传输数据实现设备之间的信息交换。在 STM32 开发中串口承担着极其重要的角色它既是调试输出的“窗口”也是与上位机、传感器模块、无线模块如蓝牙、WiFi通信的桥梁。理解 UART 的工作原理是掌握 STM32 编程的基础能力之一。2. UART 与 USART 的区别在 STM32 数据手册中我们经常同时看到 UART 和 USART 两个术语它们之间有什么区别呢UART通用异步收发传输器仅支持异步通信模式即收发双方不需要共享时钟信号。USART通用同步异步收发传输器在 UART 的基础上增加了同步通信能力可以额外输出时钟信号SCLK支持 SPI 等同步模式。简单来说USART 是 UART 的“增强版”。在绝大多数串口通信场景下我们使用的是异步模式此时两者的用法基本一致。STM32 系列芯片通常同时集成多个 USART 和 UART 外设编程时需根据实际需求选择。3. 串口通信关键概念3.1 TX 与 RX串口通信至少需要两根数据线TXTransmit发送数据线用于向外发送数据。RXReceive接收数据线用于接收外部传入的数据。需要注意的是两个设备连接时遵循“交叉连接”原则设备 A 的 TX 接设备 B 的 RX设备 A 的 RX 接设备 B 的 TX。这样才能保证一方发送、另一方接收。3.2 全双工通信UART 支持全双工通信即发送和接收可以同时进行。这是因为 TX 和 RX 是两条独立的数据线互不干扰。与之相对的概念是半双工如 RS-485 总线和单工如仅发送的广播。3.3 串行数据传输串行通信的特点是逐位传输数据。与并行通信一次传输多位相比串行通信虽然单次传输的数据量小但只需要很少的引脚非常适合引脚资源有限的单片机系统。UART 的数据帧就是按照起始位、数据位、校验位、停止位的顺序逐位发送的。3.4 上位机与下位机在串口通信的语境中常提到“上位机”和“下位机”两个概念下位机通常指嵌入式设备本身如 STM32 单片机负责采集数据、控制执行器。上位机通常指 PC 端的应用程序如串口调试助手、自研上位机软件负责发送指令、接收并显示数据。上位机与下位机通过串口通常借助 USB 转 TTL 模块建立连接实现人机交互和数据监控。4. UART 数据传输UART 的传输过程可以概括为“帧”的发送与接收。一个完整的 UART 数据帧包含以下部分空闲状态数据线保持高电平。起始位发送方将数据线拉低一个位时间通知接收方“数据要开始了”。数据位通常为 8 位也可配置为 5、6、7、9 位按低位在前、高位在后的顺序逐位发送。校验位可选用于简单的错误检测常见的有奇校验、偶校验。停止位数据线恢复高电平通常为 1 位或 2 位表示一帧数据结束。收发双方必须约定相同的波特率每秒传输的位数单位 bps才能正确解析每一位数据。常见的波特率有 9600、115200 等。波特率不一致是串口通信乱码的最常见原因。5. 物理层标准UART 协议定义了数据帧的格式但实际传输时还需要依赖具体的物理层标准来决定电平、距离和连接方式。常见的物理层标准有 TTL、RS-232、RS-485 和 RS-422它们各有特点适用于不同的应用场景。5.1 TTL 电平TTLTransistor-Transistor Logic电平是单片机系统中最常用的串口电平标准。STM32 的 UART 引脚直接输出的就是 TTL 电平。逻辑 1高电平通常为 3.3VSTM32或 5V部分 5V 单片机。逻辑 0低电平通常为 0V。特点电平范围窄抗干扰能力较弱传输距离一般不超过 1 米。TTL 电平适合板级通信例如 STM32 与传感器模块、蓝牙模块之间的短距离连接。当需要与 PC 通信时通常借助 USB 转 TTL 模块完成电平转换。5.2 RS-232 标准RS-232 是早期 PC 串口COM 口使用的标准采用负逻辑电平抗干扰能力比 TTL 强。逻辑 1负电平范围为 -3V 到 -15V。逻辑 0正电平范围为 3V 到 15V。特点传输距离可达 15 米左右但只能点对点通信且速率相对较低。STM32 的 TTL 电平不能直接连接 RS-232 设备需要经过 MAX3232 等电平转换芯片。如今 PC 上 RS-232 接口已逐渐被 USB 取代但在工业设备和老式仪器中仍常见。5.3 RS-485 标准RS-485 是一种差分信号标准广泛应用于工业现场总线支持多点通信和长距离传输。差分信号使用 A、B 两根线传输通过两线电压差表示逻辑 0 和 1抗干扰能力强。多点通信一条总线上最多可挂接 32 个节点标准负载下。传输距离可达 1200 米适合远距离工业场景。半双工同一时刻只能一方发送需要收发切换控制。STM32 通过 SP3485、MAX485 等收发器芯片将 TTL 电平转换为 RS-485 差分信号。RS-485 常用于 Modbus 协议、楼宇自控、工厂设备联网等场景。5.4 RS-422 标准RS-422 与 RS-485 类似也采用差分信号但它是全双工通信需要 4 根线两对差分线。全双工发送和接收各用一对差分线可同时收发。多点通信支持一主多从但接收端数量有限通常最多 10 个。传输距离与 RS-485 相当可达 1200 米。RS-422 适合需要同时收发且距离较远的场景例如某些工业设备之间的双向通信。由于 RS-485 在半双工场景下更常用RS-422 的应用相对较少。5.5 四种标准对比标准电平方式通信模式传输距离节点数典型应用TTL单端 3.3V/5V全双工约 1 米点对点板级模块通信RS-232单端 ±12V全双工约 15 米点对点PC 串口、工业仪表RS-485差分半双工约 1200 米最多 32 个Modbus、工业总线RS-422差分全双工约 1200 米最多 10 个远距离双向通信在实际项目中应根据传输距离、通信节点数和是否需要全双工来选择物理层标准。STM32 的 UART 外设本身不区分这些标准只需通过对应的收发器芯片完成电平转换即可。6. UART 协议UART 协议本身只定义了物理层和数据链路层的基础帧格式并不规定数据内容的含义。但在实际工程中为了让通信更可靠、更易解析通常会在 UART 帧之上再封装一层“应用层协议”。下面介绍几种常见的做法。6.1 基础帧格式一个典型的自定义串口协议帧可以设计为帧头(2字节) 数据长度(1字节) 数据(N字节) 校验(1字节) 帧尾(1字节)帧头固定值如 0xAA 0x55用于接收方识别一帧数据的开始。数据长度指明后续数据字段的字节数。数据实际要传输的有效信息。校验常用累加和校验或 CRC 校验用于检测传输过程中是否出现错误。帧尾固定值如 0x0D 0x0A标志一帧结束。6.2 数据解析流程接收方解析一帧数据的典型流程如下逐字节接收数据检测是否匹配帧头。匹配帧头后继续接收长度字节确定本帧总长度。按长度接收完整数据并同步计算校验值。校验通过且帧尾正确则判定为一帧有效数据交给上层处理。校验失败则丢弃本帧重新等待帧头。6.3 常见波特率与配置参数常见取值说明波特率9600 / 115200115200 常用于调试9600 常用于低速传感器数据位8最常用配置校验位无 / 奇 / 偶一般选择无校验以简化处理停止位1最常用配置在 STM32 的 HAL 库中上述参数通过UART_InitTypeDef结构体配置初始化后调用UART_Init()即可完成串口外设的启动。7. STM32F4xx 串口控制器前面介绍了 UART 的协议和物理层标准本节从 STM32F4xx 芯片内部的角度深入讲解串口控制器的核心组成。理解这些寄存器、引脚和状态标志是编写高效串口驱动的基础。7.1 整体结构STM32F4xx 的 USART 控制器由发送器Transmitter、接收器Receiver、波特率发生器Baud Rate Generator以及一组控制/状态寄存器组成。控制器通过 TX 引脚发送数据通过 RX 引脚接收数据并借助硬件流控制引脚RTS、CTS实现流量管理。发送器将并行数据转换为串行比特流按起始位、数据位、停止位的顺序从 TX 引脚发出。接收器从 RX 引脚采样串行比特流重新组装为并行数据并存入接收数据寄存器。波特率发生器根据系统时钟和分频配置产生收发双方约定的位时钟。控制/状态寄存器用于配置工作模式、使能中断并反映收发状态如 TXE、TC、RXNE。7.2 TX 与 RXTXTransmit Data和 RXReceive Data是串口通信的两根核心数据线在 STM32F4xx 中它们被映射到多个 GPIO 引脚可通过复用功能AF配置选择。TX 引脚发送数据输出空闲时为高电平。发送时按帧格式逐位输出数据。RX 引脚接收数据输入用于采样外部传入的串行信号。引脚复用例如 USART1 的 TX/RX 可映射到 PA9/PA10 或 PB6/PB7通过 GPIO 复用功能配置选择。在标准外设库SPL中通过GPIO_InitTypeDef将引脚配置为复用推挽输出TX和复用浮空输入RX再调用USART_Init()完成初始化。下面给出基于 SPL 的 GPIO 复用配置示例/* GPIO 复用配置USART1 的 TXPA9、RXPA10标准外设库 SPL */ void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; /* 使能 GPIOA 和 USART1 时钟 */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); /* TX复用推挽输出 */ GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, GPIO_InitStructure); /* RX复用浮空输入 */ GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, GPIO_InitStructure); /* 将 PA9、PA10 连接到 USART1 复用功能 */ GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); } /* USART1 初始化115200、8 数据位、1 停止位、无校验、无流控SPL */ void USART1_Config(void) { USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate 115200; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, USART_InitStructure); USART_Cmd(USART1, ENABLE); }7.3 硬件流控制当通信双方速率不匹配或接收缓冲区即将溢出时需要一种机制来协调发送节奏这就是硬件流控制。STM32F4xx 的 USART 支持 RTS 和 CTS 两根流控引脚。RTSRequest To Send接收方输出用于通知发送方“我可以接收数据”。当接收缓冲区满时RTS 拉高请求对方暂停发送。CTSClear To Send发送方输入用于检测接收方是否允许发送。CTS 为低电平时发送方可以继续发送CTS 为高电平时发送方暂停。启用硬件流控制后发送器在 CTS 有效前不会启动发送接收器在缓冲区满时通过 RTS 通知对方暂停从而避免数据丢失。在 HAL 库中通过UART_InitTypeDef的HwFlowCtl字段配置可选UART_HWCONTROL_NONE、UART_HWCONTROL_RTS、UART_HWCONTROL_CTS或UART_HWCONTROL_RTS_CTS。7.4 关键状态标志STM32F4xx 的 USART 状态寄存器USART_SR中TXE、TC、RXNE 是编程中最常用的三个标志位它们直接决定了收发流程的推进。TXETransmit Data Register Empty发送数据寄存器为空表示可以写入下一个待发送字节。写数据寄存器USART_DR后 TXE 自动清零。TCTransmission Complete一帧数据已完整发送完毕包括停止位。TC 置位表示数据真正从引脚发出适合在关闭串口或进入低功耗前等待。RXNERead Data Register Not Empty接收数据寄存器已收到一帧数据表示可以读取。读 USART_DR 后 RXNE 自动清零。这三个标志位既可以轮询查询也可以触发中断。例如发送时先等待 TXE 置位再写入数据接收时通过 RXNE 中断及时读取避免数据覆盖。7.5 轮询与中断收发流程基于上述标志位串口收发有两种典型实现方式轮询方式发送时循环等待 TXE 置位后写入数据接收时循环等待 RXNE 置位后读取数据。实现简单但会占用 CPU。中断方式使能 TXE 或 RXNE 中断在中断服务函数中完成数据搬运。CPU 利用率高适合实时性要求较高的场景。在标准外设库SPL中轮询方式通过USART_SendData()和USART_ReceiveData()配合状态标志实现中断方式则通过使能USART_IT_RXNE中断并在中断服务函数中读取数据完成。更高效的 DMA 方式将在后续文章中介绍。下面给出一个基于标准外设库SPL的完整示例将轮询发送与中断接收整合在一起上电后通过轮询方式发送欢迎信息随后使能 RXNE 中断接收数据并在中断服务函数中把收到的数据原样回显。/* main.c —— SPL 库串口轮询发送 中断接收示例 */ #include stm32f4xx.h uint8_t rx_buffer[64]; /* 接收缓冲区 */ uint8_t rx_index 0; /* 当前接收位置 */ uint8_t rx_complete 0; /* 一帧接收完成标志 */ /* GPIO 复用配置USART1 的 TXPA9、RXPA10SPL */ void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; /* 使能 GPIOA 和 USART1 时钟 */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); /* TX复用推挽输出 */ GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, GPIO_InitStructure); /* RX复用浮空输入 */ GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, GPIO_InitStructure); /* 将 PA9、PA10 连接到 USART1 复用功能 */ GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); } /* USART1 初始化115200、8 数据位、1 停止位、无校验、无流控SPL */ void USART1_Config(void) { USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate 115200; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, USART_InitStructure); /* 使能 USART1 接收中断 */ USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* 配置 NVICUSART1 中断优先级 */ NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority 0; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); USART_Cmd(USART1, ENABLE); } /* 主函数 */ int main(void) { GPIO_Config(); /* 配置 GPIO 复用 */ USART1_Config(); /* 初始化串口并开启中断 */ /* 轮询方式发送欢迎信息 */ uint8_t welcome[] STM32 UART SPL Demo Ready\r\n; uint8_t i; for (i 0; i sizeof(welcome) - 1; i) { /* 等待 TXE 置位后写入数据 */ while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) RESET); USART_SendData(USART1, welcome[i]); } while (1) { if (rx_complete) { /* 轮询方式回显整帧数据 */ uint8_t j; for (j 0; j rx_index; j) { while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) RESET); USART_SendData(USART1, rx_buffer[j]); } /* 复位接收状态准备接收下一帧 */ rx_index 0; rx_complete 0; } } } /* USART1 中断服务函数每收到一字节自动调用 */ void USART1_IRQHandler(void) { uint8_t ch; if (USART_GetITStatus(USART1, USART_IT_RXNE) ! RESET) { /* 读取数据寄存器同时清除 RXNE 标志 */ ch USART_ReceiveData(USART1); /* 收到换行符认为一帧结束 */ if (ch \n) { rx_complete 1; } else { rx_buffer[rx_index] ch; if (rx_index sizeof(rx_buffer)) { rx_index 0; /* 缓冲区溢出保护 */ } } } }上述示例的运行流程可以概括为系统初始化完成后通过USART_SendData()配合 TXE 标志轮询发送欢迎信息验证发送通路正常。初始化时使能USART_IT_RXNE中断每收到一字节自动进入USART1_IRQHandler()中断服务函数。中断服务函数中判断是否收到换行符未收到则存入缓冲区收到则置位rx_complete标志。主循环检测到rx_complete后将整帧数据回显并复位状态重新开始接收。7.6 小结STM32F4xx 串口控制器的核心在于 TX/RX 引脚、RTS/CTS 硬件流控制以及 TXE、TC、RXNE 三个状态标志。掌握这些底层机制才能写出稳定、高效的串口驱动并为后续的中断接收、DMA 传输打下基础。8. STM32F4xx 串口编程流程前面几节分别介绍了串口控制器的结构、引脚、状态标志和收发流程本节把这些知识点串起来给出一个基于标准外设库SPL的完整串口编程流程。整个流程可以概括为六个步骤GPIO 配置、UART 配置、中断配置、使能串口、接收数据和发送数据。下面以 USART1TXPA9、RXPA10为例逐一展开。8.1 核心步骤基于 SPL 的串口编程核心步骤如下GPIO 配置使能 GPIOA 和 USART1 时钟将 PA9 配置为复用推挽输出TXPA10 配置为复用浮空输入RX并通过GPIO_PinAFConfig()把引脚连接到 USART1 复用功能。UART 配置填充USART_InitTypeDef结构体设置波特率、数据位、停止位、校验位、硬件流控制和收发模式调用USART_Init()完成初始化。中断配置使能USART_IT_RXNE接收中断并配置 NVIC 中断优先级使能 USART1 中断通道。使能串口调用USART_Cmd(USART1, ENABLE)启动串口外设。接收数据在USART1_IRQHandler()中断服务函数中通过USART_ReceiveData()读取数据并存入缓冲区。发送数据等待 TXE 标志置位后通过USART_SendData()逐字节发送数据。8.2 GPIO 配置GPIO 配置是串口编程的第一步。STM32F4xx 的 USART1 引脚默认不是串口功能必须通过复用功能AF配置才能连接到 USART1。具体来说需要完成三件事使能 GPIOA 时钟、使能 USART1 时钟、将 PA9/PA10 配置为复用功能并连接到 USART1。/* 8.2 GPIO 配置USART1 的 TXPA9、RXPA10SPL */ void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; /* 使能 GPIOA 和 USART1 时钟 */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); /* TXPA9复用推挽输出 */ GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, GPIO_InitStructure); /* RXPA10复用浮空输入 */ GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, GPIO_InitStructure); /* 将 PA9、PA10 连接到 USART1 复用功能 */ GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); }这里有两个关键点需要说明时钟使能GPIOA 挂在 AHB1 总线上所以用RCC_AHB1PeriphClockCmd()USART1 挂在 APB2 总线上所以用RCC_APB2PeriphClockCmd()。两者缺一不可。复用功能映射GPIO_PinAFConfig()的作用是把 PA9、PA10 的复用功能选择寄存器AFRL/AFRH配置为 USART1这一步决定了引脚最终连接到哪个外设。8.3 UART 配置GPIO 配置完成后接下来配置 USART 外设本身。通过USART_InitTypeDef结构体设置通信参数再调用USART_Init()写入寄存器。常用的配置是 115200 波特率、8 数据位、1 停止位、无校验、无硬件流控、收发模式。/* 8.3 UART 配置115200、8 数据位、1 停止位、无校验、无流控SPL */ void USART1_Config(void) { USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate 115200; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, USART_InitStructure); }各字段含义如下USART_BaudRate波特率收发双方必须一致否则会出现乱码。USART_WordLength数据位长度最常用 8 位。USART_StopBits停止位常用 1 位。USART_Parity校验位一般选择无校验以简化处理。USART_HardwareFlowControl硬件流控制本例不使用。USART_Mode工作模式这里同时使能发送和接收。8.4 中断配置如果采用中断方式接收数据还需要配置 USART 中断和 NVIC。首先通过USART_ITConfig()使能 RXNE 接收中断然后配置 NVIC 中断优先级使能 USART1 的中断通道。/* 8.4 中断配置使能 RXNE 中断并配置 NVICSPL */ void NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; /* 使能 USART1 接收中断RXNE */ USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* 配置 NVICUSART1 中断优先级 */ NVIC_InitStructure.NVIC_IRQChannel USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority 0; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); }NVIC 配置中抢占优先级和子优先级的具体数值取决于工程的分组设置NVIC_PriorityGroupConfig()。在简单应用中两者都设为 0 即可满足需求。8.5 使能串口以上配置完成后最后一步是调用USART_Cmd()使能串口外设。这一步不能省略否则前面的配置不会生效。/* 8.5 使能串口SPL */ void USART_Enable(void) { USART_Cmd(USART1, ENABLE); }使能串口后USART1 就开始按照配置的波特率和帧格式工作TX 引脚进入空闲高电平状态RX 引脚开始监听外部数据。8.6 接收数据接收数据采用中断方式。当 RX 引脚收到一字节数据时RXNE 标志置位并触发中断程序自动进入USART1_IRQHandler()中断服务函数。在中断服务函数中通过USART_ReceiveData()读取数据寄存器同时清除 RXNE 标志。/* 8.6 接收数据USART1 中断服务函数SPL */ uint8_t rx_buffer[64]; /* 接收缓冲区 */ uint8_t rx_index 0; /* 当前接收位置 */ uint8_t rx_complete 0; /* 一帧接收完成标志 */ void USART1_IRQHandler(void) { uint8_t ch; if (USART_GetITStatus(USART1, USART_IT_RXNE) ! RESET) { /* 读取数据寄存器同时清除 RXNE 标志 */ ch USART_ReceiveData(USART1); /* 收到换行符认为一帧结束 */ if (ch \n) { rx_complete 1; } else { rx_buffer[rx_index] ch; if (rx_index sizeof(rx_buffer)) { rx_index 0; /* 缓冲区溢出保护 */ } } } }这里采用换行符作为一帧结束的标志是一种简单实用的做法。在实际工程中也可以使用帧头 帧尾 校验的方式这在第 6 节已经介绍过。8.7 发送数据发送数据采用轮询方式。发送前先等待 TXE 标志置位表示发送数据寄存器为空可以写入下一个字节然后调用USART_SendData()写入数据。逐字节循环即可完成整帧数据的发送。/* 8.7 发送数据轮询方式发送字符串SPL */ void USART_SendString(uint8_t *str) { while (*str ! \0) { /* 等待 TXE 置位表示发送数据寄存器为空 */ while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) RESET); /* 写入一个字节到发送数据寄存器 */ USART_SendData(USART1, *str); } /* 等待最后一帧发送完成包括停止位 */ while (USART_GetFlagStatus(USART1, USART_FLAG_TC) RESET); }发送完成后还可以等待 TCTransmission Complete标志置位确保数据真正从引脚发出这在关闭串口或进入低功耗前尤为重要。8.8 主函数整合最后把以上各个步骤整合到main()函数中形成完整的串口收发流程/* 8.8 主函数整合完整串口流程SPL */ int main(void) { /* 1. GPIO 配置 */ GPIO_Config(); /* 2. UART 配置 */ USART1_Config(); /* 3. 中断配置 */ NVIC_Config(); /* 4. 使能串口 */ USART_Enable(); /* 5. 发送数据发送欢迎信息 */ USART_SendString((uint8_t *)STM32 UART SPL Demo Ready\r\n); while (1) { /* 6. 接收数据检测到一帧接收完成 */ if (rx_complete) { /* 回显接收到的数据 */ USART_SendString(rx_buffer); /* 复位接收状态准备接收下一帧 */ rx_index 0; rx_complete 0; } } }整个流程可以概括为先配置 GPIO 和 USART再配置中断并使能串口然后通过轮询方式发送数据、通过中断方式接收数据。主循环中检测到一帧数据接收完成后将其原样回显实现简单的串口收发演示。8.9 小结本节基于标准外设库SPL完整梳理了 STM32F4xx 串口编程的六个核心步骤GPIO 配置、UART 配置、中断配置、使能串口、接收数据和发送数据。掌握这套流程就可以在此基础上扩展出更复杂的串口应用例如自定义协议解析、DMA 传输和环形缓冲区等。9. 小结本文围绕 STM32 的 UART 串口编程从基础概念到实际代码系统梳理了完整的知识链路。下面回顾全文的核心要点串口基础UART 是一种异步串行通信协议通过 TX/RX 两根数据线实现全双工通信USART 是 UART 的增强版额外支持同步模式。设备连接遵循交叉连接原则收发双方必须约定相同的波特率。物理层标准TTL 适合板级短距离通信RS-232 用于点对点远距离RS-485 支持半双工多点通信RS-422 支持全双工多点通信。实际项目中应根据传输距离、节点数和通信模式选择合适的标准并通过收发器芯片完成电平转换。UART 协议基础帧由起始位、数据位、校验位、停止位组成工程中通常在其上封装自定义应用层协议通过帧头、长度、校验和帧尾保证数据可靠解析。串口控制器STM32F4xx 的 USART 由发送器、接收器、波特率发生器和控制/状态寄存器组成核心状态标志 TXE、TC、RXNE 直接决定收发流程的推进。编程流程基于标准外设库SPL的串口编程可概括为 GPIO 配置、UART 配置、中断配置、使能串口、接收数据和发送数据六个步骤轮询方式适合简单场景中断方式适合实时性要求较高的场景。掌握以上内容就具备了 STM32 串口开发的基础能力。后续可以在此基础上继续深入串口中断接收的进阶用法、DMA 传输以及环形缓冲区等话题进一步提升串口通信的效率和稳定性。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号