SPI通信协议深度解析:Motorola与TI帧格式对比及MSPM0配置实战
1. SPI通信协议与MSPM0 UNICOMM-SPI模块概述
在嵌入式系统开发中,微控制器与外围设备(如传感器、存储器、显示屏驱动芯片等)之间的高效数据交换是核心任务之一。SPI(Serial Peripheral Interface)协议因其简单、高速、全双工的特性,成为了这类短距离通信的基石。它不像I2C那样需要复杂的地址寻址和应答机制,而是通过一个主设备(Controller,通常为MCU)控制一个或多个从设备(Peripheral),利用时钟线(SCLK)、片选线(CS)以及两根数据线(PICO/MOSI, POCI/MISO)实现数据的同步收发。这种“一主多从”的架构,使得SPI在需要高带宽、低延迟的应用场景中,如读取高速ADC数据或驱动TFT屏幕,具有无可替代的优势。
然而,SPI协议本身只是一个宽泛的框架,其具体的电气特性和时序细节,尤其是时钟极性与相位、数据帧的起止边界,并没有一个全球统一的标准。这就催生了两种在工业界广泛应用的实现变体:Motorola SPI帧格式和Texas Instruments(TI)同步串行帧格式。这两种格式的核心差异在于时钟空闲状态、数据捕获边界的定义,以及片选信号在整个传输周期中的行为。对于嵌入式工程师而言,理解这些差异并能在硬件层面正确配置,是确保通信稳定可靠的第一步。
德州仪器的MSPM0 L系列微控制器,其内置的UNICOMM-SPI模块,正是这样一个高度灵活且功能强大的通信外设。它不仅完整支持上述两种帧格式,还集成了深度可配置的FIFO、多种中断源以及DMA触发机制,旨在最大化数据吞吐效率并减轻CPU负担。本篇文章将从一个资深嵌入式开发者的视角,深入拆解Motorola与TI两种SPI帧格式的时序奥秘,并手把手带你剖析MSPM0 UNICOMM-SPI模块的关键寄存器配置、中断与DMA的使用策略,以及在实际项目中容易踩到的“坑”。无论你是正在评估MSPM0芯片,还是已经深陷SPI通信调试的泥潭,相信这里的细节和经验都能为你提供直接的帮助。
2. Motorola与TI SPI帧格式的深度解析与时序实战
要正确驱动一个SPI外设,第一步永远是看懂它的数据手册中的时序图。而时序图的核心,就是帧格式。MSPM0的UNICOMM-SPI模块通过CTL0.FRF(Frame Format)位域来切换这两种模式。选择错误,通信必然失败。
2.1 Motorola SPI帧格式:极性与相位的四种组合
Motorola格式是SPI协议中最经典和最常见的实现。它的时序由两个关键参数决定:时钟极性SPO(Clock Polarity)和时钟相位SPH(Clock Phase)。通过CTL0寄存器的SPO和SPH位进行配置,可以产生四种模式,通常被称为模式0到模式3。
- 时钟极性
SPO:决定了SCLK线在空闲状态(即CS为高电平,无数据传输时)的电平。SPO = 0:SCLK空闲时为低电平。SPO = 1:SCLK空闲时为高电平。
- 时钟相位
SPH:决定了数据在SCLK的哪个边沿被采样(捕获),以及在哪个边沿被更新(移位输出)。SPH = 0:数据在SCLK的第一个边沿(即从空闲状态跳变后的第一个边沿)被捕获,在第二个边沿更新。SPH = 1:数据在SCLK的第二个边沿被捕获,在第一个边沿更新。
你提供的文档图27-6展示的是SPO=1, SPH=1(即模式3)的配置。我们来详细拆解这个时序:
- 空闲期(Idle):
CS为高,SCLK为高(由SPO=1决定)。此时主设备的PICO(即MOSI)输出被强制拉低。这是一个很重要的细节,可以避免总线在空闲时浮空产生干扰。 - 传输启动:当SPI控制器使能且TX FIFO中有数据时,主设备将
CS拉低。这标志着一次传输的开始。紧接着,主设备的PICO输出引脚被使能。 - 第一个半周期与数据使能:在
CS拉低后,经过半个SCLK周期,主设备和从设备的数据才被使能到各自的传输线上。同时,SCLK产生一个下降沿(从高到低)的跳变。这个“半个周期”的延迟是SPH=1模式下的关键特征,它为从设备提供了足够的建立时间(Setup Time)来准备数据。 - 数据捕获与更新:在
SPO=1, SPH=1模式下,数据在SCLK的上升沿被捕获(采样),在下降沿被更新(移位输出)。这意味着主设备在SCLK下降沿改变PICO上的数据,从设备在随后的SCLK上升沿读取这个稳定的数据。同时,从设备也在SCLK下降沿改变POCI上的数据,主设备在下一个上升沿读取。 - 传输结束:
- 单字传输:所有比特传输完毕后,在最后一位被捕获后的一个完整SCLK周期,
CS线返回高电平空闲状态。 - 连续背靠背传输:
CS线在多个数据字之间保持低电平,直到最后一个字的最后一位被捕获后,才返回高电平。
- 单字传输:所有比特传输完毕后,在最后一位被捕获后的一个完整SCLK周期,
实操心得:模式选择的“潜规则”大多数SPI设备的数据手册会明确要求使用哪种模式(Mode 0, 1, 2, 3)。最常见的组合是
SPO=0, SPH=0(模式0)和SPO=0, SPH=1(模式1)。一个快速记忆方法是:关注数据捕获的边沿。对于从设备(如传感器),你只需要关心它在哪个边沿采样你的数据。通常,SPH=0意味着在SCLK的第一个边沿(对于SPO=0是上升沿,对于SPO=1是下降沿)采样;SPH=1则在第二个边沿采样。配置时务必与从设备手册严格一致。
2.2 TI同步串行帧格式:独特的片选脉冲
TI同步串行帧格式是另一种流行的标准,尤其在TI自家的许多外设中使用。它与Motorola格式的一个显著区别在于CS(在TI文档中常称为FSX或FSS)信号的行为。
根据文档图27-7,TI格式的时序特点如下:
- 空闲期(Idle):
SCLK和CS都被强制拉为低电平。主设备的PICO输出引脚处于高阻态(Tristate)。这与Motorola格式中CS和SCLK可配置为高或低不同,TI格式的空闲状态是固定的。 - 传输启动:当TX FIFO底部有数据时,
CS线会被拉高一个SCLK周期。这个脉冲信号标志着帧的开始。同时,待发送的数据从TX FIFO转移到发送逻辑的串行移位寄存器中。 - 数据移出:在
CS脉冲后的下一个SCLK上升沿,数据帧的最高有效位(MSB)从PICO引脚移出。同样,外部从设备的MSB也在此刻移出到POCI线上。 - 数据捕获:在SCLK的每个下降沿,SPI主设备和外部从设备都将数据位采样到各自的串行移位器中。这是一个关键区别:在TI格式下,数据总是在SCLK的下降沿被捕获。
- 数据存储:在最低有效位(LSB)被锁存后,第一个SCLK上升沿将接收到的数据从串行移位器传输到RX FIFO。
- 传输结束:
CS线在帧结束后恢复低电平。SCLK在空闲期同样保持不活动状态。
注意事项:TI格式的片选行为TI格式的
CS信号是一个短暂的脉冲,而非整个传输期间都保持有效的片选。这意味着它更像一个“帧同步”信号。在设计硬件连接时,需要确保从设备支持这种脉冲式片选。许多标榜“SPI兼容”的设备实际上只支持Motorola格式的常低片选。误用格式会导致从设备无法正确识别帧起始。
2.3 两种格式的对比与选型指南
为了更直观地对比,我将两种格式的核心差异总结如下表:
| 特性 | Motorola SPI 帧格式 | TI 同步串行帧格式 |
|---|---|---|
| 配置位 | CTL0.FRF = 0(3线) 或1(4线) | CTL0.FRF = 2 |
| 空闲状态 | CS高,SCLK由SPO决定(0=低,1=高) | CS低,SCLK低 |
| 片选(CS)行为 | 在整个数据字传输期间保持有效(低电平) | 在每个数据字开始前产生一个SCLK周期的高电平脉冲 |
| 数据捕获边沿 | 由SPO和SPH共同决定,可以是上升沿或下降沿 | 固定为SCLK下降沿 |
| 数据更新边沿 | 与捕获边沿相反 | SCLK上升沿(MSB移出) |
| 典型应用 | 绝大多数SPI Flash、传感器、ADC/DAC | 某些TI专属外设,部分音频编解码器 |
选型建议:
- 优先遵从从设备手册:这是铁律。从设备要求什么格式,主设备就必须配置成什么格式。
- Motorola格式的通用性:在不确定或需要兼容多种设备时,Motorola格式(尤其是模式0和模式3)是更安全的选择,其支持度最广。
- TI格式的特殊考量:仅在明确知道从设备支持TI格式时使用。它的脉冲式CS可以减少总线切换,在某些多从机系统中可能有优势,但通用性较差。
3. MSPM0 UNICOMM-SPI模块的寄存器配置详解
理解了帧格式,我们接下来就要在MSPM0的寄存器层面进行配置。UNICOMM-SPI的寄存器虽然看起来繁多,但按照功能模块化理解,就会清晰很多。配置的核心流程通常遵循:时钟源配置 -> 引脚复用 -> 基本参数设置 -> 中断/DMA配置 -> 使能模块。
3.1 时钟与基础控制寄存器配置
SPI通信的速率和稳定性,首先取决于时钟的精确配置。
1. 时钟源选择与分频 (CLKSEL,CLKDIV,CLKCTL)SPI模块的工作时钟SPIclk来源于系统时钟。CLKSEL寄存器用于选择异步或同步的时钟源(如PLL、HFCLK、SYSCLK等)。对于大多数应用,选择系统主时钟(SYSCLK)即可。 确定了源时钟频率后,需要通过CLKDIV和CLKCTL.SCR进行分频,以得到最终的SPI比特率。
CLKDIV.RATIO:对源时钟进行一个粗分频(1-8分频)。CLKCTL.SCR:进行精细分频。SPI的比特率计算公式为:SPI Bit Rate = SPIclk / ((SCR + 1) * 2)。- 例如,系统时钟
SPIclk为32MHz,目标SPI波特率为4Mbps。则SCR = (SPIclk / (Bit Rate * 2)) - 1 = (32e6 / (4e6 * 2)) - 1 = 3。配置SCR=3即可。
- 例如,系统时钟
2. 核心控制寄存器0 (CTL0)这个寄存器定义了SPI通信的基本范式。
FRF[1:0]:帧格式选择。00=Motorola 3线,01=Motorola 4线,10=TI格式,11保留。SPO和SPH:如前所述,用于配置Motorola格式的时钟极性和相位。在TI格式下,这两位通常被忽略。DSS[4:0]:数据大小选择。支持4位到16位的数据帧长度。例如,发送8位数据,则配置DSS=0x7(对应8位)。重要提示:当数据长度小于16位时,写入TXDATA的数据必须右对齐,未使用的高位会被硬件忽略。读取RXDATA时,数据也是右对齐的。CSSEL[1:0]:选择使用哪个片选线(CS0-CS3)。在控制器模式下可以动态更改,在从设备模式下必须在使能模块前配置好。PACKEN:打包使能。当使能时,一次32位的写操作会向TX FIFO压入两个16位数据;一次32位的读操作会从RX FIFO弹出两个16位数据。这可以提升总线利用率,适合连续大批量传输。
3. 核心控制寄存器1 (CTL1)这个寄存器包含了一些高级控制和模式选择。
ENABLE:SPI模块总使能位。必须在所有配置完成后最后设置。在修改CTL0、CTL1(除ENABLE外)等关键配置前,必须先清除此位。CP:控制器/外设模式选择。1=控制器模式,0=外设模式。MSB:数据传输顺序。0=LSB先传,1=MSB先传。需与外设保持一致。LBM:回环模式使能。用于模块自测试,将发送端数据直接环回到接收端,不经过外部引脚。调试时非常有用。POD(外设输出禁用):在多外设系统中,当控制器广播数据时,只有一个外设应驱动数据线。将此位置1可以禁用特定外设的输出驱动,避免总线冲突。PREN和PES:奇偶校验使能和校验类型选择(偶校验/奇校验)。用于增加通信的可靠性。RXTIMEOUT:接收超时值配置(仅外设模式)。当SCLK线长时间无活动且RX FIFO中有数据时,会触发超时中断。
3.2 状态寄存器与FIFO操作
状态寄存器 (STAT)这个只读寄存器提供了SPI模块的实时状态,是编写健壮驱动程序的基础。
BUSY:最常用的标志位。为1表示SPI正在发送或接收数据。在启动一次传输或查询传输是否完成时,都需要检查此位。TXFE/TXFF:TX FIFO空/满标志。用于判断是否可以写入新数据。RXFE/RXFF:RX FIFO空/满标志。用于判断是否有新数据可读。CDMODE:反映当前的命令/数据模式计数值。在启用CDENABLE(使用CS3作为C/D线)时有用。
FIFO操作与中断水平选择 (IFLS)UNICOMM-SPI模块内置了TX和RX FIFO,深度取决于具体型号。IFLS寄存器用于设置触发中断或DMA请求的FIFO阈值。
TXIFLSEL:设置TX FIFO中断触发水平。例如,设置为2(1/2空)时,当TX FIFO中的数据量少于或等于一半时,会触发TX中断,提示CPU可以填充更多数据。RXIFLSEL:设置RX FIFO中断触发水平。例如,设置为2(1/2满)时,当RX FIFO中的数据量达到或超过一半时,会触发RX中断,提示CPU可以读取数据。TXCLR/RXCLR:写1可分别清空TX和RX FIFO。在模块初始化或错误恢复时常用。
数据寄存器 (TXDATA,RXDATA)
TXDATA:写入数据到此寄存器,数据被压入TX FIFO。如果FIFO已满,写入操作会被阻塞或丢失(取决于具体实现)。RXDATA:从此寄存器读取数据,数据从RX FIFO弹出。如果FIFO为空,读取将返回未定义值或上次读取的值。
配置流程示例(控制器模式,8位数据,模式0,2Mbps)假设系统时钟为32MHz,目标波特率2Mbps。
- 禁用SPI模块:
CTL1.ENABLE = 0。- 配置IOMUX,将对应GPIO引脚复用为SPI功能(SCLK, PICO, POCI, CS)。
- 配置时钟:
CLKSEL选择系统时钟源。计算SCR = (32e6 / (2e6 * 2)) - 1 = 7,设置CLKCTL.SCR = 7。CLKDIV可根据需要设置,此处用默认值1分频。- 配置
CTL0:FRF=0(Motorola),SPO=0,SPH=0(模式0),DSS=0x7(8位),CSSEL选择使用的CS线。- 配置
CTL1:CP=1(控制器模式),MSB=1(MSB先传,常见),LBM=0,其他如奇偶校验按需设置。- 配置
IFLS:根据应用设置中断阈值,例如TXIFLSEL=2,RXIFLSEL=2。- 配置中断使能(
IMASK)和DMA(如果需要)。- 最后,使能模块:
CTL1.ENABLE = 1。
4. 中断系统与DMA传输的实战应用
对于高效的数据传输,轮询STAT寄存器的方式会大量占用CPU资源。UNICOMM-SPI提供了丰富的中断事件和DMA触发机制,可以实现“后台”数据传输。
4.1 中断事件详解与处理流程
中断相关的寄存器组(CPU_INT)包括:IIDX(中断索引)、IMASK(中断掩码)、RIS(原始中断状态)、MIS(屏蔽后中断状态)、ISET(软件置位)、ICLR(软件清除)。
关键中断源及其含义:
RX/TX:最常用的中断。当RX FIFO数据达到IFLS.RXIFLSEL设定的水平,或TX FIFO数据低于IFLS.TXIFLSEL设定的水平时触发。用于流控。RXFIFO_OVF:RX FIFO溢出。发生此中断意味着数据丢失,通常是由于CPU读取速度跟不上SPI接收速度所致。需要检查并优化代码,或启用DMA。TXFIFO_UNF:TX FIFO下溢(仅外设模式)。当控制器送来时钟,但外设的TX FIFO已空时触发。外设需要及时填充数据。RTOUT:接收超时(仅外设模式)。当SCLK线长时间无活动且RX FIFO非空时触发。可用于检测通信中断。IDLE:SPI进入空闲状态。一次传输序列完成时触发。DMA_DONE_RX/DMA_DONE_TX:DMA传输完成中断。
中断处理流程(以RX中断为例):
- 使能中断:在
IMASK寄存器中,将RX位(bit 2)置1。 - 中断发生:当RX FIFO数据量达到阈值,
RIS.RX位被硬件置1。如果IMASK.RX也为1,则MIS.RX变为1,并向CPU产生中断请求。 - 中断服务程序(ISR):
- 读取
IIDX寄存器。硬件会自动返回最高优先级的中断索引(例如0x03对应RX中断),并自动清除该中断在RIS和MIS中的标志位。这是自动清除方式。 - 或者,在ISR中根据
MIS寄存器判断中断源,然后通过向ICLR寄存器的对应位写1来手动清除中断标志。
- 读取
- 数据处理:在RX中断的ISR中,循环读取
RXDATA寄存器,直到STAT.RXFE变为1(FIFO空)或数据量低于阈值,以防止中断频繁触发。
避坑指南:中断标志清除务必仔细阅读数据手册关于中断清除的说明。对于
IIDX读取自动清除的方式,在ISR中只需读一次IIDX即可。对于手动清除方式(写ICLR),要确保在离开ISR前清除所有已处理的中断标志,否则会导致中断持续触发,系统卡死。混合使用两种方式可能导致意外行为,建议统一采用一种。
4.2 DMA传输配置指南
对于大数据块传输(如读写SPI Flash、传输图像数据),使用DMA可以彻底解放CPU。UNICOMM-SPI提供了独立的DMA_TRIG_RX和DMA_TRIG_TX事件发布者来触发DMA传输。
DMA传输的核心思想:当SPI的TX FIFO有空位或RX FIFO有数据时,自动触发DMA控制器,将内存中的数据搬运到TXDATA寄存器,或将RXDATA寄存器的数据搬运到内存,整个过程无需CPU干预。
配置SPI以触发DMA(以RX DMA为例):
- 使能DMA触发:在
DMA_TRIG_RX.IMASK寄存器中,使能RX触发位。 - 配置DMA通道(以MSPM0的DMA架构为例): a.选择通道:选择一个可用的DMA通道。 b.配置触发源:在DMA通道的触发控制寄存器(如
DMA_CH[n].DMATCTL)中,设置触发源为UNICOMM-SPI的RX事件。 c.配置地址: * 源地址 (DMASA):设置为SPI的RXDATA寄存器地址。这是一个外设地址,DMA从此读取数据。 * 目的地址 (DMADA):设置为SRAM中接收缓冲区的地址。DMA将数据写入此处。 d.配置传输属性: * 数据宽度 (DMADSTWDTH,DMASRCWDTH):设置为8位或16位,与SPI的DSS设置匹配。 * 地址增量:源地址(RXDATA)设置为不增量(No Change),因为总是读取同一个寄存器。目的地址(SRAM)设置为递增(Increment)。 * 传输数量 (DMASZ):设置需要传输的数据总量(如字节数)。 e.使能DMA通道:设置DMAEN位。
配置SPI以触发DMA(TX DMA配置同理):触发源改为TX事件,源地址是SRAM发送缓冲区,目的地址是TXDATA寄存器。
实操心得:DMA与FIFO阈值的协同DMA的触发同样受
IFLS.RXIFLSEL和IFLS.TXIFLSEL控制。例如,设置RXIFLSEL为“1/2满”,那么当RX FIFO数据达到一半时,才会触发DMA请求去读取数据。合理的阈值设置可以平衡响应速度和中断/DMA请求频率。对于大数据量连续传输,建议将阈值设得高一些(如3/4满),以减少触发次数,提升效率。对于低延迟要求的小数据包,可以设置较低的阈值(如1/4满)。
5. 常见问题排查与调试技巧实录
即使理解了所有寄存器,实际调试SPI通信时依然会遇到各种问题。下面是我在多年项目中总结的一些典型故障场景和排查手段。
5.1 通信完全无响应的排查清单
检查最基本的三要素:
- 电源与地:确保主从设备共地,电源电压符合要求。
- 物理连接:用万用表或示波器检查SCLK、PICO、POCI、CS四根线(3线模式则无POCI)是否连通,有无短路到电源或地。
- 引脚复用:这是新手最常犯的错误。确认MCU的SPI引脚已通过IOMUX正确配置为SPI功能,而非默认的GPIO。查阅MSPM0的引脚复用表,并检查对应的IOMUX寄存器配置。
确认电气电平:如果主从设备电压不同(如MCU是3.3V,外设是5V),需要电平转换电路,不能直接连接。
示波器/逻辑分析仪是终极武器:
- 先看CS和SCLK:发送数据时,CS线是否按预期拉低?SCLK上是否有脉冲?如果SCLK没有波形,检查SPI模块是否已使能(
CTL1.ENABLE=1),以及时钟配置(CLKSEL,CLKCTL)是否正确。 - 再看数据线:在SCLK和CS都正常的前提下,观察PICO(主机输出)线上是否有随SCLK变化的数据波形?如果主机有输出但从机无回应,检查从机是否已上电、使能,以及模式(控制器/外设)是否设反。
- 对照时序图:将示波器捕获的波形与芯片手册中的时序图(Motorola或TI格式)严格对比。重点关注:
CS有效到第一个SCLK边沿的延迟。- 数据是在
SCLK的哪个边沿(上升/下降)稳定(建立和保持时间)。 CS在传输结束后的释放时间。
- 先看CS和SCLK:发送数据时,CS线是否按预期拉低?SCLK上是否有脉冲?如果SCLK没有波形,检查SPI模块是否已使能(
5.2 数据错位或字节顺序错误
- MSB/LSB设置错误:检查
CTL1.MSB位。大多数设备是MSB先传,但有些(如某些音频芯片)是LSB先传。这个必须与外设手册一致。 - 数据位宽不匹配:检查
CTL0.DSS设置的数据位宽是否与外设期望的相同。例如,外设是12位ADC,但SPI配置为8位,就会导致数据错乱。 - FIFO打包问题:如果使能了
PACKEN(打包),那么一次32位写操作会向TX FIFO压入两个16位数据。如果实际数据帧不是16位的整数倍,或者读写操作不是32位对齐的,就会导致数据拼接错误。在不确定时,先关闭打包功能。
5.3 使用调试工具与软件技巧
充分利用回环模式:将
CTL1.LBM置1,使能内部回环。在此模式下,发送的数据会被直接环回到接收端。编写一个简单的测试程序,发送一组已知数据(如0xAA,0x55),然后读取接收数据。如果回环测试通过,证明SPI模块本身的配置、时钟、数据路径是正常的,问题可能出在外部电路或从设备上。模拟器与单步调试:在IDE(如CCS或IAR)中使用仿真器,单步执行SPI初始化代码,观察关键寄存器(
CTL0,CTL1,CLKCTL)的值是否按预期设置。在发送数据后,观察STAT.BUSY位的变化,以及TXDATA/RXDATA寄存器的值。超时机制:在发送或接收数据时,不要无限等待
BUSY标志或中断。添加一个基于系统滴答定时器的超时判断。例如,等待BUSY变低,如果超过10ms仍为高,则判定为通信超时,进行错误处理并复位SPI模块。这能防止程序因硬件故障而死锁。FIFO状态监控:在中断或DMA处理函数中,除了处理数据,还应监控
STAT.RXFF(满)和STAT.RXFE(空)标志,确保不会溢出或读空。特别是在高波特率下,CPU处理速度可能成为瓶颈。
5.4 多从机系统与片选管理
UNICOMM-SPI支持多个硬件CS线(CS0-CS3)。在驱动多个SPI从设备时:
- 硬件CS:为每个从设备分配独立的CS引脚。在传输前,通过配置
CTL0.CSSEL来选择对应的CS线,硬件会自动控制其拉低和拉高。这是最可靠的方式。 - 软件GPIO模拟CS:如果硬件CS线不够用,可以将额外的GPIO配置为输出,在传输前后手动拉低和拉高。注意:手动控制CS时,要严格遵循时序图,确保CS在SCLK空闲期间变化,并满足从设备要求的建立和保持时间。
CS_MASK_ROTATE功能:这是一个高级功能,用于在连续传输中自动轮询多个CS线。需要仔细配置CSx_ROTATE_MASK寄存器。在常规应用中,手动控制CS更为直观。
调试SPI通信,耐心和系统性排查是关键。从电源、地线、连接等硬件基础开始,再到软件配置的每一个比特,最后用仪器验证波形。把问题分解,逐一验证,总能找到症结所在。MSPM0的UNICOMM-SPI模块功能全面,一旦配置正确,其稳定性和性能都非常出色。
