news 2026/10/28 2:01:38

STM32CubeMX配置串口通信(F407ZGT6)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32CubeMX配置串口通信(F407ZGT6)

CubeMX部分

摘要:本文以 STM32F407ZGT6 为例,完整记录了使用 STM32CubeMX 配置 USART1 串口通信的全过程。内容涵盖原理图引脚确认(PA9 为 TX、PA10 为 RX)、CubeMX 中使能 USART1 并设置波特率 115200、8 位数据位、1 位停止位、无校验等参数,以及过采样率 16 倍采样的作用与原理。随后给出库函数层面的 usart.c 配置流程(开启时钟、GPIO 复用推挽输出、连接串口、写入寄存器),并在 main.c 中通过 HAL_UART_Transmit / HAL_UART_Receive 实现串口收发,配合 if 与 switch 两种写法解析上位机指令控制 LED 亮灭,适合 STM32 串口入门参考。

先声明一下:我使用了别人的图片,如果介意看到了,联系我后会删除与修改。
STM32F407ZGT6 原理图


由上面两图可以看出:
USART1 接在 PA9 和 PA10 这两个引脚上。


在图形化界面中可以清晰地看到:
PA10 — RX(接收)
PA9 — TX(发送)


这里可以看到,USART1 已经被标上了 √。

先看到上面,对应着:

第一个参数对应着波特率(常见的有 115200、9600)。
数据位长度(Word Length)对应着数据位的位数。
由于一个字节要 8 个 bit 位,所以这里用 8 bits。
常见的还有 9 bits,这个多一位一般是给奇偶校验位的(只能一定程度上减少出错的风险)。

同时起始位和停止位各自都有一位(一般情况)。
起始位:低电平。
停止位:高电平。
其中低位先行与小端字节序很像。

校验位(Parity):这里选择无校验。
停止位(Stop Bits):给一位。**********
其他的目前不需要(这里默认会配置LED部分哈)
然后打开vscode

库函数代码部分


找到 usart.c 文件

从中间一段看起
先设置外设 - USART1
配置通信速率 - 115200 bits/s
设置数据位长度(Word Length)- 8 位
停止位(Stop Bits)- 一位
校验位(Parity)- 无
模式(Mode)- 发送和接收
硬件流控制(Hardware Flow Control)- 不需要
过采样率(OverSampling)- 16 倍
判断是否配置成功 - 否则进入错误中断部分,防止出现未知错误。

过采样率的作用

在一个数据位之间连续采样 16 次,其中第 8、9、10 次如果全是高电平,则认为是 1;如果全是低电平,则认为是 0。

特别地,如果第 8、9、10 次采样中出现不一致的电平,则采用「少数服从多数」的原则:

  • 1、1、0 → 1
  • 0、0、1 → 0

其他组合同理。不过一旦出现这种采样不一致的情况,通常说明链路存在问题,例如波特率不匹配、地线没有共地、走线太长或周围有强电磁干扰。


这里只解释重要的参数,其他的自行了解。
模式(Mode)- 复用推挽输出模式。
上、下拉(Pull-up/Pull-down)- 无。
速度(Speed)- 非常高(减少信号的上升、下降沿时间,保证通信质量)。
配置引脚的复用功能编号(Alternate Function)- 将 PA9、PA10 连接到 USART1 外设。

配置流程可以概括为:

开启时钟(GPIOA、USART1)→ PA9、PA10 初始化为复用推挽输出 → 连接串口外设 → 写入寄存器完成配置。

核心配置(main.c)

下面先用一张流程图把 main.c 里串口收发的完整判断逻辑串起来,再逐段看代码:

'0'

'1'

'0'

'1'

其他

进入 while(1) 主循环

HAL_UART_Transmit 发送 receive_data 两个字节

HAL_UART_Receive 接收上位机发来的两个字节到 receive_data

解析 receive_data[1]

state = GPIO_PIN_RESET(熄灭)

state = GPIO_PIN_SET(点亮)

解析 receive_data[0]

操作 LED1(GPIOF / LED1_Pin)

操作 LED2(GPIOF / LED2_Pin)

不动作,直接进入下一轮

回到 while(1) 循环开头

receive_data是一个长度为 2 的uint8_t数组,两个字节分工明确:receive_data[0]用来选择要操作哪一颗 LED('0'对应 LED1,'1'对应 LED2),receive_data[1]用来决定这颗 LED 是亮还是灭('0'表示关,'1'表示开)。所以上位机只要发两个字符,例如"01",就表示「选中 LED1 并点亮」,"10"则表示「选中 LED2 并熄灭」。


接下来补充代码部分,在使用串口部分时要先验证一下哦~
方法一代码:

// char message[] = "Hello world";staticuint8_treceive_data[2];/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while(1){/* *message需要强制转换为uint*_t类型的指针,否则会报错 */// HAL_UART_Transmit(&huart1, (uint8_t*)message, strlen(message), 100);HAL_UART_Transmit(&huart1,receive_data,2,HAL_MAX_DELAY);HAL_UART_Receive(&huart1,receive_data,2,HAL_MAX_DELAY);GPIO_PinState state=GPIO_PIN_SET;if(receive_data[1]=='0'){state=GPIO_PIN_RESET;//PF9 -- PF10}if(receive_data[0]=='0'){HAL_GPIO_WritePin(GPIOF,LED1_Pin,state);}elseif(receive_data[0]=='1'){HAL_GPIO_WritePin(GPIOF,LED2_Pin,state);}/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}

方法二代码:用 if 语句实现

方法一直接在while(1)里用HAL_GPIO_WritePin写引脚电平,方法二则把「选 LED + 定亮灭」拆成LED1_ON()、LED1_OFF()这类宏或函数,可读性更好。下面先给出 if 嵌套的写法:

/* *方法二 *0一般是关 *1一般是开 */if(receive_data[1]=='0'){if(receive_data[0]=='0'){LED1_OFF();}elseif(receive_data[0]=='1'){LED2_OFF();}}elseif(receive_data[1]=='1'){if(receive_data[0]=='0'){LED1_ON();}elseif(receive_data[0]=='1'){LED2_ON();}}

switch 语句实现(更简洁)

/* *方法二 *switch语句实现 *0一般是关 *1一般是开 */switch(receive_data[1]){case'0':{if(receive_data[0]=='0'){LED1_OFF();}elseif(receive_data[0]=='1'){LED2_OFF();}break;}case'1':{if(receive_data[0]=='0'){LED1_ON();}elseif(receive_data[0]=='1'){LED2_ON();}break;}default:break;}

这里也可以把receive_data[0]的判断再拆成一层 switch,代码会更整齐。

结语

本文从 CubeMX 的引脚与参数配置讲起,一路走到main.c里的串口收发与 LED 控制,核心其实就是三件事:引脚复用配对(PA9/PA10)、串口参数一致(115200-8-N-1)、收发数据按约定解析。

如果后续想继续扩展,可以尝试:

  • 用串口中断或 DMA 替代阻塞式HAL_UART_Receive,避免主循环被卡住;
  • 增加帧头帧尾或校验位,让指令解析更可靠;
  • 把 LED 控制封装成独立模块,方便移植到其他工程。

本人水平有限,只是把了解到的一点知识整理出来,欢迎各位大佬在评论区指正。下一篇见!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/28 2:01:28

ollama v0.40.11发布:macOS原生语音生成上线,d3决策模型正式加入

2026年10月26日,Ollama 发布 v0.40.11 版本。本次更新围绕两个核心方向展开:一是面向 macOS 的语音生成能力,二是引入 d3 决策模型。 对于希望让文本、聊天回复直接以语音形式输出的使用者来说,v0.40.11 带来了新的语音生成方式&a…

作者头像 李华
网站建设 2026/10/28 2:01:27

从零到一认识外骨骼(2)

接前一篇文章:从零到一认识外骨骼(1) 本文内容参考: 知识宝典丨解码科技:外骨骼机器人的前世今生 从《明日边缘》走向现实世界 军用动力外骨骼编年史 _ 游民星空 GamerSky.com 外骨骼机器人(一&#xff…

作者头像 李华
网站建设 2026/10/28 2:01:25

OpenCV用python处理图片

目录 通用步骤自定义保存操作按键分类保存 PyCharm 在导入 OpenCV 的包之后,最基础的是如何对一个图片进行操作。 通用步骤有几部: 1:导包(导入 OpenCV 图像处理库,cv2 就是它在 Python 里的名字。导入后你就能调用…

作者头像 李华
网站建设 2026/10/28 2:01:23

大模型微调手记:从显存账本到 vLLM 上线,我踩过的那些坑

上个月给一个知识库项目收尾,模型训完上线,业务方第一句话是"它怎么说话跟以前一样"。翻训练日志才发现 eval loss 早就不动了,我一直在看 train loss 往下掉。那次之后我改了自己的顺序:先算显存,再定数据&…

作者头像 李华
网站建设 2026/10/28 2:00:55

数组,一维数组,二维数组

1、数组的概念数组是一组相同类型元素的集合数组中存放的是1个或者多个数据,但数组的元素个数不能为0数组中存放的多个数据,类型是相同的数组分为一维数组和多维数组,多维数组比较常见的是二维数组2、一维数组的创建与初始化2.1 数组创建基本…

作者头像 李华
网站建设 2026/10/28 2:00:03

代码漏洞检测-python+Flask

本项目为前几天收费帮学妹做的一个项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 基于pythonFlask代码安全检测系统通过Mysql数据库连接数据库 http://127.0.0.1:510…

作者头像 李华