嵌入式开发学习记录:USART串口通信
文章目录本文记录了嵌入式开发中 USART 串口通信的学习过程包含理论学习、环境搭建、代码实现与问题排查等内容。以下是文章结构概览 学习进度概览 学习记录与问题追踪1. 理论学习与概念梳理2. 环境搭建与第一个工程3. 轮询模式工程创建代码实现与调试过程4. 中断模式工程创建代码实现与调试过程5. DMA模式工程创建代码实现与调试过程6. printf重定向到usart串口上实现printf打印信息到串口助手上 学习进度概览当前学习阶段嵌入式开发 - USART 串口通信当前使用的开发板STM32F407VGT6-Disk开始时间2026 年 8 月 22 日学习目标理解 USART通用同步异步收发器的基本工作原理掌握 STM32或其他 MCU的 USART 外设配置流程能够实现基本的串口收发功能查询/中断/DMA 方式记录并解决学习过程中遇到的实际问题注意本文中每个实验均另开了一个工作空间并重新创建项目并非在原先工程上做出改变 学习记录与问题追踪1. 理论学习与概念梳理时间2026/08/16内容复习了串行通信与并行通信的区别。理解了 USART 与 UART 的关键差异USART 支持同步模式有时钟线UART 仅支持异步。学习了波特率、数据位、停止位、奇偶校验等关键参数的含义。2. 环境搭建与第一个工程时间2026/08/20内容使用 STM32CubeMX 初始化 USART 外设生成代码。使用 STM32CubeIDE 进行开发。使用 USB 转 TTL 模块连接电脑配合串口助手工具进行调试。遇到的问题串口助手打印结果乱码串口助手无打印结果配合 printf 函数重定向但 printf 函数没能打印出结果3.轮询模式工程创建代码实现与调试过程时间2026/08/20使用 STM32CubeMX 创建新工程并开启外部高速晶振HSE作为系统时钟源。创建工程开启外部晶振配置时钟修改 debug 模式开启串口为异步模式勾选为每个外设单独生成 .c/.h 文件生成代码使用 VS Code 打开项目借助扩展包采用提示词工程给出的代码写好测试发送的代码打开 CubeIDE代码自动更新点击小锤子编译无报错无警告按照设置的串口连接好硬件及开发板为 USB 转 TTL 模块下载好驱动本文采用波特律动串口助手中提供的驱动下载链接下载好 CH340 型号驱动并按如图方式连接好硬件部分TXD 接 PA10RXD 接 PA9并将 USB 口接在电脑上烧录代码打开波特律动串口助手选择好串口并开启查看串口信息打印遇到的实际问题与解决方案发现串口有东西打印出来且打印间隔为原 while 函数中设置的 1 秒但是打印出来的数据是乱码本应该是 Hello World时间间隔没问题则程序确实进入了 while 循环且循环没问题但数据乱码问题大概率出在波特率不匹配硬件接线问题[最终解决方案]修改连接的串口我最终改成使用usart2串口使用PA2,PA3两个引脚--取消时钟配置--并重新生成代码代码最终逻辑如图波特率校验位等无任何修改最终得到串口输出结果改写代码为接收电脑发送的数据并用发送函数检验是否收到最终也能成功返回发送的数据最后总结原因成功与失败的最大区别是取消了外部晶振提供时钟采用的内部HSI大概率就是这个原因影响了串口4.中断模式工程创建代码实现与调试过程时间2026/08/21MX工程创建与轮询方式类似但本次不使用外部时钟且勾选usart2的全局中断点击usart2的NVIC标签勾选全局中断保存并生成代码代码仅需将发送接收函数加上_IT后缀将传递的超时时间字段去掉即可。编译并烧录查看串口助手打印结果结果在未发送任何数据时界面不断发送空发送了R0后界面不断发送R0回来查看代码发现将两个中断模式的发送接收函数都写到while循环里了中断模式不像轮询模式一样是非阻塞的会一直循环执行导致循环过快而显示如图样式只要将中断接收函数放到while循环外即可但是一般不会将中断发送放在while循环里不然也会导致上述结果一般是中断接收后调用中断处理函数HAL_UART_RxCpltCallback此函数可自己重新定义一下并将逻辑写入而后中断接收完成后将执行函数中的逻辑那有要求中断接收不能放在while循环里要保证能不断接收则可将中断接收函数放在中断处理函数的末尾这样中断处理函数逻辑完成前就会进入下一次中断接收。5.DMA模式工程创建代码实现与调试过程时间2026/08/21MX项目创建只要基于中断模式下再添加DMA通道即可如图分别添加Rx和Tx的DMA通道保持默认设置即可保存并生成代码发送、接收函数仅需在中断发送函数的基础上将_IT后缀改为_DMA即可我在中断回调处理函数中加上了阻塞式发送并在末尾补上DMA接收将接收数组放在PV注释对中以防报错编译烧录查看串口助手发现能正常接收并回复接收不定长数据主要靠的是串口空闲中断使用HAL_UARTEx_ReceiveToIdle这个函数也有阻塞中断DMA三种方式也是通过修改后缀即可使用另外使用此函数对应的回调函数也有所不同这里应使用HAL_UARTEx_RxEventCallback回调函数这里我直接使用DMA方式在本工程里进行测试结果如图由于我定义的数组长度是50所以发送过长时触发了传输过半中断故而后面的数据没能返回可以使用_HAL_DMA_DISABLE_IT函数取消传输过半中断。6.printf重定向到usart串口上实现printf打印信息到串口助手上时间2026/08/21目前尝试了各种方法如重写fputc函数重写_write函数关闭半主机模式代码实现写在fputc函数后均未能实现须待解决