目录
SPI协议简介
极性与相位
SPI框图
单字节收发
发送数据流程
接收数据流程
ECSPI控制器
关键特性
时钟源
主机模式
等待状态
片选控制
单突发传输
多突发传输
相位控制
ECSPI Memory Map
ECSPI寄存器
ECSPIx_RXDATA
ECSPIx_TXDATA
编辑
ECSPIx_CONREG
ECSPIx_CONFIGREG
ECSPIx_STATREG
ECSPIx_PERIODREG
前言:
增强型可配置串行外设接口ECSPI(Enhanced Configurable Serial Peripheral Interface)是一个全双工、同步的四线制串行通信模块,ECSPI 包含一个 64×32 的接收缓冲区(RXFIFO) 和一个 64×32 的发送缓冲区(TXFIFO),64 是 FIFO 深度(可连续存储 64 个数据单元),32 是位宽(每个单元 32 位,即 4 字节),此时 RXFIFO/TXFIFO 最大可缓存256字节数据;
SPI协议简介
SPI(Serial Peripheral interface)支持全双工通信,时钟频率可达MHz级别;
SPI通过4个引脚与外部器件相连:
- MISO:主设备输入/从设备输出引脚,从模式下发送数据,主模式下接收数据;
- MOSI:主设备输出/从设备输入引脚,主模式下发送数据,从模式下接收数据;
- SCK: 串口时钟,作为主设备的输出,从设备的输入,主机负责生成同步时钟信号;
- NSS: 片选引脚,用来选择总线上的特定从机(Slave)进行通信;
极性与相位
时钟极性(CPOL)指串行时钟SCLK在 空闲状态(单次数据传输完成/无数据传输时)的电平;
- 低极性(CPOL=0):SCLK 在空闲时保持 低电平;
- 高极性(CPOL=1):SCLK 在空闲时保持 高电平;
时钟相位(CPHA)指 数据采样(读取)发生于 串行时钟SCLK的哪个边沿;
- CPHA=0:数据在 SCLK 的第一个边沿被采样,第二个边沿用于更新数据(主从机更新自身的移位寄存器);
- CPHA=1:数据在 SCLK 的第二个边沿被采样,第一个边沿用于更新数据;
SPI协议按照极性与相位可组合为四种模式,分别为模式0(Mode 0),模式1(Mode 0),模式2(Mode 2),模式3(Mode 3);
注意: SPI 是全双工通信,但是发送数据和采样数据必然发生在同一个时钟周期的不同边沿;
以模式 0 为例,
CPOL=0, CPHA=0
,核心逻辑如下:1. 主机侧行为(Master):
- 发送数据(MOSI 输出):在 SCLK 的 下降沿(第二边沿)完成移位输出(数据从主机移位寄存器 → MOSI 总线);
- 采样数据(MISO 输入):在 SCLK 的 上升沿(第一边沿)完成锁存采样(数据从 MISO 总线 → 主机移位寄存器);
2. 从机侧行为(Slave):
- 发送数据(MISO 输出):在 SCLK 的 上升沿(第一边沿)完成移位输出(数据从从机移位寄存器 → MISO 总线);
- 采样数据(MOSI 输入):在 SCLK 的 下降沿(第二边沿)完成锁存采样(数据从 MOSI 总线 → 从机移位寄存器);
SPI框图
移位寄存器(Shift Register): 串并转换器
- 发送侧:CPU 写入的字节并行加载到移位寄存器,然后通过 MOSI 逐位串行发送;
- 接收侧:从机通过 MISO 发来的串行位,逐位串行移入到移位寄存器,最终合并为并行字节,供 CPU 读取;
发送缓冲区(TX Buffer):
- 将发送缓冲区可设计为先进先出队列(TXFIFO),允许 CPU 提前写入多个待发送数据,SPI 自动按顺序发送,无需 CPU 逐字节判断发送缓冲区为空;
接收缓冲区(RX Buffer):
- 将接收缓冲区可设计为先进先出队列(RXFIFO),自动缓存多个接收数据,CPU 可批量读取,避免因 CPU 响应慢导致数据丢失;
波特率发生器:
- 可以配置分频系数,生成指定频率 SCLK 时钟;
单字节收发
假设主机向从机发送
0x55
(二进制01010101
),同时接收从机返回的0xAA
(二进制10101010
),假定
- CPOL=0,CPHA=0,模式 0,SCK 空闲低电平,上升沿发送 / 采样数据;
- 数据宽度为8位数据,比特位传输顺序为MSB(先传最高有效位);
发送数据流程
路径:
CPU → TXFIFO → 移位寄存器 → MOSI → 从机
Step 1:CPU 写入数据到 TXFIFO
CPU 通过地址和数据总线,将待发送的字节0x55
写入 发送缓冲区(TXFIFO),若 TXFIFO 支持多字节,可连续写入多个数据,SPI 会自动按顺序发送;Step 2:移位寄存器加载数据
主控制电路检测到 TXFIFO 有数据,触发移位寄存器从 TXFIFO 取出第一个字节0x55
,并行加载到移位寄存器中(移位寄存器内容:01010101
);Step 3:SCK 时钟驱动,逐位发送
波特率发生器根据设置的分频系数生成 SCK 时钟(假设分频后频率为f_SCK
),在 SCK 的上升沿,移位寄存器将0x55
从 最高比特位开始 通过 MOSI 引脚 逐位移出,发送到从机;
- 第 1 个上升沿:发送
0
(0x55
的第 7 位,MSB);- 第 2 个上升沿:发送
1
(0x55
的第 6 位);- …… 直到 8 个时钟后,
0x55
全部发送完成;Step 4:TXE 标志反馈发送缓冲区是否为空
当移位寄存器的 8 位全部发送后,TXFIFO 中若无新数据,状态寄存器 发送缓冲区空标志位置位,通知 CPU可以写入下一个字节;
接收数据流程
路径:
从机 → MISO → 移位寄存器 → RXFIFO → CPU
Step 1:从机数据输入 MISO
从机通过 MISO 引脚 发送数据0xAA
(二进制10101010
),在 SCK 的上升沿,主机的移位寄存器逐位捕获 MISO 的信号;Step 2:移位寄存器串并转换
每个 SCK 上升沿,移位寄存器将 MISO 的一位存入,持续 8 个时钟后,完整的字节0xAA
被存入 接收缓冲区(RXFIFO);Step 3:RXNE 标志反馈接收缓冲区非空
当接收字节被转移到 RXFIFO,状态寄存器的接收缓冲区非空标志位置位,通知 CPU读取数据;Step 4:CPU 读取 RXFIFO
CPU 通过地址和数据总线访问 RXFIFO,读出0xAA
,完成接收;
ECSPI控制器
I.MX6ULL 具有 4 个 ECSPI,每个 ECSPI 支持四个硬件片选信号
关键特性
- 全双工同步串行接口
- 可配置为主机 / 从机模式
- 四路片选(SS)信号,支持多外设连接
- 传输续传功能,允许无限制长度的数据传输
- 收发数据均采用 32 位宽、64 项深度 的 FIFO(即每个 FIFO 可存 64 个 32 位数据)
- 片选(SS)和 SPI 时钟(SCLK)的极性与相位均可配置
- 支持直接内存访问(DMA)
- 最大工作频率可达到参考时钟频率(即与系统参考时钟同频运行)
- 主机模式(Master Mode):设备作为通信发起者和控制者,主动产生 SCLK 时钟 和 片选信号(SS),驱动数据传输;
- 从机模式(Slave Mode):设备作为被动响应者,不产生时钟,等待主机的 SCLK 和 SS 信号,同步收发数据;
时钟源
主机作为 SPI 时钟(SCLK)的主动生成者,从机作为 被动同步者,主机选取通信速度(SCLK 频率)不能超过从机规格书中标注的最大时钟频率,否则传感器无法正确采样,导致数据传输出错;
结论:主机的 SCLK 频率 ≤ 从机支持的最大 SCLK 频率
①. 复用器用于选择根时钟源,由 CSCDR2寄存器 的 ECSPI_CLK_SEL位控制,配置为 0 选择 pll3_60m 作为 ECSPI 根时钟源,配置为 1 选择 osc_clk 作为 ECSPI 时钟源;假设配置为1;
②. ECSPI 时钟分频值,由CSCDR2寄存器 的ECSPI_CLK_PODF位控制,分频值为 (2^ECSPI_CLK_PODF),假设设置为 0,即 1 分频;
③. 最终进入 ECSPI模块时钟ECSPI_CLK_ROOT=60MHz;
主机模式
等待状态
若主机(ECSPI)速度远快于从设备,从设备可能因无法及时处理数据导致错误,存在一种解决方案是在 连续的 SPI 突发传输之间(突发传输:单次片选(SS)有效期间,连续传输多个字节 / 位的数据块) 插入若干个等待状态(空闲周期),延长传输间隔,给从设备足够时间处理数据;
阶段 1:第一个突发传输(Burst 1)
- SS 拉低(选中从机)→ SCLK 产生时钟脉冲 → MOSI/MISO 传输数据→ SS 拉高(释放从机,结束第一个突发);
阶段 2:等待状态(Wait States)
- SS 保持拉高(从机被释放,不响应 SCLK)→ SCLK 产生空闲时钟(由寄存器
ECSPI_PERIODREG
配置,用于延长间隙时间)→ 此阶段无数据传输,给从机 / 主机时间处理上一突发的收尾(从机将 RXFIFO 数据写入内部缓存,主机准备下一突发的 TXFIFO 数据);阶段 3:第二个突发传输(Burst 2)
- SS 再次拉低(重新选中从机)→ SCLK 恢复时钟脉冲 → 继续传输新的一组数据 → SS 拉高(结束第二个突发);
实现机制:
- 数量控制:通过
ECSPI_PERIODREG[SAMPLE PERIOD]
配置等待状态的持续周期数(插入 n个时钟周期的空闲);- 时钟源选择:通过
ECSPI_PERIODREG[CSRC]
选择等待状态的时钟来源;
片选控制
SPI 片选控制用于决定当前操作是 单突发传输 还是 多突发传输;
单突发传输: 一次片选(SS)持续低电平期间,连续传输 多个数据块,片选(SS)仅拉低一次,直到所有数据传输完成后才拉高;
多突发传输:将传输拆分为 多个独立的短突发,每次突发对应 独立的片选周期(SS 拉低→传输→拉高),片选(SS)多次拉低 / 拉高,每次突发是独立的片选有效周期;
ECSPI_CONREG
寄存器BURST_LENGTH
位定义单个突发的最大字节数,ECSPI_CONREG
寄存器SS_CTL位进行模式切换;
- SS_CTL置位(多突发传输):适合需独立片选触发的外设;
- SS_CTL清零(单突发传输):适合需连续数据流的外设;
单突发传输
一 突发前:片选拉低,初始化通信
- SS 拉低 → 从机被选中,进入待命状态;
- SCLK 开始产生时钟脉冲 → 准备传输数据;
二 数据传输阶段 1:TXFIFO 有数据,连续移位
- TXFIFO 预存数据→ ECSPI 自动从 FIFO 取数据,通过 MOSI 逐位移出;
- SCLK 持续运行 → 每个时钟边沿触发 MOSI/MISO 数据移位(全双工同步);
三 等待间隙:TXFIFO 空,SCLK 暂停
- 若 TXFIFO 数据耗尽(两个 8 位数据传输完成,新数据未及时填充)→ ECSPI 插入等待软件写数据的间隙:
- SCLK 暂停产生 “有效移位时钟”(可能保持固定电平或低速运行);
- 此间隙给软件时间填充 TXFIFO(如 CPU 响应中断,写入新数据到 TXFIFO);
四 数据传输阶段 2:TXFIFO 填充后,恢复传输
- 软件向 TXFIFO 写入新数据 → ECSPI 检测到 FIFO 非空,恢复 SCLK 时钟脉冲;
- 继续传输后续数据,直到 BURST LENGTH 定义的长度完成;
五 突发后:片选拉高,结束通信
- 所有数据传输完成 → SS 拉高 → 释放从机,结束本次单突发传输;
多突发传输
相位控制
相位控制位(
ECSPI_CONREG[PHA]
)用于控制 发送数据的移位输出边沿 和 接收数据的锁存边沿;
ECSPI Memory Map
ECSPI寄存器
ECSPIx_RXDATA
只读寄存器(Read-Only),该寄存器始终显示FIFO 最前端的未读数据(即第一个入队、尚未被读取的数据),每次成功读取该寄存器(且 RXFIFO 非空),FIFO 会自动推进即头部数据被消费,下一个数据上移到 FIFO 头部,等待下一次读取;
ECSPIx_TXDATA
只写寄存器(Write-Only),写入的数据追加到 FIFO 尾部,该寄存器允许软件持续写入数据到 FIFO 尾部(只要 FIFO 未满),即使 SPI 正在发送数据(
ECSPI_CONREG[XCH]=1
,即XCH 置位,硬件正在发送 TXFIFO 中的数据);
ECSPIx_CONREG
bit[31:20]: BURST_LENGTH位,定义 单次 SPI 突发(片选(SS)仅拉低一次)传输的有效位数,从 LSB 开始,截取连续
n
位传输,n = BURST_LENGTH + 1,示例如下:
0x00000003
(二进制0000 0000 0000 0000 0000 0000 0000 0011
):
BURST_LENGTH=0x000
(n=1)→ 传输bit0=1
(LSB);BURST_LENGTH=0x001
(n=2)→ 传输bit0=1
,bit1=1
;典型值映射:
0x000
→ 1 位(LSB 优先);0x01F
→ 32 位(完整字传输);
bit[19:18]: CHANNEL_SELECT位,通道选择位,通道是指同一 ECSPI 模块内部,通过硬件片选(SS0~SS3)区分的从设备选择通道;
bit[15:12]: PRE_DIVIDER位,预分频,
0000
=1 分频,0001
=2 分频,…,1111
=16 分频;bit[11:8]: POST_DIVIDER位,后分频(2 的幂次分频),
0000
=2⁰=1 分频,0001
=2¹=2 分频,…,1111
=2¹⁵ 分频;ECSPI 采用 两级分频器 生成 SPI 时钟(SCLK),公式:
SCLK频率 = 参考时钟 / [(PRE_DIVIDER + 1) × (2^POST_DIVIDER)]
- 假设参考时钟为 80MHz,需 SCLK=10MHz → 总分频
80/10=8
;- 选
PRE_DIVIDER=0001
(2 分频),POST_DIVIDER=0010
(4 分频)→ 总分频2×4=8
,符合需求;
bit[7:4]: CHANNEL_MODE位,ECSPI1 模块的 通道编号 与 片选引脚(SSn) 是 一一固定对应 ,每个通道可独立配置主 / 从模式;
bit[3]: SMC位,SMC位仅对主机模式通道有效,即
CHANNEL_MODE=1
,决定:当 TXFIFO 有数据时,ECSPI 如何触发SPI 突发传输,具有两种触发逻辑,由SMC
位的值决定:模式 1:
SMC = 0
(默认)→ 由XCH
位显式控制启动
- 触发条件:需软件主动设置
XCH
位(ECSPI_CONREG[XCH] = 1
),才会启动 SPI 突发传输;- 与
SS_CTL
协同:XCH
启动的是单次突发还是多次突发,由SS_CTL
(SPI SS Wave Form Select)决定:
- 若
SS_CTL
配置为多突发模式:XCH
置 1 后会持续启动突发,直到 TXFIFO 空或手动清零XCH
;- 若
SS_CTL
配置为单突发模式:XCH
置 1 仅启动一次突发,传输完成后自动清零XCH
;模式 2:
SMC = 1
→ 写入 TXFIFO 时自动启动
- 触发条件:无需软件干预
XCH
,只要向 TXFIFO 写入数据(通过ECSPI_TXDATA
寄存器),硬件会立即自动启动 SPI 突发传输;- 特点:数据写入 TXFIFO 的瞬间,突发自动开始,适合需要实时采集传感器数据的场景;
bit[2]:XCH位,用于控制 SPI 突发的启动时机;
0
:空闲(无传输);1
:启动单次 / 多次突发(由SS_CTL
定义模式),传输中自动保持置 1,完成后清零
bit[0]: EN位,使能 / 禁用 ECSPI 模块;
- 置
1
:使能模块;- 置
0
:禁用模块;
ECSPIx_CONFIGREG
bit[23:20]:SCLK_CTL(SCLK 空闲状态控制位),用于控制每个通道的 SCLK 在空闲期的电平状态,
SCLK_CTL[3:0]
分别对应 Channel 3~0;
0
:空闲时 SCLK 保持 低电平;1
:空闲时 SCLK 保持 高电平;
bit[19:16]:DATA_CTL(数据引脚空闲状态控制),
DATA_CTL[3:0]
分别对应 Channel 3~0(每位控制一个通道);
0
:空闲时数据引脚保持 高电平;1
:空闲时数据引脚保持 低电平;
bit[15:12]:SS_POL(片选极性控制),控制每个通道的 片选信号(SSn)的有效电平,
SS_POL[3:0]
分别对应 Channel 3~0;
0
:SS 有效电平为 低电平(常见模式,SS 拉低选通从机);1
:SS 有效电平为 高电平(特殊场景,SS 拉高选通从机);
bit[11:8]: SS_CTL(片选波形控制),主机模式(
SMC=0
时生效):
0
:单突发模式 → 片选保持低电平,仅传输一次突发;1
:多突发模式 → 片选在突发间拉高,连续传输多次突发(直到 TXFIFO 空)
bit[7:4]:SCLK_POL,控制每个通道的 SCLK 极性(空闲电平),
SCLK_POL[3:0]
分别对应 Channel 3~0(每位控制一个通道的 SCLK 极性);
0
:SCLK 空闲电平为 高(CPOL=1);1
:SCLK 空闲电平为 低(CPOL=0);
bit[3:0]: SCLK_PHA(时钟相位控制,即 CPHA),控制每个通道的 SCLK 相位(数据采样 / 移位的边沿),
SCLK_PHA[3:0]
分别对应 Channel 3~0(每位控制一个通道的 SCLK 相位);
0
:Phase 0 模式 → 采样在 第一边沿(由 CPOL 决定上升 / 下降沿);1
:Phase 1 模式 → 采样在 第二边沿(由 CPOL 决定上升 / 下降沿);
ECSPIx_STATREG
bit[7]:(TC),传输完成状态(Transfer Completed),用于指示当前 SPI 突发传输是否完成;
0
:传输中(数据移位未完成,或新传输已启动);1
:传输完成(所有数据已移位输出 / 输入,可启动新传输);- 操作:写 1 清零(
w1c
),软件需主动清零以准备下一次传输;
bit[6]: (RO),接收 FIFO 溢出(RXFIFO Overflow),用于检测 RXFIFO 溢出错误;
0
:无溢出;1
:溢出(数据丢失风险,需软件处理);- 操作:写 1 清零(
w1c
),清零后需检查 RXFIFO 数据,避免遗漏;
bit[5]: (RF),接收 FIFO 满(RXFIFO Full),用于指示 RXFIFO 是否已满(达到 64 字深度);
0
:未满(可继续接收数据);1
:已满(需立即读取 RXFIFO,否则可能触发 RO 溢出);- 操作:只读,由硬件根据 FIFO 状态自动更新;
bit[3]: (RR),接收 FIFO 就绪(RXFIFO Ready),指示 RXFIFO 中是否有有效数据(至少 1 个字);
0
:空(无有效数据,读取 RXDATA 会返回未定义值);1
:就绪(有数据,可安全读取 RXDATA);- 操作:只读,由硬件根据 FIFO 状态自动更新;
bit[2]: (TF),发送 FIFO 满(TXFIFO Full),用于指示 TXFIFO 是否已满(达到 64 字深度);
0
:未满(可继续写入数据);1
:已满(写入 TXDATA 会失败,需等待 FIFO 空);- 操作:只读,由硬件根据 FIFO 状态自动更新;
bit[0]: (TE),发送 FIFO 空(TXFIFO Empty),用于指示 TXFIFO 是否为空(无有效数据);
0
:非空(有数据,可继续传输);1
:空(需写入数据,否则传输会暂停或发送 0);- 操作:只读,由硬件根据 FIFO 状态自动更新;
ECSPIx_PERIODREG
bit[21:16]: CSD_CTL位,主机拉低片选(SS)选中从机后,先等几个 SCLK 周期,让从机准备好接收数据,CSD_CTL用于控制片选有效边沿 → 第一个 SCLK 边沿 的延迟时钟数,取值范围为
0 - 63
,表示插入0 - 63
个 SPI 时钟周期(SCLK) 的延迟;
bit[15]:CSRC位,用于选择等待状态的时钟来源,决定延迟时间的基准频率;
0
:SPI 时钟(SCLK)→ 延迟时间随 SCLK 频率动态变化(当SCLK=10MHz 时,1 个等待状态 = 100ns,当SCLK=1MHz 时 = 1μs);1
:低频参考时钟(32.768KHz)→ 延迟时间固定(1 个等待状态≈30.5μs),不受 SCLK 频率影响;
bit[14:0]: SAMPLE_PERIOD,用于控制 连续 SPI 传输之间 插入的等待状态数量,取值范围为0~32767,仅在 主机模式(
CHANNEL_MODE=1
)且多突发传输时生效;