目录

STM32HAL-快速入门十八UART-编程一-查询方式实现串口收发

STM32HAL 快速入门(十八):UART 编程(一)—— 查询方式实现串口收发

前言

大家好,这里是 Hello_Embed。上一篇我们拆解了 STM32 UART 的硬件结构,理解了寄存器配置、数据收发的底层流程。本篇将进入实战环节,先用最基础的 “查询方式” 实现串口通信 —— 完成 “单片机发送字符串到电脑”“电脑发送字符,单片机接收后加一返回” 两个功能,同时明确查询方式的优缺点,为下一篇 “中断方式” 和后续 “DMA 方式” 铺垫。

一、实战准备:硬件连接与驱动安装

在编程前,需先完成硬件连接、驱动安装和串口工具配置,确保单片机与电脑能正常通信。

1. 硬件连接:TX 与 RX 交叉对接

需使用 “USB-TTL 转接器” 连接单片机与电脑,核心原则是 “发送接接收,接收接发送”

  • 转接器的 TXD → 单片机的 PA10(USART1_RX)
  • 转接器的 RXD → 单片机的 PA9(USART1_TX)
  • 转接器的 GND → 单片机的 GND(共地,避免信号干扰)。
    实际连接可借助面包板,确保引脚接触可靠,转接器实物示意:
    https://i-blog.csdnimg.cn/direct/9b36a689ef284e63a7ceccc71a4c1a11.png
2. 驱动安装与 COM 口确认
  • 安装 USB-TTL 转接器驱动(如 CH340 驱动,可在 B 站搜索安装教程,此处不展开);
  • 驱动安装完成后,将转接器插入电脑 USB 口,打开 “设备管理器→端口”,确认串口对应的 COM 号(本文为 COM9),后续串口工具需匹配此 COM 口:
    https://i-blog.csdnimg.cn/direct/27de362caf714ba5adca73976c40dffa.png
二、UART 三种编程方式对比

结合 UART 硬件结构,常用编程方式有三种,核心区别在于 “CPU 参与度” 和 “效率”:

编程方式核心逻辑优点缺点适用场景
查询方式CPU 轮询状态寄存器(SR),判断收发时机逻辑简单,代码量少占用 CPU 资源,数据不及时读取易丢失简单调试、低速率小数据量通信
中断方式硬件触发中断,CPU 仅在中断时处理收发不占用 CPU 资源,响应快逻辑稍复杂,需处理中断回调中速率数据通信,需兼顾其他任务
DMA 方式DMA 替 CPU 完成寄存器与内存的数据搬运完全不占用 CPU 资源配置复杂,需理解 DMA 硬件逻辑高速、大数据量通信(如 LCD 显示 + 串口收发)

本篇聚焦 “查询方式”,后续两篇将分别讲解中断和 DMA 方式,三种方式的核心函数参考:

https://i-blog.csdnimg.cn/direct/26caa35586b044a698e726dc84424d84.png

三、CubeMX 配置 UART(USART1)

查询方式的配置非常简单,只需使能 UART 异步模式并确认基础参数:

  1. 选择 UART 外设
    进入 “Connectivity→USART1”,设置 “Mode” 为 “Asynchronous”(异步模式),系统会默认分配 PA9(TX)和 PA10(RX),无需修改引脚:
    https://i-blog.csdnimg.cn/direct/94994a54833e48dab710729770e57ded.png
  2. 确认通信参数
    进入 “Parameter Settings”,检查基础参数是否符合默认配置(与电脑串口工具需一致):
  • 波特率(Baud Rate):115200(常用速率,兼顾速度与稳定性);
  • 数据位(Word Length):8 Bits;
  • 校验位(Parity):None(无校验);
  • 停止位(Stop Bits):1 Bit;
    无需修改其他配置(中断、DMA 暂不启用):
    https://i-blog.csdnimg.cn/direct/76118f89fd764c7b9664e3b0df79e569.png
  1. 生成工程
    配置完成后生成代码,工程中会自动添加 USART 相关文件(如stm32f1xx_hal_usart.c),并在main.c中生成初始化函数MX_USART1_UART_Init()
四、查询方式代码实现

查询方式的核心是 “CPU 通过轮询状态寄存器,判断是否可收发数据”,主要使用 HAL 库的HAL_UART_Transmit(发送)和HAL_UART_Receive(接收)函数。

1. 串口发送:单片机→电脑

目标:单片机循环发送字符串 “Hello_Embed !\r\n” 到电脑,通过串口工具查看。

  1. 定义发送数据
    main.c的 “USER CODE BEGIN 2” 区域定义要发送的字符串:
/* USER CODE BEGIN 2 */
char *str = "Hello_Embed !\r\n";  // 要发送的字符串,\r\n是换行符
/* USER CODE END 2 */
  1. 调用发送函数
    while(1)循环中调用HAL_UART_Transmit,函数参数解析如下:
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
  • *huart:UART 句柄指针,此处为&huart1(CubeMX 自动定义的 USART1 句柄);
  • *pData:发送数据缓冲区指针,此处为(uint8_t *)str(字符串强转为字节指针);
  • Size:发送数据长度,用strlen(str)获取字符串实际长度(不含结束符 ‘\0’);
  • Timeout:超时时间(ms),设为 1000(1 秒内未发送完成则返回超时错误)。
    完整发送代码:
while (1)
{
  /* USER CODE END WHILE */
  /* USER CODE BEGIN 3 */
  // 发送字符串到电脑
  HAL_UART_Transmit(&huart1, (uint8_t *)str, strlen(str), 1000);
  HAL_Delay(500);  // 延时500ms,避免数据发送过快
  /* USER CODE END 3 */
}
  1. 实验结果
    打开串口工具(本文用 “纸飞机”),选择 COM9、波特率 115200,烧录程序后,工具会持续收到字符串,证明发送成功:
    https://i-blog.csdnimg.cn/direct/fcdc568e4f494afda87d2de8ecc13770.png
2. 串口接收与返回:电脑→单片机→电脑

目标:电脑发送一个字符,单片机接收后加 1 返回(如发送 ‘1’ 返回 ‘2’,发送 ‘a’ 返回 ‘b’)。

  1. 定义接收相关变量
/* USER CODE BEGIN 2 */
char *str1 = "Please enter a char : \r\n";  // 提示用户输入
char c;  // 存储接收的字符
/* USER CODE END 2 */
  1. 接收与返回逻辑
    while(1)中先发送提示信息,再等待接收电脑发送的字符,接收成功后加 1 返回:
while (1)
{
  /* USER CODE END WHILE */
  /* USER CODE BEGIN 3 */
  // 1. 发送提示信息
  HAL_UART_Transmit(&huart1, (uint8_t *)str1, strlen(str1), 1000);
  
  // 2. 等待接收电脑发送的1个字符(超时100ms,循环等待直到接收成功)
  while (HAL_OK != HAL_UART_Receive(&huart1, (uint8_t *)&c, 1, 100));
  
  // 3. 字符加1(ASCII码递增)
  c = c + 1;
  
  // 4. 返回加1后的字符,加换行符便于查看
  HAL_UART_Transmit(&huart1, (uint8_t *)&c, 1, 1000);
  HAL_UART_Transmit(&huart1, (uint8_t *)"\r\n", 2, 1000);  // \r\n占2个字节
  /* USER CODE END 3 */
}
  1. 关键说明:
    • HAL_UART_Receive参数:接收 1 个字符(Size=1),超时 100ms;用while循环等待HAL_OK(接收成功),避免提示信息不停发送;
    • 字符加 1 原理:字符在计算机中以 ASCII 码存储,如 ‘1’ 的 ASCII 码是 0x31,加 1 后变为 0x32(对应 ‘2’),‘a’(0x61)加 1 后变为 ‘b’(0x62)。
  2. 实验结果
    电脑发送 ‘1’,单片机返回 ‘2’;发送 ‘a’,返回 ‘b’;用 HEX 模式发送 0x31(即 ‘1’ 的 ASCII 码),返回 0x32(即 ‘2’),符合预期:
    https://i-blog.csdnimg.cn/direct/cb31f7209e1c434ca8a01c5377b422ef.png
五、查询方式的缺陷

虽然查询方式实现简单,但存在明显不足:数据不及时读取易丢失。例如,电脑快速发送 “12345”,单片机因轮询等待,可能只接收到部分字符(如仅收到 ‘1’ 和 ‘3’),无法完整返回 “23456”—— 这是因为 CPU 在处理前一个字符时,后一个字符已被新数据覆盖。
要解决数据丢失问题,需采用 “中断方式” 让硬件主动通知 CPU 接收数据,这正是下一篇笔记的重点。

结尾

本文用查询方式实现了 UART 的基础收发功能,理解了 HAL 库HAL_UART_TransmitHAL_UART_Receive的用法,同时明确了查询方式的适用场景与缺陷。下一篇我们将学习 “UART 中断方式”,通过中断回调函数高效处理收发,彻底解决数据丢失问题。
Hello_Embed 继续带你从基础到进阶,逐步掌握 UART 的高效编程技巧,敬请期待~