资讯中心

STM32串口数量规划:从硬件选型到软件优化的嵌入式开发指南

📅 2026/8/8 2:36:42
STM32串口数量规划:从硬件选型到软件优化的嵌入式开发指南
1. 从“够用”到“不够用”为什么串口数量如此重要刚接触STM32那会儿我总觉得串口这东西有一个不就够了吗接个调试助手打印点日志或者和电脑传点数据一个串口绰绰有余。直到我开始做第一个稍微复杂点的项目——一个需要同时连接GPS模块、蓝牙模块、4G模块和一块串口屏的物联网终端设备时我才被现实狠狠上了一课。看着手头那块引以为傲的STM32F103C8T6它只有一个USART和一个UART我瞬间陷入了“串口焦虑”。是时候重新设计硬件还是用软件模拟或者当初选型时我是不是应该多看一眼数据手册里的“USART”那一栏这几乎是每个STM32开发者都会经历的阶段。串口UART/USART作为嵌入式系统中最基础、最可靠、最“古老”的通信接口之一其重要性不言而喻。它不像I2C或SPI那样需要严格的时序和主从架构也不像CAN或以太网那样复杂它就是简单的“发送线”和“接收线”加上地线就能工作调试方便协议简单几乎所有的传感器、模块、屏幕和无线设备都提供了串口作为通信方式。因此一颗MCU能提供多少个可用的串口直接决定了你的系统能“挂”多少外设能实现多复杂的通信拓扑。很多人包括曾经的我在项目初期往往会忽略这个参数认为“MCU性能够用就行”。但恰恰是串口、定时器、ADC通道这些外设的数量往往成为项目后期扩展的瓶颈。今天我们就来彻底聊聊STM32的串口数量这件事。这不是一个简单的查表游戏而是关乎项目选型、硬件设计、软件架构乃至成本控制的系统工程。我会结合STM32F103C8T6和STM32F103ZET6这两款经典且对比鲜明的型号把串口数量的门道掰开揉碎了讲清楚让你下次选型时心里绝对有底。2. 核心概念厘清USART、UART与串口在深入讨论数量之前我们必须先统一“语言”。在STM32的世界里你经常会同时看到USART和UART这两个词它们都常被我们俗称为“串口”但在硬件层面有细微而重要的区别。UART是通用异步收发传输器的缩写。它是最基础的异步串行通信协议实现只包含最基本的TX发送、RX接收功能通信双方依靠事先约定好的波特率进行数据传输没有时钟线。我们常说的“串口通信”大多指的就是UART。USART是通用同步/异步收发传输器的缩写。顾名思义它是一个“全能选手”在UART功能的基础上增加了同步通信模式。在同步模式下USART可以额外提供一条时钟线CK用于在高速或需要严格时钟同步的场景下由主机提供时钟信号驱动从机进行数据收发。此外USART通常还支持硬件流控制RTS/CTS、LIN总线、智能卡模式等更丰富的功能。注意在STM32中所有标为USART的外设都兼容UART模式。也就是说当你只需要异步通信时完全可以把一个USART当成UART来用。因此在统计“串口”数量时我们通常将USART和UART的数量相加。但心里要明白USART的功能更强大在资源紧张时可以优先把USART分配给需要同步模式或硬件流控制的外设。那么一个串口无论是USART还是UART在物理上对应着什么它对应着MCU芯片上的一组特定的引脚。例如USART1_TX 和 USART1_RX 就是USART1这个外设的发送和接收引脚。STM32强大的引脚复用功能允许同一个物理引脚可以被配置为多种功能GPIO、定时器通道、ADC输入、串口等但在同一时刻一个引脚只能有一种功能。这就引出了下一个关键问题串口的数量不仅取决于芯片内部集成了多少个USART/UART外设还取决于这些外设的引脚是否与其他关键功能冲突以及你是否能成功地将它们“引”到芯片外部。3. 经典案例对比C8T6与ZET6的串口资源解剖理论说再多不如看两个活生生的例子。我们以意法半导体ST的STM32F103系列中两款经久不衰的型号为例它们分别代表了资源紧凑型和资源富裕型两种典型场景。STM32F103C8T6“蓝色药丸”核心这是一颗搭载Cortex-M3内核拥有64KB Flash和20KB RAM的MCU采用LQFP48封装。它在开源硬件领域极其流行成本低廉。内部外设它拥有3个串口具体是USART1、USART2、USART3。引脚映射与冲突这是关键所在。在48脚的封装下引脚数量有限这些串口的引脚可能与其他重要功能复用。USART1默认映射到PA9TX和PA10RX。但PA9和PA10同时也是USB的DP和DM引脚如果使用USB功能。更常见的一个冲突是PA9/PA10与SWD调试接口的SWCLK和SWDIO毫无冲突可以放心使用。USART2默认映射到PA2TX和PA3RX。注意PA2和PA3通常也是ADC的输入通道ADC_IN2, ADC_IN3。如果你的项目需要用到这两个通道进行高精度模拟量采集就需要权衡。此外PA2有时也被用作定时器2的通道3。USART3默认映射到PB10TX和PB11RX。这部分引脚冲突相对较少是比较“干净”的串口资源。我的踩坑经历我曾在一个项目中同时需要USB虚拟串口用USART1模拟、一个GPS模块USART2和一个蓝牙模块USART3。一切都很完美直到我想增加一个ADC按键检测恰好用到了PA2和PA3。这时就必须做出选择是牺牲ADC功能还是把蓝牙模块换到USART2然后腾出USART3的引脚最终我选择了后者并重新设计了PCB。教训就是在原理图设计阶段必须拿着芯片的引脚定义图把所有要用到的外设串口、ADC、I2C、SPI、定时器、USB、调试口的引脚需求全部列出来像下棋一样统筹规划避免后期“打架”。STM32F103ZET6“大容量”代表这是一颗同样基于Cortex-M3但拥有512KB Flash和64KB RAM的MCU采用LQFP144封装。引脚数量多了近两倍资源丰富度不可同日而语。内部外设它拥有5个串口具体是USART1、USART2、USART3、UART4、UART5。资源分析144个引脚带来了巨大的灵活性。除了上述3个USART它还额外提供了两个UART注意是UART不是USART。UART4和UART5通常映射到PC10/PC11和PC12/PD2等引脚上。引脚数量多意味着冲突大幅减少每个外设基本都有独立的、不冲突的引脚可用无需在USART、ADC、定时器之间做艰难取舍。功能可以并行你可以轻松实现同时与5个不同设备进行串口通信例如主调试日志USART1、触摸屏USART2、无线数传模块USART3、RS485总线设备UART4、另一个传感器UART5。设计更从容即使某个串口的默认引脚被占用你也有极大的概率在芯片的其他位置找到它的“重映射”引脚。从C8T6的3个串口且需精心规划到ZET6的5个串口且游刃有余这不仅仅是数量上的“2”更是项目复杂度和设计自由度的质变。对于需要连接多个串口外设的中大型项目ZET6这类144脚芯片几乎是必然选择。4. 超越数据手册如何准确查询与规划串口资源知道了串口数量很重要但怎么才能不踩坑呢不能光凭记忆或者道听途说必须掌握官方、准确的查询方法。第一步找到正确的数据手册千万不要只用中文的“参考手册”或网络博文。最权威的信息来源永远是ST官网提供的两个文档数据手册对应具体型号例如STM32F103xC/D/E datasheet。这份文档的核心是告诉你这颗芯片有什么以及这些外设对应到具体封装上的哪个引脚。你需要的关键表格是“Pin definitions”或“Pinout and pin description”。参考手册对应整个产品系列例如STM32F10x reference manual。这份文档的核心是告诉你这些外设怎么用包括寄存器详解、功能描述等。关于USART/UART的功能描述在这里。第二步解读引脚定义表在数据手册的引脚定义表中你会看到类似下面的描述以STM32F103C8T6的PA9为例引脚号引脚名称类型主功能默认复用功能重映射功能30PA9I/OFTUSART1_TXTIM1_CH231PA10I/OFTUSART1_RXTIM1_CH3主功能就是普通的GPIO。默认复用功能复位后通过配置复用功能寄存器可以将引脚切换到该功能。对于PA9就是USART1_TX。重映射功能部分外设的引脚可以通过“重映射”功能切换到另一组引脚上。这需要配置特定的重映射寄存器。不是所有外设和所有引脚都支持重映射需查表确认。第三步使用CubeMX进行可视化规划对于新手或复杂项目我强烈推荐使用ST官方的STM32CubeMX工具。它的最大优势就是可视化引脚冲突检测。在CubeMX中选择你的具体型号如STM32F103C8T6。在图形化界面上你可以直接点击芯片的某个引脚为其分配功能例如选择“USART2_TX”。如果该引脚已被其他已启用的功能占用比如ADCCubeMX会立即用醒目的颜色如橙色标记出来提示冲突。你可以尝试为同一个外设如USART2选择其他的“重映射”引脚如果芯片支持的话。规划好所有外设后CubeMX可以直接生成初始化代码极大减少底层配置的工作量。这个工作流能帮你把抽象的“串口数量”问题转化为直观的“引脚资源分配”问题从而在画原理图之前就杜绝了硬件层面的冲突。5. 当硬件串口不够用软件模拟与硬件扩展方案即使经过精心规划有时我们还是会面临串口不够用的窘境尤其是在使用C8T6这类小封装芯片做功能验证或原型开发时。别慌我们有多种“救火”方案。方案一软件模拟串口Software UART这是最灵活的方案不占用额外的硬件串口资源只需要两个普通的GPIO引脚一个模拟TX一个模拟RX和两个定时器通常一个用于精确的位时序生成一个用于超时检测。工作原理程序在一个高精度定时器如SysTick或通用定时器的中断里严格按照波特率周期手动控制GPIO引脚输出高低电平来模拟起始位、数据位、停止位。接收端则通过外部中断或定时器捕获来检测起始位然后采样数据位。优点理论上可以模拟无数个串口只要GPIO和定时器资源够用。成本为零。缺点CPU占用率高波特率越高定时器中断越频繁对CPU是沉重负担。9600波特率以下尚可115200就非常吃力了。精度和稳定性差容易受到其他中断的干扰导致时序错乱通信误码率高。实现复杂需要编写严谨的驱动代码处理各种异常情况如帧错误、噪声。适用场景极低波特率如1200 2400的通信或者对实时性要求不高的单向数据传输如仅发送调试信息。绝不推荐用于与关键传感器或模块的双向、高速、可靠通信。方案二使用串口扩展芯片这是最专业、最可靠的硬件解决方案。市面上有专用的多通道UART扩展芯片例如SC16IS7522通道、SC16IS7624通道等。它们通过I2C或SPI总线与STM32连接却可以提供额外的、独立的、全功能的硬件串口。工作原理STM32通过I2C/SPI像操作寄存器一样向扩展芯片读写数据。扩展芯片内部有独立的硬件UART负责完成所有串行通信的时序、缓冲工作。优点真正的硬件串口通信稳定可靠波特率高可达5Mbps以上不占用STM32的CPU时间。扩展能力强一颗芯片就能增加2-4个甚至更多串口。集成FIFO通常带有硬件FIFO缓冲区减少中断频率提高系统效率。缺点增加了额外的芯片成本和PCB面积。通信速率受限于I2C/SPI总线的速度。适用场景串口需求远超MCU自带数量且对通信质量和性能有较高要求的正式产品。方案三复用与协议设计有时问题可以通过优化系统设计来解决而不是增加硬件。单总线多设备如果多个从设备都支持Modbus RTU等标准总线协议可以将它们全部挂载在同一个UART上通过不同的设备地址进行区分。这需要每个设备都支持该协议。串口服务器/网关使用一个带多串口的廉价MCU如STM32F103ZE作为“串口汇聚网关”它负责与所有串口设备通信然后通过一个高速接口如USB、CAN或另一个串口与主STM32交换数据。这实际上是把串口压力转移了。评估非串口替代方案问问自己这个外设一定要用串口吗能否换成I2C或SPI后两者通常只需要2-4根线且可以挂载多个设备在连接多个同类传感器时可能更节省资源。在实际项目中我通常的决策路径是首先用CubeMX最大化利用硬件串口如果还差1个且波特率很低考虑软件模拟如果差2个以上或需要高速可靠通信毫不犹豫地选择串口扩展芯片。6. 项目选型实战如何根据串口需求选择STM32型号现在让我们把所有这些知识融会贯通落实到项目选型这个终极问题上。面对ST海量的STM32型号如何快速锁定目标第一步明确需求清单拿出一张纸列出所有需要连接的通信外设及其接口类型和预估波特率。 例如GPS模块UART 9600 bps4G Cat.1模块UART 115200 bpsAT指令、921600 bps数据透传串口触摸屏UART 115200 bpsRS485温湿度传感器UART 9600 bpsModbus RTU调试日志输出UART 115200 bps这样一看你至少需要4个独立的硬件串口调试口可以与下载口共用但通常不建议因为下载时需要复位。第二步增加安全余量在需求清单数量的基础上至少增加1个作为设计余量。产品开发过程中临时增加一个测试接口、一个备用通信通道是常有的事。所以这个项目至少需要选择一款拥有5个硬件USART/UART的STM32。第三步对照选型表与封装访问ST官网使用STM32产品选型工具。你可以直接筛选“USART/UART数量” 5。你会发现像STM32F103ZET6144脚、STM32F407ZGT6144脚、STM32F429ZIT6144脚等型号都会出现在列表中。 接下来关键点来了注意封装。同样有5个串口LQFP144封装和LQFP100封装引出的引脚可能不同。有些串口在较小封装下可能无法全部引出到外部引脚即被“阉割”了。你必须下载对应封装的数据手册确认你需要的每一个串口的TX/RX引脚都能被使用且不与你的其他关键功能如FSMC、SDRAM接口、高速USB冲突。第四步成本与性能权衡在满足串口数量和引脚需求的基础上再考虑其他因素主频与性能处理多个串口的高波特率数据流是否需要更高的主频内存每个串口都需要缓冲区同时运行多个串口中断服务程序是否需要更大的RAM其他外设是否需要CAN、以太网、USB OTG、加密引擎等成本与供货这是最终的决定性因素之一。一个实用的技巧是在项目原型阶段可以选择一款引脚兼容但资源更丰富的型号。例如你的产品最终可能定位于STM32F103C8T648脚但在开发板阶段完全可以使用同样48脚但串口更多的型号如果存在或者直接使用144脚的型号做验证待所有功能、引脚分配确认无误后再反向优化到目标型号这样可以避免因资源估计不足导致的硬件反复修改。7. 软件层面的优化高效管理多个串口通道硬件选对了只成功了一半。当你的STM32同时驱动着四五个串口且波特率都不低时软件架构若不合理系统很快就会崩溃。这里分享几个我实践中总结的软件优化要点。1. 中断服务程序要“短平快”串口通信严重依赖中断。无论是接收完成中断RXNE还是发送完成中断TC/TXE中断服务函数都必须尽可能短。经典错误在中断里进行复杂的数据解析如解析GPS的NMEA语句、调用printf、或进行耗时的内存操作。正确做法中断里只做最核心的两件事接收中断将数据从USART-DR寄存器快速读出来存入一个环形缓冲区FIFO然后立即清除中断标志并退出。发送中断从发送环形缓冲区中取出下一个待发送字节写入USART-DR寄存器如果缓冲区空了则关闭发送完成中断。 所有数据处理协议解析、命令响应都放在主循环或低优先级的任务中从环形缓冲区里读取数据。2. 使用DMA解放CPU这是提升多串口系统性能的神器。STM32的USART基本都支持DMA。接收DMA配置DMA通道自动将USART接收到的数据搬运到你指定的内存缓冲区。你可以设置DMA在接收满一定数量数据如一帧数据长度后产生中断然后一次性处理一整帧数据这比每个字节都中断一次效率高得多。发送DMA将需要发送的一大段数据如一帧响应报文放入缓冲区启动DMADMA会自动将数据搬运到USART发送寄存器无需CPU干预。发送完成后产生中断通知CPU即可。 使用DMA后CPU仅在数据块收发完成时才被中断一次极大降低了中断频率和CPU负载。对于高速串口如921600bps的4G模块数据透传DMA几乎是必选项。3. 环形缓冲区设计无论是中断模式还是DMA模式环形缓冲区都是核心数据结构。它解耦了“数据产生中断”和“数据消费主程序”的速度。实现要点需要两个索引写索引write_idx和读索引read_idx和一个缓冲区数组。写索引在中断中推进读索引在主程序中推进。判断“缓冲区满”的条件是(write_idx 1) % BUFFER_SIZE read_idx这样总会保留一个空位避免歧义。线程安全如果使用了RTOS多个任务可能同时访问缓冲区需要使用信号量、互斥锁来保护读写操作。4. 协议分层与模块化不要为每个串口写一套庞大而混乱的代码。应该将代码分层硬件驱动层封装最底层的USART初始化、中断/DMA配置、单个字节的收发函数。这一层与具体业务逻辑无关。数据链路层管理环形缓冲区提供“读取一帧数据”、“发送一帧数据”的接口。可以在这里实现简单的数据分包、粘包处理如基于超时或特定帧头帧尾。应用协议层针对每个外设的特定协议如Modbus RTU、NMEA-0183、自定义AT指令集进行解析和封装。每个串口对应一个独立的协议解析模块。 这样的结构清晰可维护性强。当需要更换一个外设比如从A品牌GPS换到B品牌时你只需要更换对应的应用协议层模块底层驱动完全不用动。管理多个串口就像指挥一个交响乐团硬件是乐器软件是指挥谱。合理的资源分配硬件选型和清晰的调度逻辑软件架构相结合才能让每个“声部”和谐有序地工作奏出稳定的系统乐章。记住在嵌入式世界里最宝贵的往往不是CPU的运算速度而是那些看似简单却数量有限的外设资源以及你驾驭它们的能力。