当前位置:首页 > 技术学院 > 技术前线
[导读]在嵌入式开发的入门学习路径中,STM32F103的串口通信是绝大多数开发者接触的第一个外设实操项目。作为一款诞生多年、生态极其成熟的经典MCU,STM32F103系列内置最多5个串口外设,从最基础的调试日志打印,到和传感器、上位机的双向数据交互,串口是整个嵌入式开发体系中使用频率最高的通信外设。很多新手开发者刚上手的时候,照着教程配置完CubeMX生成代码,串口上电之后完全没有任何输出,反复排查很久都找不到问题根因,连最简单的printf重定向都频频踩坑。

在嵌入式开发的入门学习路径中,STM32F103的串口通信是绝大多数开发者接触的第一个外设实操项目。作为一款诞生多年、生态极其成熟的经典MCU,STM32F103系列内置最多5个串口外设,从最基础的调试日志打印,到和传感器、上位机的双向数据交互,串口是整个嵌入式开发体系中使用频率最高的通信外设。很多新手开发者刚上手的时候,照着教程配置完CubeMX生成代码,串口上电之后完全没有任何输出,反复排查很久都找不到问题根因,连最简单的printf重定向都频频踩坑。

串口通信的底层逻辑看起来简单,但是想要在STM32F103上实现稳定可靠的双向收发,背后有大量容易被忽略的细节,从时钟树配置、引脚复用,到收发模式选择、中断和DMA的优化,每一个环节的疏漏都会导致通信异常。今天我们就从零基础入门到高级优化,全面拆解STM32F103串口的完整使用方法,帮你彻底掌握这项最核心的嵌入式外设技能。

STM32F103串口的基础认知

STM32F103系列的串口外设分为两大类,其中1到3号是通用同步异步串行接口USART,不仅支持常规的异步串口通信,还可以同步对接外部时钟源,实现SPI主模式的同步通信;4号和5号是通用异步串行接口UART,只支持标准的异步串口通信,没有同步功能。所有串口的核心寄存器完全兼容,操作逻辑基本一致,入门阶段从最常用的USART1开始上手是最高效的选择。

STM32F103的串口是完全基于APB总线挂载的外设,不同串口对应的时钟总线不同:USART1挂载在APB2总线上,最高时钟频率可以达到72MHz;剩下的USART2、USART3、UART4、UART5全部挂载在APB1总线上,最高时钟频率是36MHz。很多新手配置串口的时候,直接在CubeMX里把系统主频设为72MHz,却忘记确认APB1的预分频系数,导致APB1总线时钟不是36MHz,最终串口的实际波特率和预期值出现明显偏差,通信的时候出现大量乱码,这是入门阶段最常见的低级错误。

异步串口通信的核心优势是不需要额外的时钟线同步,只需要TX发送引脚、RX接收引脚和GND地线三根线,就能实现两个设备之间的双向数据传输。通信双方只需要提前约定好完全一致的波特率、数据位长度、停止位数量、校验位规则,就能实现稳定的数据交互,硬件接线极其简单,几乎所有嵌入式传感器、调试模块都默认支持串口通信协议,这也是它至今依然是嵌入式开发第一通信外设的核心原因。

基于STM32CubeMX的标准配置流程

现在几乎所有开发者都不再直接操作寄存器配置串口,用STM32CubeMX图形化工具完成初始化配置,既高效又不容易出错,一套标准的配置流程可以覆盖90%以上的常规应用场景。

第一步新建工程,在芯片选型界面精准选中你使用的STM32F103具体型号,注意区分C8T6、CBT6不同封装的引脚差异,避免后续引脚配置出现错位。接下来首先配置RCC时钟,把高速外部时钟HSE设置为外部晶振模式,配置系统主时钟为72MHz,同时确认APB2预分频器不分频,APB1预分频器设置为2分频,保证APB2总线时钟为72MHz,APB1总线时钟为36MHz,这是STM32F103串口稳定运行的标准时钟配置,从根源上避免波特率偏差的问题。

第二步配置调试接口,把SYS里的Debug选项设置为Serial Wire串行线调试模式,绝对不能保持默认的无调试模式,否则代码第一次下载之后,调试器就再也无法连接芯片,只能按住复位键抢时间重新下载,后续调试会非常麻烦。

第三步进入串口配置界面,选择你要使用的串口外设,把模式设置为异步模式Asynchronous,然后配置核心通信参数:常用的波特率选择115200,数据位长度8位,停止位1位,无校验位,这是嵌入式开发中最通用的串口通信参数,几乎所有串口调试助手都默认支持这套配置。接下来配置串口对应的GPIO引脚,USART1默认的TX引脚是PA9,RX引脚是PA10,把TX引脚配置为复用推挽输出模式,RX引脚配置为上拉输入模式,避免引脚悬空引入干扰。

最后进入项目管理器界面,设置好工程名称和存储路径,注意路径绝对不能包含中文和空格,否则后续Keil编译的时候会出现莫名其妙的报错。工具链选择MDK-ARM V5,勾选“为每个外设生成独立的.c/.h文件”选项,让生成的代码结构更清晰,点击生成代码,就能得到完整的串口初始化工程。

收发逻辑实现与高级优化技巧

生成完基础初始化代码之后,就可以在Keil工程里编写串口的收发业务逻辑,从最简单的基础发送,逐步升级到高效的中断和DMA模式,适配不同复杂度的业务场景。

最基础的串口发送实现,直接调用HAL库提供的HAL_UART_Transmit函数,传入串口句柄、数据缓冲区指针和数据长度,函数会阻塞运行直到所有数据全部发送完成。入门阶段最常用的调试功能,就是把标准库的printf函数重定向到串口1,重写fputc函数,把printf的输出全部转发到串口发送接口,之后你就可以像在PC端开发一样,直接调用printf函数打印调试日志,不用手动一个个发送字节,调试效率大幅提升。

这种阻塞式发送模式逻辑最简单,代码最稳定,完全不会出现数据错乱的问题,但是发送大量数据的时候会全程阻塞CPU,无法处理其他业务逻辑,只适合调试打印这类数据量小、实时性要求不高的场景。如果你的项目需要持续发送大量数据,就可以改用中断发送模式,调用HAL_UART_Transmit_IT函数启动非阻塞发送,CPU不需要全程等待串口发送完成,发送过程完全由中断自动处理,发送完成之后会触发对应的完成回调函数,CPU可以在发送的间隙处理其他业务,大幅提升CPU的利用率。

对于需要频繁接收外部设备数据的场景,绝对不能采用轮询查询标志位的方式读取串口数据,这种模式不仅浪费CPU资源,还很容易出现丢包问题。正确的做法是开启串口接收中断,调用HAL_UART_Receive_IT函数预先指定好接收缓冲区,当串口收到数据的时候自动触发中断,在中断服务函数里把数据存入缓冲区,业务主循环里再处理接收到的完整数据包。STM32F103的串口中断回调函数里,一定要记得重新调用接收函数,开启下一次的接收中断,否则第一次接收完成之后,后续所有数据都不会再触发中断,直接出现接收卡死的问题,这是新手开发串口接收时最高发的踩坑点。

如果你的项目需要串口持续高速传输大量数据,比如传输图片、升级固件,还可以开启串口的DMA收发模式,让数据的搬移完全由DMA硬件自动完成,不需要CPU参与任何字节拷贝操作,串口的收发全程零占用CPU资源,哪怕波特率跑到1Mbps以上,也不会出现任何丢包问题,是高性能串口应用的最优方案。

实际调试过程中如果遇到串口完全没有输出的问题,按照固定的排查顺序一步步来:首先确认硬件接线TX接RX、RX接TX没有接反,然后检查串口调试助手的波特率等参数和配置完全一致,再确认GPIO引脚的复用模式配置正确,最后用示波器测量TX引脚的输出波形,几乎所有问题都能快速定位。

STM32F103的串口是所有嵌入式外设中性价比最高的入门学习对象,吃透它的配置和优化技巧,你就能快速打通硬件和上位机之间的通信链路,为后续更复杂的外设开发打下坚实的基础。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭