引言

在嵌入式系统开发中,串口通信是最基础且重要的通信方式之一。从简单的调试信息输出到复杂的数据传输,串口都扮演着不可或缺的角色。本教程将从零开始,深入讲解STM32的串口通信,涵盖从基础的文件传输到高效的DMA数据传输,帮助初学者快速掌握串口通信的核心技术。

一、串口通信前言

1.1 串口通信类别

串口通信根据不同的分类标准可以分为多种类型,理解这些分类有助于我们选择合适的通信方式。

按数据传输方式分类

同步串行通信

  • 需要时钟信号同步
  • 发送和接收方使用同一时钟
  • 数据传输效率高
  • 典型代表:SPI、I2C

异步串行通信

  • 不需要时钟信号
  • 依靠起始位和停止位同步
  • 硬件要求简单
  • 典型代表:UART
特性 同步通信 异步通信
时钟信号 需要 不需要
传输效率 中等
硬件复杂度 较高 较低
传输距离 较短 较长
成本 较高 较低
典型应用 高速板内通信 设备间通信

STM32F103系列提供5路串口,包含3个 USART 和2个 UART 。

串口的引脚如下图所示:
在这里插入图片描述

按数据传输方向分类

单工通信

  • 数据只能单向传输
  • 一方固定为发送端,另一方为接收端
  • 如:广播、遥控器

半双工通信

  • 数据可以双向传输,但不能同时
  • 需要方向切换
  • 如:对讲机、RS-485

全双工通信

  • 数据可以同时双向传输
  • 发送和接收通道独立
  • 如:电话、UART

在这里插入图片描述

按电气标准分类

TTL串口

  • 电压:0-5V/0-3.3V
  • 传输距离:< 2米
  • 应用:板内通信

RS-232

  • 电压:±15V
  • 传输距离:≤ 15米
  • 应用:设备间通信

RS-485

  • 电压:±7V
  • 传输距离:≤ 1200米
  • 应用:工业现场总线

各类串口通信对比表:

特性 TTL UART RS-232 RS-485 USB转串口
电平标准 0-3.3V/5V ±15V ±7V 3.3V/5V
传输距离 0.5-2米 ≤15米 ≤1200米 5米(USB限制)
通信方式 全双工 全双工 半双工/全双工 全双工
节点数量 点对点 点对点 多点(32-256) 点对点
抗干扰 中等 中等
成本 中等 中等
应用场景 开发板调试 工控设备 工业总线 PC连接
特殊类型串口通信

软件串口(Software Serial)

  • 通过GPIO模拟串口时序
  • 灵活性高,但占用CPU资源
  • 用于引脚不足的情况

硬件串口(Hardware UART)

  • 专用硬件实现
  • 不占用CPU资源
  • 性能稳定可靠

虚拟串口(Virtual COM Port)

  • 通过USB模拟串口
  • 即插即用,使用方便
  • 如:CH340、CP2102等

1.2 串口协议

串口通信(Serial Communication)是一种异步串行通信方式,数据按位顺序传输。其核心特点是通信双方不需要共享时钟信号,而是通过预定义的波特率来实现同步。

串口数据帧格式:

每个数据帧包含以下几个部分:

  • 起始位:1位低电平,标志数据帧的开始
  • 数据位:5-9位有效数据,通常为8位
  • 校验位:1位,用于错误检测(可选)
  • 停止位:1-2位高电平,标志数据帧的结束
┌─────┬───────────┬────────┬─────────┐
│起始位│  数据位   │ 校验位 │ 停止位  │
│ (1b) │ (5-9b)   │ (0-1b)│ (1-2b)  │
└─────┴───────────┴────────┴─────────┘

串口通信参数配置表:

参数 说明 常见配置 影响因素
波特率 数据传输速率(bps) 9600, 19200, 115200等 传输速度、通信距离
数据位 每个字符的数据位数 5, 6, 7, 8位 数据精度
停止位 帧结束标志位数 1, 1.5, 2位 帧间隔
校验位 错误检测机制 无、奇校验、偶校验 数据可靠性
流控制 数据传输控制 无、RTS/CTS、XON/XOFF 大数据量传输

波特率计算公式:

波特率 = 时钟频率 / (16 × USARTDIV)
其中USARTDIV是一个浮点数,整数部分写入BRR[15:4],小数部分写入BRR[3:0]

1.3 RS-232标准详解

RS-232是由电子工业联盟(EIA)制定的串行数据通信接口标准,广泛应用于计算机和外部设备的连接。

RS-232主要特性:

  • 电气特性:采用负逻辑,+3V至+15V表示逻辑0,-3V至-15V表示逻辑1
  • 机械特性:DB9或DB25连接器
  • 传输距离:最大15米(在19200bps时)
  • 连接方式:点对点全双工通信

RS-232 DB9接口定义表:

引脚 名称 方向 说明
1 DCD 输入 数据载波检测
2 RXD 输入 接收数据
3 TXD 输出 发送数据
4 DTR 输出 数据终端就绪
5 GND - 信号地
6 DSR 输入 数据设备就绪
7 RTS 输出 请求发送
8 CTS 输入 清除发送
9 RI 输入 振铃指示

RS-232信号电平标准表:

信号状态 电压范围 逻辑值
逻辑1 (MARK) -3V ~ -15V 1
逻辑0 (SPACE) +3V ~ +15V 0
过渡区 -3V ~ +3V 不确定

1.4 TTL电平 vs RS232电平

在嵌入式系统中,我们经常需要在TTL电平和RS232电平之间进行转换,理解两者的差异至关重要。

TTL电平特性:

  • 逻辑1:+5V或+3.3V(取决于供电电压)
  • 逻辑0:0V
  • 适用于板内或短距离通信

电平对比分析表:

特性 TTL电平 RS232电平 影响分析
逻辑1电压 +5V/+3.3V -3V ~ -15V 电平不兼容,需要转换
逻辑0电压 0V +3V ~ +15V 电平不兼容,需要转换
电压摆幅 0-5V/0-3.3V ±15V RS232抗干扰能力更强
传输距离 0.5-2米 最长15米 RS232适合较长距离
抗干扰能力 较弱 较强 RS232适合工业环境
成本 较高 TTL更适合成本敏感应用
应用场景 板内通信 设备间通信 根据需求选择

电平转换原理图:
在这里插入图片描述

1.5 CH340模块工作原理

CH340是国内厂商沁恒微电子推出的USB转串口芯片,因其性价比高而广泛应用。

CH340功能框图:
在这里插入图片描述

CH340工作流程:

  1. USB数据包接收和解包
  2. 协议解析和数据提取
  3. 电平转换和串行化
  4. UART信号输出

CH340模块参数表:

参数 规格 说明
接口类型 USB 2.0 全速设备,12Mbps
串口支持 UART 支持常用串口模式
电压电平 3.3V/5V TTL 兼容大多数MCU
波特率范围 50bps ~ 2Mbps 覆盖常用需求
数据位宽 5、6、7、8位 可配置
校验位 无、奇、偶校验 可配置
封装形式 SOP-16 易于焊接
驱动支持 Windows/Linux/macOS 跨平台兼容

CH340与STM32连接示例:

CH340模块      STM32F103
TXD  ──────→  PA10(RX)
RXD  ←──────  PA9(TX)
GND  ───────  GND
VCC  ───────  3.3V/5V

二、实战文件传输

本次实验将两台笔记本电脑,借助 usb转ttl 模块和杜邦线,建立起串口连接。然后用串口助手等工具软件(带文件传输功能)将一台笔记本上的一个大文件(图片、视频和压缩包软件)传输到另外一台电脑,预算文件大小、波特率和传输时间三者之间的关系,并对比实际传输时间。

2.1 实验环境搭建

首先打开串口调试器
发送段设置如下:这里选择了一个图片进行发送
在这里插入图片描述

2.2 硬件连接指南

两台笔记本电脑,两个USB转TTL模块,四条杜邦线,两个串口线连接这两台电脑。连线方式:3V3-3V3,GND-GND,TXD-RXD,RXD-TXD。
在这里插入图片描述

2.3 文件传输实验

分别串口调试助手的串口打开,发送方点击发送,接收方点击接收。

VID_20251018_201309


最后保存数据到文件夹,右击打开方式选择画图,即可打开接收图片
在这里插入图片描述

2.3.1 波特率与传输时间关系

理论基础:

串口传输每个字节需要10个位(包括起始位、数据位和停止位),由此得出:

传输时间计算公式:
传输时间(秒)= (文件字节数 × 10)/ 波特率

有效传输速率:
实际速率(KB/秒)= 波特率 / (10 × 1024)

不同情况下的理论传输时间:

文件规格 波特率 预计时间 理论速率
2MB文件 9600 34.8分钟 0.94 KB/秒
2MB文件 115200 约3分钟 11.25 KB/秒
2MB文件 460800 约44秒 45 KB/秒
2MB文件 921600 约22秒 90 KB/秒
50MB文件 115200 约72分钟 11.25 KB/秒
50MB文件 921600 约9分钟 90 KB/秒
2.3.2 实际性能测试对比

测试条件:

  • 操作系统:Windows 11
  • 测试软件:串口调试助手
  • 测试文件:2MB JPG图片
  • 测试方法:每个波特率测试3次取平均值

实测数据记录:

波特率 理论时间 实测时间 实际速率 稳定性
9600 34.8分钟 36.2分钟 0.90 KB/s 稳定
115200 2.9分钟 3.1分钟 10.5 KB/秒 稳定
460800 43.5秒 46.8秒 41.7 KB/秒 稳定
921600 21.8秒 24.1秒 81.3 KB/秒 较稳定

性能对比分析:

通过测试发现,实际传输时间普遍比理论计算值长约5-10%,主要原因包括:

  1. 文件传输协议的控制信息开销
  2. 串口软件的数据处理时间
  3. 操作系统调度延迟
  4. 错误重传机制的影响

随着波特率提高,实际速率与理论速率的差距有所增大,在最高波特率时差距达到20%左右。

2.4 地线重要性分析

地线的关键作用

地线在串口通信中具有重要作用:

  • 建立统一的电压参考基准
  • 形成完整的电流回路
  • 抑制信号干扰
  • 保障设备安全
地线连接实验

测试设置:

  • 波特率:115200
  • 文件大小:1MB
  • 对比有地线和无地线的情况

测试结果:

接地状态 传输效果 错误情况 观察现象
地线完好 传输成功 无错误 文件完整接收
未接地线 传输失败 100%错误 无法建立通信
地线接触不良 传输不稳定 15-40%错误 数据包丢失
接地问题分析

在串口通信系统中,接地质量直接影响通信的稳定性和可靠性。接地问题通常表现为三种典型情况,每种情况都有其独特的现象和深层次原因。

完全无地线连接是最严重的接地故障。当两个通信设备之间没有建立地线连接时,系统实际上缺少一个共同的电压参考基准。这就像两个人用不同的语言标准进行对话,完全无法理解对方的意思。在电气特性上,发送端和接收端的逻辑电平"0"和"1"没有统一的判断标准,导致信号无法被正确解析。在实际操作中,表现为通信完全中断,设备间无法建立任何有效连接。解决这一问题的关键在于建立可靠的地线通路,使用万用表检查GND线是否形成完整回路是最直接的诊断方法。

地线接触不良是较为隐蔽但常见的问题。这种情况通常由于接口氧化、连接器松动或导线断裂导致接触电阻增大。当接触电阻存在时,信号电流流经地线会产生额外的电压降,使得参考电平发生漂移。这种漂移是随机的,导致接收端对逻辑电平的判断时对时错。具体表现为数据传输中出现随机性错误,某些数据包能正常接收,而另一些则完全错误。特别是在有外部干扰的环境中,这种问题会更加明显。确保接地可靠需要从物理连接入手,包括清洁连接器、紧固接口,以及在要求高的场合采用焊接代替插接。

地线质量问题往往被初学者忽视。使用过细的导线、过长的走线或劣质材料都会增加接地回路的阻抗。在高频信号传输时,集肤效应会使电流集中在导线表面,进一步增加有效电阻。当地线阻抗过大时,高频噪声无法有效泄放,会在系统中积累,降低信号的信噪比。这不会立即导致通信中断,但会显著增加误码率,迫使系统频繁进行数据重传,从而降低有效传输速率。改善地线质量需要选择截面积足够的多股铜线,保持地线长度最短,并避免与强干扰源平行走线。

这些接地问题在实际工程中往往相互交织,需要系统性地分析和解决。良好的接地不仅是一个连接点,更是一个低阻抗的回路系统。在复杂的电磁环境中,合理的接地设计是保证串口通信质量的重要基础,值得在工程实施中给予充分重视。

三、串口通信配置

以下工程建立省略了相关基本配置操作,如有需要会将文章放入参考资料里

3.1 正常串口通信开发

3.1.1 操作实现

开启USART1异步通信如下:
在这里插入图片描述
设置波特率等如下(此处为系统默认)
在这里插入图片描述
这样就可以生成工程,打开工程,我们需要使用下面一俩行函数

HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)

功能:串口发送指定长度的数据。如果超时没发送完成,则不再发送,返回超时标志(HAL_TIMEOUT)。

参数:

  • *UART_HandleTypeDef huart:UART结构体( huart1)
  • *pData:需要发送的数据
  • Size:发送的字节数
  • Timeout:最大发送时间,发送数据超过该时间退出发送

代码实现如下:

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_UART_Transmit(&huart1, (uint8_t *)"hello windows!\r\n", 16 , 0xffff);
		 HAL_Delay(1000);  //延时1s
  /* USER CODE END 3 */
}

轮询代码实现需要调用 HAL_UART_Receive()函数如下:

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    // 轮询方式接收一个字节
    if (HAL_UART_Receive(&huart1, rx_data, 1, 10) == HAL_OK) // 10ms超时,避免长时间阻塞
    {
      // 处理接收到的命令
      switch(rx_data[0])
      {
        case '#': // 暂停发送
            send_enabled = 0;
          break;
        case '*': // 继续发送
            send_enabled = 1;
          break;
      }
    }
    // 定时发送"hello windows!"
    if(send_enabled)
    {
				HAL_UART_Transmit(&huart1, (uint8_t *)"hello windows!\r\n", 16 , 0xffff);
				HAL_Delay(1000);  //延时1s
		}
    }  
  /* USER CODE END 3 */
}

3.1.2 实现展示

一秒发送hallow windows!展示如下:

屏幕录制 2025-10-19 014012

轮询停止发送展示如下:

屏幕录制 2025-10-19 014129

3.1.3 仿真分析

点击魔法棒,设置debug。勾选Use Simulator 使用软件调试。更改 Dialog DLL 以及 Parameter
在这里插入图片描述
点击方框内,开始调试
在这里插入图片描述

打开 logic analyzer窗口,进行波形分析
在这里插入图片描述

点击 Setup 选项
在这里插入图片描述

点击方框 新建 。输入 USART1_SR
类型设置为比特流,并可以选择设置波形颜色。设置完就可以点击下方 Close 退出了
在这里插入图片描述

点击方框内 run开始
在这里插入图片描述

在这里插入图片描述
可以发现延时准确

  • 计算实际传输的比特数

要发送的字符串是 “hallow windows!”。

数一下字符: h,a,l,l,o,w,w,i,n,d,o,w,s,!` 一共 15个字符。

在串口通信中,每个字符(字节)的传输包含:1个起始位、8个数据位、1个停止位,总共 10 个比特。

所以,传输这15个字符所需的总比特数为:总比特数 = 15 字符 × 10 比特/字符 = 150 比特

  • 计算实际比特率(波特率)

已知:

传输时间 = 1.442278 ms = 0.001442278 秒

传输的总比特数 = 150 比特

波特率 (bps) = 总比特数 / 传输时间
波特率 = 150 bits / 0.001442278 s ≈ 104,001 bps

  • 结论与分析

计算出的波特率约为 104,000,这与标准的 115,200 波特率最为接近。两者之间存在约10%的误差,这是完全合理的,主要原因如下:系统开销,计算的是纯数据传输时间,但实际测量可能包含了软件处理、操作系统调度、串口助手内部缓冲等微小延迟;时钟精度,USB转TTL模块或电脑主板时钟可能存在微小偏差,导致实际波特率与设定值有细微差别;测量误差,时间测量工具(很可能是软件计时)本身存在一定的精度限制。

3.2 基于中断开发

3.2.1 中断机制原理

中断是嵌入式系统中至关重要的机制,它允许处理器在正常程序执行过程中响应外部或内部事件。理解中断原理对于开发高效的串口通信程序至关重要。

中断基本概念

中断可以理解为一种"硬件级别的函数调用"。当特定事件发生时,处理器暂停当前正在执行的程序,转去执行相应的中断服务程序(ISR),执行完毕后再返回到原程序继续执行。

中断工作流程

  1. 中断请求:外设(如串口)检测到事件并发出中断请求信号
  2. 中断响应:处理器完成当前指令后,响应中断请求
  3. 现场保护:自动保存关键寄存器值到堆栈
  4. 中断服务:执行对应的中断服务程序
  5. 现场恢复:恢复之前保存的寄存器值
  6. 中断返回:返回到被中断的程序继续执行

中断相关术语表

术语 英文 说明
中断源 Interrupt Source 能够产生中断请求的信号源
中断向量 Interrupt Vector 中断服务程序的入口地址
中断优先级 Interrupt Priority 决定多个中断同时发生时的响应顺序
中断屏蔽 Interrupt Mask 暂时禁止某些中断响应的机制
中断嵌套 Interrupt Nesting 高优先级中断打断低优先级中断服务的过程
现场保护 Context Saving 保存被中断程序的执行状态

STM32中断系统架构

STM32的中断系统基于ARM Cortex-M内核的NVIC(嵌套向量中断控制器),具有高度可配置性。

中断优先级分组

STM32支持中断优先级分组,将4位优先级分为抢占优先级和子优先级:

优先级分组 抢占优先级位数 子优先级位数 说明
分组0 0位 4位 无抢占优先级,只有16个子优先级
分组1 1位 3位 2级抢占优先级,8个子优先级
分组2 2位 2位 4级抢占优先级,4个子优先级
分组3 3位 1位 8级抢占优先级,2个子优先级
分组4 4位 0位 16级抢占优先级,无子优先级

中断响应时序

中断响应时间包括多个阶段:

  1. 检测延迟:从中断发生到处理器检测到的时间
  2. 处理延迟:处理器完成当前指令的时间
  3. 入口延迟:保存现场和跳转到ISR的时间
  4. ISR执行:中断服务程序实际执行时间
  5. 退出延迟:恢复现场和返回的时间

典型中断响应时间表

处理器状态 最小响应周期 最大响应周期 影响因素
空闲状态 12周期 12周期 固定延迟
执行简单指令 12+周期 12+当前指令周期 当前指令长度
执行长指令 12+周期 12+多个周期 如除法指令
中断禁用 无限等待 无限等待 中断使能状态
低优先级中断中 嵌套延迟 等待当前ISR完成 优先级设置

中断源分类

STM32中的中断源可以分为以下几类:

内核中断

  • 系统异常:复位、硬故障、存储器管理故障等
  • 外部中断:通过EXTI控制器连接的外部信号

外设中断

  • 定时器中断:更新、捕获、比较等事件
  • 串口中断:发送完成、接收数据、错误等
  • 其他外设:ADC、DMA、I2C、SPI等

中断使能与控制流程

在这里插入图片描述

中断标志管理

每个中断源都有相应的标志位来指示中断状态:

  • 挂起标志:中断已发生但尚未处理
  • 活跃标志:中断正在被处理
  • 使能标志:允许该中断触发

中断处理最佳实践

  1. ISR设计原则

    • 执行时间尽可能短
    • 避免调用复杂函数
    • 及时清除中断标志
    • 注意共享数据保护
  2. 中断优先级安排

    • 实时性要求高的中断设置高优先级
    • 相关中断设置相同的抢占优先级
    • 避免中断饥饿现象
  3. 中断调试技巧

    • 使用中断计数器统计中断频率
    • 测量ISR执行时间
    • 检查中断响应延迟

常见中断问题与解决方案

问题现象 可能原因 解决方法
中断不触发 中断未使能、优先级设置错误 检查使能位和优先级配置
中断频繁触发 标志位未清除、硬件故障 确保在ISR中清除标志位
系统卡死 中断嵌套过深、堆栈溢出 优化优先级、增加堆栈大小
数据竞争 共享数据未保护 使用临界区保护共享数据

通过深入理解中断机制原理,开发者可以更好地设计和优化串口通信程序,确保系统的实时性和可靠性。中断机制的正确使用是嵌入式系统开发中的关键技能之一。

3.2.2 操作实现

在上头工程的基础上新增如下:
在这里插入图片描述
然后需要认识如下中断函数:

HAL_UART_Receive_IT():串口中断模式接收
HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //串口接收中断回调函数

在文件main.c 里 main函数外部 添加以下代码
在这里插入图片描述
主函数添加如下代码

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	HAL_UART_Receive_IT(&huart1, (uint8_t *)RxBuffer,1); 
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		if(RxFlag)
		{
				HAL_UART_Transmit(&huart1, (uint8_t *)"hello windows!\r\n", 16 , 0xffff);
				HAL_Delay(1000);  //延时1s
		}

  }
  /* USER CODE END 3 */
}

主函数后调用中断函数如下

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)
	{
		    if (HAL_UART_Receive(&huart1, RxBuffer, 1, 10) == HAL_OK) // 10ms超时,避免长时间阻塞
    {
      // 处理接收到的命令
      switch(RxBuffer[0])
      {
        case '#': // 暂停发送
            RxFlag = 0;
          break;
        case '*': // 继续发送
            RxFlag = 1;
          break;
      }
    }

		
	}
	
}
/* USER CODE END 4 */

实现展示和上面轮询效果展示一致。

3.3 基于DMA通信开发

3.3.1 DMA工作原理

DMA(直接存储器访问)是嵌入式系统中用于提高数据传输效率的重要技术。它允许外设与内存之间或内存与内存之间直接传输数据,无需CPU的介入,从而解放CPU资源,提高系统整体性能。

DMA基本概念

DMA可以理解为系统中的"数据传输专员",专门负责大规模数据的搬运工作。当需要进行大量数据传输时,CPU只需初始化DMA控制器,之后DMA控制器会自动完成剩余的数据传输任务,期间CPU可以继续执行其他计算任务。

DMA系统架构

在STM32中,DMA控制器是一个独立的外设,通过系统总线与内存和外设连接:
在这里插入图片描述

DMA传输要素

每个DMA传输都包含以下基本要素:

要素 说明 示例
源地址 数据传输的起始位置 USART1->RDR
目标地址 数据传输的目的位置 rx_buffer
传输数量 需要传输的数据单元数量 1024
数据宽度 每次传输的数据位宽 8位、16位、32位
传输模式 数据传输的工作方式 正常模式、循环模式

DMA传输过程详解

  1. 初始化阶段

    • CPU配置DMA控制器的相关寄存器
    • 设置源地址、目标地址、传输数量等参数
    • 使能DMA传输
  2. 传输阶段

    • DMA控制器接管总线控制权
    • 按配置参数自动进行数据传输
    • 每次传输后更新地址和计数器
  3. 完成阶段

    • 传输计数器归零
    • 产生传输完成中断
    • 释放总线控制权

DMA工作模式对比

工作模式 触发方式 传输特点 适用场景
单次传输 软件触发 传输指定数量后停止 单次数据块传输
循环传输 连续触发 传输完成后自动重新开始 连续数据流
外设触发 外设事件触发 由外设信号启动传输 实时数据采集

DMA传输类型

STM32支持多种DMA传输类型:

外设到存储器

  • 源地址:外设数据寄存器
  • 目标地址:内存缓冲区
  • 典型应用:串口数据接收

存储器到外设

  • 源地址:内存缓冲区
  • 目标地址:外设数据寄存器
  • 典型应用:串口数据发送

存储器到存储器

  • 源地址:内存区域A
  • 目标地址:内存区域B
  • 典型应用:数据块复制

DMA通道与流

在STM32中,DMA控制器采用"流"和"通道"的概念:

概念 说明 特点
流(Stream) DMA控制器的数据传输通路 每个流可独立配置
通道(Channel) 流与外设的对应关系 决定数据流向
仲裁器 管理多个流的优先级 解决流间竞争

DMA流优先级机制

当多个流同时请求DMA传输时,仲裁器根据优先级决定服务顺序:

优先级设置 仲裁方式 特点
非常高 固定最高优先级 实时性要求最高的传输
优先服务 重要数据传输
轮询服务 普通数据传输
最后服务 后台数据传输

DMA传输配置参数

数据宽度配置

数据宽度 适用场景 传输效率 对齐要求
字节(8位) 串口通信 较低 无特殊要求
半字(16位) 音频数据 中等 2字节对齐
字(32位) 图像处理 较高 4字节对齐

地址增量模式

增量模式 源地址行为 目标地址行为 适用场景
固定地址 不递增 不递增 FIFO寄存器
递增地址 每次递增 每次递增 数组传输
混合模式 固定/递增 递增/固定 特殊需求

DMA中断类型

DMA控制器提供多种中断源,用于通知传输状态:

中断类型 触发条件 应用场景
传输完成 所有数据传输完成 处理完整数据块
半传输 传输完成一半数据 双缓冲技术
传输错误 总线错误或地址错误 错误处理
FIFO错误 FIFO上溢或下溢 流控制异常

DMA性能优化技术

双缓冲技术
使用两个缓冲区交替工作,实现数据传输与处理的并行:

缓冲区A[接收中] ←── DMA
缓冲区B[处理中] ←── CPU

突发传输
通过单次请求传输多个数据,减少总线占用时间:

突发大小 传输次数 总线效率 延迟
单次传输 1次/请求 较低 较低
4字节突发 4次/请求 较高 中等
8字节突发 8次/请求 很高 较高

FIFO使用
DMA控制器内置FIFO缓冲区,用于平滑数据传输:

FIFO模式 工作方式 适用场景
禁用 直通模式 简单传输
使能 使用FIFO缓冲 大数据量传输
阈值控制 按阈值触发 流量控制

DMA传输时序分析

典型DMA传输时间计算公式:

总传输时间 = (数据量 × 数据宽度) / 总线频率 + 初始化开销 + 中断处理时间

DMA使用注意事项

  1. 内存对齐

    • 确保源地址和目标地址符合对齐要求
    • 错误对齐可能导致传输效率下降或硬件错误
  2. 缓存一致性

    • 在使用缓存时注意DMA传输的数据一致性
    • 必要时进行缓存维护操作
  3. 资源竞争

    • 避免多个主设备同时访问同一内存区域
    • 合理设置DMA流优先级
  4. 错误处理

    • 实现完善的DMA错误检测和恢复机制
    • 监控传输进度,防止传输停滞
3.3.2 操作实现

在中断工程基础上设置DMA,点击添加即可,如下:
在这里插入图片描述
调用下面函数

HAL_UART_Transmit_DMA():串口DMA模式发送

代码实现如下:

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		  HAL_UART_Transmit_DMA(&huart1, (uint8_t *)"hello windows! \r\n", 15 );
			HAL_Delay(1000);  //延时1s
  }

实现效果展示与上头效果一致。

3.4 三者对比

在STM32串口通信开发中,轮询、中断和DMA是三种主要的通信方式。理解它们的特点和适用场景,对于设计高效的嵌入式系统至关重要。

CPU资源占用对比

从CPU资源占用的角度来看,三种方式有着明显的差异:

方式 CPU占用程度 占用原因 资源利用率
轮询方式 CPU需要不断查询状态寄存器,在等待期间处于忙等待状态
中断方式 中等 CPU仅在数据到达或发送完成时被中断,大部分时间可执行其他任务
DMA方式 数据传输过程完全由DMA控制器完成,CPU只需初始化和处理完成中断

实现复杂度分析

在代码实现和维护方面,三种方式的难度各不相同:

方式 代码复杂度 调试难度 适合的开发者
轮询方式 简单 容易,逻辑直观 初学者
中断方式 中等 中等,需处理中断嵌套和资源竞争 有经验的开发者
DMA方式 复杂 困难,需要理解DMA控制器工作原理 资深开发者

性能表现对比

性能表现方面,三种方式在不同数据量下的表现差异明显:

数据量 轮询方式 中断方式 DMA方式
小数据包(<16字节) 响应慢 响应快 配置开销大
中等数据(16-64字节) 效率低 效率中等 效率开始显现
大数据块(>64字节) 不可行 效率较低 效率最高

实时性分析

实时性要求是选择通信方式的重要考量因素:

方式 响应时间 确定性 适用实时场景
轮询方式 不稳定,依赖查询频率 非实时系统
中断方式 快速,微秒级响应 中等实时要求
DMA方式 最快,硬件级响应 优秀 高实时要求

资源消耗对比

在系统资源消耗方面,三种方式的需求不同:

资源类型 轮询方式 中断方式 DMA方式
CPU时间 大量消耗 中等消耗 少量消耗
内存占用 很少 中等 需要DMA缓冲区
外设资源 仅需串口 需要串口+NVIC 需要串口+DMA控制器

适用场景总结

基于以上分析,三种方式的主要适用场景如下:

应用场景 推荐方式 理由
简单调试输出 轮询方式 实现简单,满足基本需求
中等数据量通信 中断方式 平衡性能和复杂度
高速数据流传输 DMA方式 最大化传输效率
多任务系统 中断或DMA 减少CPU占用
资源极度受限 轮询方式 节省系统资源

四、总结

通过本教程的完整学习,我们从串口通信的基础理论到实际应用进行了全面的探索。在理论基础部分,我们深入理解了串口通信的各种类型、协议格式、电平标准以及转换模块的工作原理,这些知识为后续的实践操作奠定了坚实的理论基础。在文件传输实验中,我们通过亲手搭建硬件环境、进行数据传输测试,不仅验证了波特率与传输时间的关系,更重要的是认识到了地线连接在通信质量中的关键作用,这些实践经验对于嵌入式开发来说非常宝贵。
在STM32的三种串口通信方式实践中,我们逐步掌握了轮询、中断和DMA的使用方法和适用场景。从简单的轮询发送,到能够及时响应的中断通信,再到高效解放CPU的DMA传输,每一种方式都有其独特的优势和应用价值。通过仿真分析和实际测试,我们不仅学会了如何配置和使用这些功能,更重要的是理解了在不同应用场景下如何选择合适的通信方式,这对于今后进行更复杂的嵌入式系统设计具有重要意义。

五、参考资料

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐