1. SPI总线核心原理与工程价值解析
搞嵌入式开发这么多年,SPI总线绝对是我打交道最多的通信协议之一。它不像I2C那样需要复杂的地址寻址和应答机制,也不像UART那样依赖精确的波特率匹配。SPI更像是一种“简单粗暴”的高速数据管道,主设备一拉时钟线,数据就哗啦啦地流过去,特别适合对速度有要求的场景,比如驱动TFT屏幕、读写SD卡或者跟高速ADC/DAC芯片通信。它的核心魅力就在于这种极简的同步机制——主设备产生时钟,从设备跟着时钟节拍收发数据,双方共享同一个时序参考,避免了异步通信中的时钟漂移问题。
SPI的全称是Serial Peripheral Interface,中文叫串行外设接口。别看名字里有“外设”,它其实是一种点对点或多点同步串行通信的事实标准。它的物理连接通常需要四根线:SCK(Serial Clock,时钟线)、MOSI(Master Out Slave In,主出从入)、MISO(Master In Slave Out,主入从出)和SS(Slave Select,从设备选择,有时也叫CS或NSS)。有些简化版本会省掉MISO或MOSI实现半双工,或者把SS线固定拉低只接一个从设备,但四线全双工是最经典、最完整的形态。
它的工作原理,本质上就是两个移位寄存器背靠背连成了一个16位的环形移位寄存器。主设备和从设备各有一个8位移位寄存器。当主设备启动传输时,它通过SCK线发出8个时钟脉冲,每来一个脉冲,主设备的移位寄存器就向左(或向右,取决于配置)移出一位到MOSI线上,同时从MISO线上采样一位移入自己寄存器的最低位。从设备那边同步动作,只不过方向相反:它从MOSI线上采样数据移入自己的寄存器,同时将自己的寄存器内容通过MISO线移出去。8个脉冲过后,主设备寄存器里的数据就“跑”到了从设备里,而从设备的数据也“跑”到了主设备里,完成了一次数据交换。这个过程是全双工的,收发同时进行,效率很高。
为什么SPI在工程上如此受青睐?第一是速度,在短距离板级通信中,SPI可以轻松跑到几十兆赫兹,远超I2C的几百千赫兹和UART的几兆波特率。第二是灵活性,它没有复杂的协议开销,数据帧长度不固定(虽然8位最常见),传输内容完全由主设备控制,想发什么就发什么。第三是驱动简单,从软件角度看,通常就是配置几个寄存器,然后读写数据寄存器,中断或者轮询标志位即可,不涉及复杂的报文解析。当然,这种灵活性也是一把双刃剑,它没有标准的链路层协议,意味着每次换一个从设备芯片,你都得仔细研读它的数据手册,搞清楚它期待什么样的命令序列、时钟极性和相位,这也是SPI调试中最容易踩坑的地方。
2. 时钟相位与极性:SPI通信的时序灵魂
如果说SPI总线是数据的高速公路,那么时钟相位(CPHA)和时钟极性(CPOL)就是这条公路上的交通信号灯规则,规定了数据车流何时可以通行(采样),以及信号灯本身的初始状态。这两个参数的组合,直接决定了数据位和时钟边沿的对应关系,是确保主从设备能够正确解读每一位数据的关键。很多通信失败的问题,根源都出在这两个配置不匹配上。
2.1 CPOL与CPOL参数详解
我们先拆开看这两个参数。时钟极性CPOL,这个比较好理解,它定义了时钟信号SCK在空闲状态(即没有数据传输时)的电平。
- CPOL = 0:这意味着时钟空闲时为低电平。当传输开始时,时钟会从低电平跳变到高电平,产生一个上升沿,然后在高电平维持一段时间后,再跳回低电平,产生一个下降沿。你可以把它想象成一个“低电平休息,高电平活跃”的时钟。
- CPOL = 1:与上面相反,时钟空闲时为高电平。传输时,时钟先从高变低(下降沿),再从低变高(上升沿)。这是一个“高电平休息,低电平活跃”的时钟。
单纯改变CPOL,只是把整个时钟波形做了一个高低电平的翻转,就像把正弦波上下颠倒一样。它本身并不改变数据采样和时钟边沿的相对时序关系。真正决定采样时刻的是时钟相位CPHA。
时钟相位CPHA,定义了数据是在时钟的哪个边沿被采样(捕获),以及在哪个边沿被更新(输出)。这是SPI时序里最核心、也最容易混淆的概念。
- CPHA = 0:数据在时钟的第一个边沿(即第一个跳变沿)被采样,在下一个边沿(第二个跳变沿)被更新。注意,这里的“第一个边沿”是相对于时钟周期的开始而言的。如果CPOL=0(空闲低),第一个边沿就是上升沿;如果CPOL=1(空闲高),第一个边沿就是下降沿。
- CPHA = 1:与CPHA=0相反,数据在时钟的第一个边沿被更新,在第二个边沿被采样。
这么说可能还是有些抽象,我们结合CPOL,把四种模式(Mode 0, 1, 2, 3)的俗称和官方定义对应起来,这是工程实践中必须烂熟于心的:
- Mode 0 (CPOL=0, CPHA=0):时钟空闲低,数据在时钟上升沿采样,下降沿更新。这是最常见的一种模式。
- Mode 1 (CPOL=0, CPHA=1):时钟空闲低,数据在时钟下降沿采样,上升沿更新。
- Mode 2 (CPOL=1, CPHA=0):时钟空闲高,数据在时钟下降沿采样,上升沿更新。
- Mode 3 (CPOL=1, CPHA=1):时钟空闲高,数据在时钟上升沿采样,下降沿更新。
注意:不同芯片厂商的数据手册对“Mode”编号的定义可能不一致!有些文档会交换Mode 1和Mode 2的定义。最保险、最不会出错的方法,永远是直接看手册中关于CPOL和CPHA的时序图描述,而不要仅仅依赖“Mode X”这个名称。
2.2 四种传输格式的时序图解读
理解了定义,我们来看MC68HC11手册里的两张经典时序图,这几乎是所有SPI教材的范本。
CPHA=0格式(对应Mode 0和Mode 2)当CPHA=0时,SS(从设备选择)信号扮演了至关重要的角色。传输的开始不是由第一个时钟边沿定义的,而是由SS信号的下降沿(从高变低)定义的。在SS变低后,第一个时钟边沿到来之前,主设备必须将要发送的第一位数据(通常是最高位MSB)放到MOSI线上,从设备也必须将它的第一位数据放到MISO线上。然后,在第一个时钟边沿,主从设备同时采样对方的数据线(即读取数据)。在随后的第二个时钟边沿,双方更新数据线,为下一个位的传输做准备。如此循环8次。
这里有一个关键点:在CPHA=0模式下,SS信号必须在每个字节传输之间拉高(至少一个时钟周期)。因为SS的下降沿标志着传输开始,如果SS一直为低,从设备会认为这是一个超长的、未定义长度的传输,逻辑可能混乱。同时,手册特别警告,如果从设备在SS为低时尝试写SPI数据寄存器,会引发写冲突错误。
CPHA=1格式(对应Mode 1和Mode 3)当CPHA=1时,SS信号可以(也通常)一直保持低电平,特别适合单一固定主从设备的系统。传输的开始由第一个时钟边沿定义。在第一个时钟边沿,主从设备更新各自的数据线(输出数据)。紧接着,在第二个时钟边沿,双方采样对方的数据线。SS信号在整个过程中可以保持有效(低电平),用于使能从设备,而传输的边界完全由时钟周期数(8个)来界定。
模式选择实战经验在实际项目中,你几乎不需要自己去推导该用哪种模式。从设备芯片的数据手册的“SPI接口”或“串行通信”章节,一定会��确写明它支持的模式(例如,“SPI Mode 0, 3 supported”)。你的任务就是根据手册,将主控制器(MCU)的SPI配置成相同的模式。如果找不到明确说明,就找时序图,根据图中数据稳定区域和时钟边沿的关系来判断CPHA和CPOL。
一个常见的坑是,有些传感器或存储器芯片,其数据手册的时序图可能画的是CPOL=0/CPHA=0,但文字描述却写“数据在时钟下降沿锁存”,这其实是矛盾的。此时应以时序图为准,因为图是电气特性的真实反映。遇到这种歧义,最好用逻辑分析仪抓一下实际波形,这是最权威的判官。
3. MC68HC11 SPI子系统深度剖析与配置
MC68HC11(以及其衍生型号如MC68HC11A8)是摩托罗拉(后飞思卡尔,现恩智浦)经典的8位微控制器,它的SPI模块设计非常具有代表性,后来很多MCU的SPI设计都与之类似。理解它的寄存器配置和内部机制,对于掌握SPI底层原理大有裨益。
3.1 SPI相关寄存器详解
MC68HC11的SPI功能主要通过三个寄存器控制:SPI控制寄存器(SPCR)、SPI状态寄存器(SPSR)和SPI数据寄存器(SPDR)。此外,端口D的数据方向寄存器(DDRD)也至关重要,因为它控制着SPI四根引脚是作为通用IO还是SPI功能。
1. 端口D数据方向寄存器(DDRD - $1009)这是一个7位寄存器(Bit 7未使用),控制Port D每个引脚是输入(0)还是输出(1)。对于SPI相关的四个引脚(PD2/PD3/PD4/PD5),其方向控制逻辑有点特殊,需要结合SPI主从模式来理解:
| 引脚 | SPI功能 | 主模式 (MSTR=1) | 从模式 (MSTR=0) | 注意事项 |
|---|---|---|---|---|
| PD5/SS | 从设备选择 | 若DDRD5=0:作为模式错误检测输入。必须保持高电平,若被拉低则触发MODF错误。 若DDRD5=1:作为通用输出,与SPI无关。 | 固定为输入(SS从设备选择线),忽略DDRD5。 | 关键点:做主设备时,如果不使用多主模式,务必将DDRD5设为1,将其配置为通用输出并输出高电平,或直接接上拉电阻到VCC,避免意外低电平触发模式错误。 |
| PD4/SCK | 串行时钟 | 必须将DDRD4设为1,使能SCK输出。 | 固定为输入(时钟输入),忽略DDRD4。 | 主设备不使能SCK输出,时钟就发不出去。 |
| PD3/MOSI | 主出从入 | 必须将DDRD3设为1,使能MOSI输出。 | 固定为输入(数据输入),忽略DDRD3。 | 如果主设备只想接收、不想发送(比如读只读器件),可以故意不使能MOSI输出(DDRD3=0)。 |
| PD2/MISO | 主入从出 | 固定为输入(数据输入),忽略DDRD2。 | 必须将DDRD2设为1,使能MISO输出。 | 从设备不使能MISO输出,数据就无法回传给主设备。在多从机系统中,同一时刻只能有一个从设备的MISO被使能。 |
2. SPI控制寄存器(SPCR - $1028)这是SPI功能的核心配置寄存器。
- SPIE (Bit 7):SPI中断使能。1=使能,当SPIF或MODF标志置位时产生中断请求。
- SPE (Bit 6):SPI系统使能。1=开启SPI功能,相关引脚受SPI模块控制。
- DWOM (Bit 5):端口D线或模式。1=Port D所有输出引脚变为开漏输出,需外接上拉电阻。这在多主系统或非常规接线(如MISO和MOSI短接成单线)时,可以防止总线竞争导致CMOS闩锁损坏。
- MSTR (Bit 4):主/从模式选择。1=主模式,0=从模式。
- CPOL (Bit 3):时钟极性选择。定义见上文。
- CPHA (Bit 2):时钟相位选择。定义见上文。
- SPR1, SPR0 (Bits 1:0):SPI波特率选择位(仅主模式有效)。决定SCK时钟相对于内部E时钟的分频比。E时钟通常是MCU总线时钟的一半。
- 00: E / 2
- 01: E / 4
- 10: E / 16
- 11: E / 32
3. SPI状态寄存器(SPSR - $1029)这是一个只读寄存器,用于反映传输状态和错误。
- SPIF (Bit 7):SPI传输完成标志。一次传输(8位)完成后由硬件自动置1。清除方法:先读SPSR(此时SPIF=1),再访问SPDR(读或写均可)。
- WCOL (Bit 6):写冲突错误标志。当SPI传输正在进行时,如果软件试图写SPDR,此标志置1。清除方法同SPIF。
- MODF (Bit 4):模式错误标志。当SPI配置为主模式(MSTR=1)且SS引脚被外部拉低时置1。这通常意味着总线上有另一个设备试图成为主机。清除方法:先读SPSR(此时MODF=1),再写SPCR。
4. SPI数据寄存器(SPDR - $102A)这是一个特殊的寄存器。读它,你访问的是接收数据缓冲区;写它,你访问的是发送移位寄存器。它是SPI数据交换的窗口。
3.2 MC68HC11 SPI初始化与数据传输实战
假设我们要将MC68HC11配置为SPI主设备,模式为Mode 0 (CPOL=0, CPHA=0),时钟为E/4,中断方式接收数据。外接一个SPI从设备,其SS引脚连接MCU的PC0(我们用一个通用IO口软件控制)。
; 汇编示例 (MC68HC11) SPCR EQU $1028 SPSR EQU $1029 SPDR EQU $102A DDRD EQU $1009 PORTD EQU $1008 DDRC EQU $1007 PORTC EQU $1006 SPI_MASTER_INIT: ; 1. 配置SS控制线为输出高电平(假设使用PC0) LDAA #$01 STAA DDRC ; 设置PC0为输出 STAA PORTC ; 输出高电平,不选中从设备 ; 2. 配置SPI引脚方向 (Port D) LDAA #%00111000 ; 设置DDRD: Bit5(SS)=1(输出,禁用模式错误检测), ; Bit4(SCK)=1(输出), Bit3(MOSI)=1(输出), Bit2(MISO)=0(输入) STAA DDRD ; 注意:此时PD5/SS作为通用输出,但我们可以不用它,用PC0控制从设备。 ; 3. 配置SPI控制寄存器 ; SPIE=1(使能中断), SPE=1(使能SPI), DWOM=0(推挽输出), ; MSTR=1(主模式), CPOL=0, CPHA=0, SPR1:SPR0=01 (E/4) LDAA #%11010001 ; 二进制: 1 1 0 1 0 0 0 1 STAA SPCR ; 4. 清空可能的标志位(通过读SPSR,访问SPDR) LDAA SPSR LDAA SPDR RTS发送一个字节的数据(例如0xAA)并接收返回数据:
SPI_TRANSFER: ; 拉低SS线,选中从设备 BCLR PORTC, #$01 ; 清除PC0,输出低电平 ; 将待发送数据写入SPDR,启动传输 LDAA #$AA STAA SPDR ; 等待传输完成(轮询方式) WAIT_SPIF: BRCLR SPSR, #$80, WAIT_SPIF ; 等待SPIF标志置位 ; 传输完成,读取接收到的数据 LDAB SPDR ; 读取的数据在B寄存器 ; 拉高SS线,释放从设备 BSET PORTC, #$01 ; 设置PC0,输出高电平 ; 此时,发送的0xAA在A寄存器,接收的数据在B寄存器 RTS如果是中断方式,则在初始化后开启总中断,并在中断服务程序(ISR)中读取SPDR即可。
实操心得:在MC68HC11上,清除SPIF/WCOL/MODF标志的“先读SPSR,再访问SPDR/SPCR”的顺序是硬性要求,不能颠倒或只做一步。这个操作会触发内部硬件逻辑清除标志位。很多初学者调试时发现标志位“清不掉”,问题往往出在这里。
4. SPI系统错误处理与高级应用技巧
SPI通信看似简单,但在复杂的系统或多设备共享总线时,一些隐蔽的错误就会浮现。MC68HC11的SPI模块提供了两种错误检测机制:模式故障(MODF)和写冲突(WCOL)。理解并妥善处理这些错误,是构建稳健SPI系统的关键。
4.1 模式故障(MODF)错误详解与防护
模式故障是多主SPI系统中特有的错误。设想一个场景:总线上有两个MCU都可以作为主设备。当设备A作为主设备正在通信时,如果设备B也错误地配置自己为主设备并开始驱动SCK和MOSI线,就会发生总线竞争,两个推挽输出的CMOS驱动器直接对接到一起,可能产生大电流,损坏芯片。
MC68HC11的防护机制是:当自身配置为主模式(MSTR=1)且**SS引脚被配置为输入(DDRD5=0)**时,该SS引脚就充当了模式错误检测输入。一旦这个引脚被拉低(意味着另一个设备试图将它选为从设备),硬件会立即:
- 强制将DDRD中与SPI相关的位(DDRD5, DDRD4, DDRD3, DDRD2)清零,禁用所有SPI输出驱动器(变为高阻态)。
- 强制将MSTR位清零,将自己重新配置为从设备。
- 强制将SPE位清零,关闭SPI系统。
- 置位MODF状态标志,并可能产生SPI中断。
防护策略与实战建议:
- 单主系统:这是最常见的情况。务必将主设备的SS引脚(PD5)通过软件设置为输出(DDRD5=1),并输出高电平(或悬空但外部上拉)。这样彻底禁用了模式故障检测功能,避免因干扰导致误触发。你的从设备选择信号,应该使用其他普通的GPIO口来控制。
- 多主系统:需要精心设计总线仲裁逻辑。一种常见方法是,所有设备的SS引脚都连接在一起,并上拉到VCC。任何设备想成为主设备前,先尝试将自己的SS引脚配置为输出并拉低。如果它能成功拉低(说明没有其他主设备在活动),它就成为主设备;如果拉低失败(线已经被其他设备拉低),它就等待。MC68HC11的模式故障机制为这种“线与”仲裁提供了硬件支持,但软件逻辑需要自己实现。
- 开漏输出保护:在复杂或容易受干扰的系统中,可以启用DWOM位,将Port D输出设置为开漏模式。这样即使发生总线竞争,也只是将总线拉到低电平,不会产生电源到地的直通大电流。记得在每个开漏输出的线上加一个上拉电阻(通常4.7kΩ-10kΩ)。
4.2 写冲突(WCOL)错误处理
写冲突错误发生在软件试图向SPDR写入数据时,一次SPI传输正在进行中。由于MC68HC11的SPI发送器不是双缓冲的,写入SPDR的数据会直接进入发送移位寄存器。如果移位寄存器正在忙着移出数据,此时写入就会破坏本次传输。
- 对于主设备:写冲突是完全可以通过软件避免的。主设备自己发起传输,它很清楚传输何时开始(写SPDR)和何时结束(SPIF置位)。只要在写SPDR前确保SPIF为1(即上一次传输已完成),就不会发生写冲突。
- 对于从设备:写冲突是常态,需要妥善处理。从设备无法预知主设备何时发起传输。如果从设备在SS有效期间(对于CPHA=0)或SCK活动期间(对于CPHA=1)写SPDR,就会触发WCOL。从设备的正确做法是:在传输结束后(SPIF置位),立即读取接收到的数据,并准备好下一次要发送的数据,但不要立即写入SPDR。应该等到主设备下一次发起传输、SS线再次有效(CPHA=0)或SCK出现第一个边沿(CPHA=1)之后,再写入新的数据到SPDR。通常,从设备在中断服务程序中,读取旧数据后,将新数据存入一个缓存变量,等到检测到传输开始的信号(SS下降沿或SCK边沿)时,才将缓存变量写入SPDR。
错误处理代码示例:
// C语言风格示例,处理主设备发送时的潜在错误 uint8_t SPI_MasterTransfer(uint8_t data) { // 可选:检查上次传输是否完成(如果使用轮询且非阻塞调用) // while(!(SPCR & SPIF_MASK)); SPDR = data; // 启动传输 while(!(SPSR & SPIF_MASK)); // 等待传输完成 // 传输完成,检查错误标志 if (SPSR & WCOL_MASK) { // 发生了写冲突(主设备一般不应该发生) // 清除标志:读SPSR,再读SPDR uint8_t dummy = SPSR; dummy = SPDR; return 0xFF; // 返回错误值 } if (SPSR & MODF_MASK) { // 发生了模式故障(在多主系统中可能出现) // 清除标志:读SPSR,再写SPCR(通常需要重新初始化SPI) uint8_t dummy = SPSR; SPCR = SPCR; // 写回原值,或重新配置 SPI_MasterInit(); // 重新初始化SPI return 0xFE; // 返回错误值 } // 无错误,返回接收到的数据 return SPDR; }4.3 高级应用:单线双向通信与菊花链
单线双向通信:有时为了节省引脚,会将MOSI和MISO线短接,用一根数据线进行半双工通信。这时需要主从设备密切配合。主设备发送时,需使能自己的MOSI输出(DDRD3=1),同时确保从设备的MISO输出被禁用(高阻态)。主设备接收时,需禁用自己的MOSI输出(DDRD3=0),同时从设备使能MISO输出。这需要动态切换引脚方向,对时序要求较高。MC68HC11的DWOM(开漏模式)在此场景下非常有用,可以防止切换瞬间的竞争。
菊花链(Daisy-Chain):多个SPI从设备的MISO和MOSI首尾相连,形成一个大的移位寄存器。主设备发送多个字节的数据,数据像流水一样依次流过每个从设备。每个从设备在接收数据的同时,也将自己之前寄存的数据移出去。这种方式可以用一个SS线控制多个设备,但每个设备都需要支持这种“穿透”模式,并且通信协议需要设计好,让每个设备知道数据流中哪一段是属于自己的。这在驱动多个级联的LED驱动器或数字电位器时很常见。
5. 常见问题排查与调试技巧实录
调试SPI通信,逻辑分析仪是必不可少的利器。没有它,就像在黑暗中摸索。下面是我总结的SPI问题排查清单和实战技巧。
5.1 SPI通信失败排查清单
- 电源与地线:确保主从设备共地,电源稳定。这是所有通信的基础,却最容易被忽略。
- 物理连接:检查SCK、MOSI、MISO、SS四根线(或三根线)是否连接正确、牢固。线太长可能需考虑阻抗匹配。
- 从设备选择:确认SS信号有效(通常低电平选中)。用示波器或逻辑分析仪看SS线在传输期间是否被正确拉低。特别注意CPHA=0模式下,SS必须在字节间拉高。
- 时钟模式:这是最高频的故障点。确认主从设备的CPOL和CPHA设置完全一致。用逻辑分析仪抓取SCK和MOSI/MISO的波形,对照数据手册的时序图,检查数据是在正确的时钟边沿保持稳定并被采样。
- 时钟频率:主设备时钟是否过快?超过从设备支持的最大SCK频率?尝试降低SPI波特率(调整SPR1/SPR0)。
- 引脚配置:
- 主设备:SCK、MOSI是否配置为输出(DDRD4=1, DDRD3=1)?SS是否已正确处理(单主系统建议DDRD5=1)?
- 从设备:MISO是否配置为输出(DDRD2=1)?其他引脚是否配置为输入?
- SPI模块使能:SPE位是否置1?
- 数据寄存器操作:
- 主设备:是否在写入SPDR启动传输后,等待SPIF置位后才读取数据?
- 从设备:是否在传输开始后(根据CPHA模式)才将待发数据写入SPDR?是否及时读取SPDR以避免覆盖?
- 中断与标志清除:如果使用中断,是否清除了SPIF标志(读SPSR再读SPDR)?是否开启了全局中断?
5.2 逻辑分析仪使用技巧
- 连接:将分析仪的通道分别连接到SCK、MOSI、MISO、SS线上。
- 触发:设置为下降沿触发,触发源设为SS线(如果使用SS)。这样能稳定捕获到每一次传输的完整波形。
- 解码:使用分析仪的SPI解码功能。设置正确的CPOL、CPHA、位序(通常是MSB First)。解码后,数据会以十六进制或二进制形式直接显示在波形上方,一目了然。
- 分析:
- 看SS:是否在正确的时间变低/变高?脉宽是否覆盖了8个时钟周期?
- 看SCK:是否有8个脉冲?空闲电平是否符合CPOL设置?
- 看数据:MOSI和MISO上的数据是否在SCK的��样边沿(根据CPHA确定是第一个还是第二个边沿)保持稳定?解码出的数据是否符合预期?
- 对比:将抓到的波形与数据手册的时序图严格对比,包括建立时间、保持时间等参数。
5.3 MC68HC11特有陷阱
- 初始化顺序:建议先配置DDRD设置引脚方向,再配置SPCR使能SPI模块。避免使能SPI后引脚方向还是错的。
- SS引脚悬空:如果主设备的SS引脚(PD5)配置为输入(DDRD5=0)且悬空,很容易因噪声被误判为低电平,触发MODF错误,导致SPI模块被禁用。务必上拉或设置为输出。
- 标志清除的原子性:清除SPIF/WCOL/MODF标志的两步操作(读SPSR,访问SPDR/SPCR)应该是一个不可中断的原子操作。如果在两步之间发生了中断,且中断服务程序也访问了SPI,可能导致标志清除异常。在中断嵌套复杂的系统中,需要特别注意。
- 从设备响应慢:如果从设备是低速MCU或响应慢,主设备发送时钟太快,从设备可能来不及在下一个时钟边沿准备好数据。表现为MISO线上数据异常。解决方法:降低主设备SCK频率;或检查从设备程序,确保其SPI中断或轮询响应足够快。
调试SPI就像破案,波形图就是现场证据。绝大部分问题,一张清晰的逻辑分析仪截图都能找到答案。养成“先看波形,再猜原因”的习惯,能节省大量无谓的代码排查时间。最后,保持耐心,SPI的四种模式虽然容易记混,但一旦理解其本质——数据相对于时钟边沿的稳定和变化关系——就能以不变应万变,快速适配任何SPI器件。