1. 课程导论:SPI通信协议基础、DMA传输原理、轮询模式与中断模式对比

1.1 SPI通信协议基础

SPI(Serial Peripheral Interface,串行外设接口)是一种由Motorola公司推出的全双工、同步、高速串行通信总线。在嵌入式系统中,SPI常用于连接MCU与传感器、ADC/DAC、LCD显示屏、Flash存储器等外设。

1.1.1 物理层与信号线

SPI总线采用主从(Master-Slave)架构,通常由4根信号线组成:

信号线 全称 方向 功能描述
SCLK Serial Clock Master → Slave 由主设备产生的同步时钟信号,决定数据传输速率
MOSI Master Out Slave In Master → Slave 主设备输出数据线,从设备接收数据
MISO Master In Slave Out Slave → Master 从设备输出数据线,主设备接收数据
CS/SS Chip Select / Slave Select Master → Slave 片选信号,低电平有效,用于选中目标从设备

1.1.2 工作模式与时钟极性/相位

SPI协议通过时钟极性(CPOL)和时钟相位(CPHA)的组合定义了4种工作模式,决定了数据采样和输出的时钟边沿:

模式 CPOL CPHA 空闲时钟电平 数据采样边沿
Mode 0 0 0 低电平 第一个跳变沿(上升沿)
Mode 1 0 1 低电平 第二个跳变沿(下降沿)
Mode 2 1 0 高电平 第一个跳变沿(下降沿)
Mode 3 1 1 高电平 第二个跳变沿(上升沿)
开发提示: 在配置SPI外设时,必须确保主设备和从设备的工作模式一致。多数SPI Flash和传感器默认使用Mode 0或Mode 3,建议优先查阅外设数据手册确认。

1.1.3 SPI数据传输流程

SPI的每次数据传输本质上是主从设备内部移位寄存器的循环交换过程。以发送1字节数据为例:

  1. 拉低CS:主设备将片选信号置为低电平,激活目标从设备。
  2. 时钟驱动:主设备在SCLK线上产生8个时钟脉冲。
  3. 数据移位:每个时钟周期,主设备通过MOSI线移出1位数据,同时通过MISO线移入1位数据。
  4. 交换完成:8个时钟周期后,主设备的发送寄存器内容已移入从设备,从设备的发送寄存器内容已移入主设备。
  5. 拉高CS:传输结束,主设备将CS置为高电平,释放从设备。
SPI通信时序与数据交换示意图 SPI 全双工数据交换原理(主从移位寄存器) 主设备 (Master) 移位寄存器 [ 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 ] 发送数据: 0xA6 从设备 (Slave) 移位寄存器 [ 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 ] 发送数据: 0x65 MOSI MISO SCLK (时钟由主设备驱动) CS (片选): 低电平有效,传输期间保持低电平 每个SCLK时钟周期完成1位数据的交换,8个时钟周期完成1字节的全双工传输

1.2 DMA传输原理

DMA(Direct Memory Access,直接存储器访问)是一种允许外设与存储器之间直接传输数据而无需CPU干预的硬件机制。在SPI通信中引入DMA,可以显著降低CPU负载,提升系统吞吐量。

1.2.1 DMA的核心工作流程

DMA传输由DMA控制器(DMAC)管理,其基本工作流程如下:

  1. CPU配置DMA:设置源地址、目标地址、传输长度、传输宽度、触发源等参数。
  2. 外设触发:当SPI外设的接收数据寄存器非空(RXNE)或发送数据寄存器空(TXE)时,向DMA控制器发出请求。
  3. DMA接管总线:DMA控制器通过总线仲裁获得系统总线控制权,执行一次数据传输。
  4. 传输完成:DMA将数据从源地址搬运到目标地址,传输计数器递减。
  5. 中断通知:当传输计数器减至0时,DMA控制器可产生传输完成中断,通知CPU。

1.2.2 DMA传输的关键参数

参数 说明 典型配置
源地址 数据来源的起始地址 SPI_DR(数据寄存器)或内存缓冲区
目标地址 数据存放的目标起始地址 内存缓冲区或SPI_DR
传输宽度 每次传输的数据位宽 8位、16位或32位
传输长度 总共需要传输的数据单元个数 1 ~ 65535(取决于DMA控制器)
地址增量模式 每次传输后地址是否自动递增 外设地址固定,内存地址递增
循环模式 传输完成后是否自动重新开始 常用于连续数据流场景
DMA传输架构与SPI协同工作图 DMA 控制器与 SPI 外设协同传输架构 CPU 配置DMA后休眠 不参与数据传输 DMA 控制器 总线仲裁 数据搬运 SPI 外设 TXE / RXNE 请求 数据寄存器 系统内存 发送缓冲区 接收缓冲区 配置参数 响应请求 DMA请求 读写内存 优势:CPU只需初始化DMA配置,后续数据传输由DMA硬件自动完成,CPU可执行其他任务 适用于大数据块传输,如SPI Flash读写、LCD刷屏、ADC数据采集等场景

1.3 轮询模式与中断模式对比

在SPI驱动开发中,轮询模式和中断模式是两种最基本的CPU与外设交互方式。理解它们的差异,是选择合适驱动架构的前提。

1.3.1 轮询模式(Polling Mode)

轮询模式是指CPU通过循环检查外设状态寄存器的标志位,来判断数据是否准备好发送或接收。以SPI发送为例:

// SPI轮询模式发送1字节(伪代码)
void SPI_Polling_Send(uint8_t data) {
    // 等待发送缓冲区空(TXE标志位)
    while (!(SPI->SR & SPI_SR_TXE));
    // 写入数据寄存器
    SPI->DR = data;
    // 等待传输完成(BSY标志位清除)
    while (SPI->SR & SPI_SR_BSY);
}

1.3.2 中断模式(Interrupt Mode)

中断模式是指当外设状态满足条件时(如接收数据寄存器非空),外设向CPU发送中断请求,CPU暂停当前任务,执行中断服务函数(ISR)处理数据。

// SPI中断模式接收1字节(伪代码)
void SPI_IRQHandler(void) {
    if (SPI->SR & SPI_SR_RXNE) {
        // 读取数据寄存器,清除RXNE标志
        uint8_t data = SPI->DR;
        // 将数据存入接收缓冲区
        rx_buffer[rx_index++] = data;
    }
}

1.3.3 三种模式综合对比

对比维度 轮询模式 中断模式 DMA模式(本课程重点)
CPU占用率 高(持续占用CPU等待) 中(仅ISR执行时占用) 低(仅初始化配置)
实时响应 差(受轮询周期影响) 好(硬件触发立即响应) 好(硬件自动搬运)
实现复杂度 低(简单循环检查) 中(需配置中断向量、优先级) 高(需配置DMA通道、流、请求映射)
适用数据量 小(1~10字节) 中(10~100字节) 大(100字节以上)
代码可读性 高(线性执行) 中(主循环+ISR分离) 中(配置+回调分离)
典型场景 GPIO模拟SPI、调试阶段 按键响应、小数据量通信 Flash读写、LCD刷屏、音频流
课程定位说明: 本课程选择“轮询模式实现SPI通信DMA传输配置”作为切入点,原因有二:第一,轮询模式代码结构清晰,便于初学者理解DMA配置流程;第二,在实际工程中,轮询+DMA的组合常用于“单次大数据块传输”场景,既能保证传输完整性,又能降低CPU负载。后续章节将逐步拆解这一组合的完整实现。

1.3.4 模式选择决策树

在实际项目开发中,可根据以下条件快速选择SPI驱动模式:

  • 数据量 < 10字节 → 轮询模式(简单高效,无需中断开销)
  • 数据量 10~100字节,且CPU有其他任务 → 中断模式(平衡响应与负载)
  • 数据量 > 100字节,或需要连续传输 → DMA模式(解放CPU,提升吞吐量)
  • 系统对实时性要求极高 → 中断模式或DMA模式(避免轮询阻塞)
  • 调试阶段或功能验证 → 轮询模式(便于单步跟踪和问题定位)
常见误区: 初学者容易认为DMA模式一定比中断模式好。实际上,DMA的初始化配置和通道占用本身也有开销。对于小数据量传输,中断模式的整体效率可能更高。选择驱动模式时,应结合具体硬件资源和应用场景综合评估,而非盲目追求“高级”特性。