STM32 UART 基础与实战

1. 串行输入输出接口的基本概念

串行通信的基本模式:

  • 单工传输:一个设备只能发送或接受。
  • 半双工:通信双方都可以进行发送和接收,但一台设备不能同时发送和接收。
  • 双工传输:可以同时进行双向通通信。

串行通信协议类型:

  • 同步串行通信协议:通信双方共用一个时钟,并由时钟来实现发送端和接收端的同步。
  • 异步串行通信协议:不需要时钟做同步,但双方必须使用各自的时钟保持相同的传送波特率(每秒传送数据二进制代码的位数,单位是b/s),并以每个字符数据的起始位与发送设备保持同步。数据以相同的帧格式传送,每一帧由起始位、数据位、校验位、停止位组成。

时钟与数据采样

二进制数据在串行传输过程中以数字信号波形的形式出现。无论是发送还是接收,都需要时钟信号对数据进行定位。

  • 同步传输:发送端和接收端共用同一个时钟,时钟频率等于波特率,每个数据位只需采样一次,通信速度快但需要额外的时钟线,实现更复杂。
  • 异步传输:双方不需要共享时钟,而是各自保持相同的波特率。通常,接收端的时钟频率会设置为波特率的 8、16 或 64 倍,通过多次采样来降低噪声干扰和时钟漂移的影响。例如,时钟频率为波特率的 8 倍时,每接收一个数据位会采样 8 次,从而提高数据的可靠性。虽然异步通信速度略慢,但实现简单、连线更少,广泛应用于实际工程中。

2. UART 通信简介

UART(Universal Asynchronous Receiver/Transmitter,通用异步收发传输器)是一种常见的串行通信(一次只能传输一个二进制位,数据需要一位一位地传输)协议,广泛应用于嵌入式系统。典型应用包括调试信息输出、外设通信(如 GPS、蓝牙、WiFi 模块)、MCU 之间数据交互

UART控制器基本结构 

图片来源:网络

上图展示了一个异步串行总线控制器的内部结构。主要模块说明如下:

  • 波特率发生器(Clock Generator):用于产生发送和采样时钟,决定数据传输速率。
  • 发送寄存器(Transmitter Register):用于从总线写入数据到 UART,准备发送。
  • 接收寄存器(Receive Register):用于将接收到的数据从 UART 传输到总线。
  • 移位寄存器(Shift Register):负责将一个字符的数据逐位发送到 TX 引脚,或从 RX 引脚逐位接收并组装成完整字符。

通过这些模块的协作,UART 能够实现高效、可靠的串行数据收发。

UART 帧通常包括以下部分:

  • 空闲(Idle,逻辑高电平 1):总线未传输数据时保持高电平。
  • 起始位(Start bit,逻辑低电平 0):通知接收端即将开始传输新字符。
  • 数据位(Data bits):紧随起始位的 5~9 位(常用 8 位),表示实际传输的数据内容。
  • 奇偶校验位(Parity bit,可选):用于检测数据在传输过程中是否出错。
  • 停止位(Stop bit(s),逻辑高电平 1):1 或 2 位高电平,表示本字符传输结束。
图片来源:网络

上图展示了一个 UART 帧的实际波形:包含 1 个起始位、8 个数据位(D1–D8)和 2 个停止位,共 11 位。

数据位数量、校验位设置、奇偶校验类型以及波特率等参数,需通信双方事先约定一致。

“停止位”本质上是一个最小持续高电平周期,通常为 1~2 位时间。发送端的停止周期可以更长,接收端只需满足最小要求。每帧结束后,接收端会等待下一个起始位,从而实现异步同步。

由于起始位为低电平、停止位为高电平,因此每个字符之间至少有两次电平跳变,便于接收端识别帧边界。

如果线路持续保持低电平超过一个字符周期(发送或接收一个字符的时间),UART 会检测为 Break 条件(断线状态)。

3. 实验

必备开发软件:STM32CubeIDE、STM32CubeMX、Tera Term
实验目标:掌握 UART 基本操作
硬件需求:STM32 开发板(示例型号:STM32F746G-DISCO)

实验步骤

  1. CubeMX 工程配置
    打开 STM32CubeMX,选择开发板型号,创建新工程。

  2. UART 引脚与参数配置

    • 选择一个 UART 控制器(如 USART1),模式设为异步模式( Asynchronous),波特率保持默认值 115200。 
    • 添加DMA配置 
    • 启用 NVIC 中断 
  3. 生成代码并导入 IDE
    生成代码后,在 STM32CubeIDE 中打开工程。


3.1 轮询方式(Polling)

最简单的方式,通过阻塞方式发送和接收数据。

  • 在 main 函数的 while(1) 循环中添加如下代码:
char msg[] = "Hello UART\r\n";
HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);

uint8_t rxData;
HAL_UART_Receive(&huart1, &rxData, 1, HAL_MAX_DELAY); // 接收 1 字节
  • 连接开发板,下载程序。
  • 打开 Tera Term,建立串口连接,并通过“设置->串口”菜单设置波特率为 115200。。  
  • 运行后,串口会输出 "Hello UART",输入任意字符会继续输出。

3.2 中断方式(Interrupt)

适用于数据量较小、实时性要求高的场景。

  • 删除轮询方式相关代码。
  • 声明全局变量 rxData,并实现回调函数:
uint8_t rxData;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)
    {
        HAL_UART_Transmit(&huart1, &rxData, 1, HAL_MAX_DELAY); // 回显
        HAL_UART_Receive_IT(&huart1, &rxData, 1); // 重新启动接收
    }
}
  • 在 main 函数中UART初始化后添加:
HAL_UART_Receive_IT(&huart1, &rxData, 1); // 启用中断接收
  • 下载程序,打开 Tera Term,程序运行时输入字符可实现回显。

3.3 DMA 方式

适合大数据量传输,减少 CPU 占用。

  • 删除中断方式相关代码。
  • 在 while(1) 循环前添加:
uint8_t txBuffer[100] = "UART DMA Example\r\n";
HAL_UART_Transmit_DMA(&huart1, txBuffer, strlen((char*)txBuffer));
  • 下载程序,打开 Tera Term,程序运行时可看到串口输出 "UART DMA Example”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值