1. 项目概述为什么我们需要深入理解SPI在嵌入式系统开发尤其是工业控制、汽车电子和电机驱动领域微控制器与外围芯片如ADC、DAC、传感器、存储器、通信隔离器的通信是构建整个系统的基石。面对I2C、UART、CAN等众多协议SPISerial Peripheral Interface以其简单、高速、全双工的特性成为了短距离板级通信的“硬通货”。然而很多开发者对SPI的认知可能还停留在“四根线、主从通信”的层面一旦遇到复杂的时序要求、多从机管理、或是需要利用DMA解放CPU的场景就容易陷入调试泥潭。我最近在基于TI的TMS320F28069进行一个伺服驱动器项目时就深刻体会到了这一点。项目需要同时与多路高精度ADC、数字隔离器和EEPROM通信对SPI的吞吐率、时序稳定性和CPU占用率提出了苛刻要求。仅仅照搬参考例程结果不是数据错位就是通信效率低下频繁的中断严重影响了电流环的控制周期。这迫使我不得不放下“拿来主义”重新钻进TMS320x2806x的技术参考手册从硬件模块框图到每一个控制寄存器的位定义进行了一次彻底的“解剖”。本文正是这次“解剖”与实践的总结。我将以TMS320x2806x的SPI模块为蓝本但讨论的原理和思路适用于绝大多数MCU的SPI外设。我们不仅会回顾SPI的基础更会深入探讨那些手册里一笔带过、但在实际项目中至关重要的细节如何精准配置时钟相位与极性以适应不同器件如何利用FIFO和中断机制实现高效、稳定的数据流如何巧妙配置GPIO来模拟多片选信号以驱动多个SPI从设备以及如何开启DMA让SPI通信在后台“静默”运行彻底释放CPU资源。无论你是正在评估SPI方案还是已经深陷调试困境希望这篇结合了原理、手册解读和实战踩坑经验的总结能为你提供一条清晰的路径。2. SPI核心原理与TMS320x2806x模块架构解析2.1 SPI通信基础不止是四根线SPI的本质是一种同步、全双工、主从式的串行通信协议。其经典模型包含四根信号线SPICLK (Serial Clock): 时钟信号由主设备产生用于同步数据位传输。SPISIMO (Slave In, Master Out) / MOSI: 主设备输出、从设备输入的数据线。SPISOMI (Slave Out, Master In) / MISO: 从设备输出、主设备输入的数据线。SPISTE (Slave Transmit Enable) / SS (Slave Select): 从设备使能信号低电平有效由主设备控制。很多初学者认为SPI就是简单的“主发从收”但实际上由于是全双工数据在MOSI和MIO线上是同时进行移入和移出的。这意味着每一次传输主从双方都会交换一个数据帧通常为8位或16位。主设备在发出数据的同时也会接收到从设备的数据这个数据可能是有意义的也可能是“哑元”Dummy Data。理解这一点对于后续配置3线模式和处理接收缓冲区至关重要。2.2 TMS320x2806x SPI模块内部透视TMS320x2806x的SPI模块是一个高度集成化的数字通信外设其内部结构远不止一个简单的移位寄存器。结合技术手册中的框图我们可以将其核心组件分解如下时钟与总线接口模块通过低速外设时钟LSPCLK驱动并连接到芯片的 Peripheral Bus。系统控制块负责其时钟门控和复位而PIE外设中断扩展模块则管理其产生的中断信号SPIINT/SPIRXINT, SPITXINT。核心数据通路移位寄存器 (SPIDAT): 这是SPI的“心脏”负责在SPICLK边沿的控制下将数据逐位移出到输出引脚同时将输入引脚的数据逐位移入。它是一个16位的寄存器支持1-16位可变长度的数据帧。发送缓冲区 (SPITXBUF): 一个16位的缓冲寄存器。CPU或DMA将待发送的数据写入此处。当移位寄存器SPIDAT空闲时数据会自动从SPITXBUF加载到SPIDAT中开始发送。这个双缓冲结构使得CPU可以在当前数据正在发送时准备下一个要发送的数据从而实现连续传输。接收缓冲区 (SPIRXBUF): 同样是一个16位的缓冲寄存器。当SPIDAT完成一个完整数据帧的接收后其内容会自动传输到SPIRXBUF中供CPU或DMA读取。这避免了数据覆盖并为处理接收数据提供了时间窗口。增强型FIFO这是提升性能的关键。标准模式下SPITXBUF和SPIRXBUF都是单字16位缓冲。而FIFO模式则为其各自扩展了一个16级x16位的先进先出缓冲区。这意味着CPU可以一次性写入最多16个数据到发送FIFO或者从接收FIFO中一次性读取最多16个数据极大地减少了中断频率提升了大数据块传输的效率。控制与状态逻辑这是一组寄存器SPICTL, SPIBRR, SPICCR等用于配置工作模式主/从、时钟特性、数据格式、中断使能等并反映当前状态如发送完成、接收溢出、缓冲区满等。注意手册中特别强调了SPISTE信号的作用。在从机模式下一个高电平的SPISTE会禁止从机接收数据这可以防止因干扰产生的虚假时钟导致从机与主机失步。因此TI不建议将SPISTE引脚直接永久拉低即常有效。正确的做法是主机在需要与特定从机通信时才将该从机的SPISTE线拉低通信结束后再拉高。2.3 关键寄存器速览与功能映射理解寄存器是进行精准编程的前提。以下是几个最核心的寄存器及其关键位SPICCR (配置控制寄存器):SPICHAR (3:0): 数据字符长度位。可配置为1-16位。这是很多错误的源头务必与通信对象保持一致。CLKPOLARITY: 时钟极性。决定SPICLK空闲状态的电平0低电平1高电平。SPISWRESET: 软件复位位。写0复位整个SPI模块计数器、状态标志清零通常在初始化配置前将其清零配置完成后再置1。SPICTL (控制寄存器):MASTER_SLAVE: 主从模式选择1主机0从机。TALK: 发送使能。清零时从机的SPISOMI输出为高阻态。在多从机系统中用于确保同一时刻只有一个从机驱动数据线。CLK_PHASE: 时钟相位。决定数据在时钟的哪个边沿被采样。SPIINTENA: SPI中断使能位非FIFO模式。SPIBRR (波特率寄存器):用于主机模式下设置SPICLK的波特率。计算公式为当SPIBRR 3~127时SPI Baud Rate LSPCLK / (SPIBRR 1)当SPIBRR 0, 1, 2时SPI Baud Rate LSPCLK / 4其中LSPCLK是低速外设时钟频率需根据系统时钟和分频配置确定。SPIFFTX, SPIFFRX, SPIFFCT (FIFO相关寄存器):SPIFFENA: FIFO功能总使能位。TXFFIL, RXFFIL: 发送/接收FIFO中断触发级别。例如设置RXFFIL8则当接收FIFO中数据量大于等于8时触发接收中断。TXFFST, RXFFST: 只读位反映当前发送/接收FIFO中存有的数据字数。FFTXDLY: FIFO发送延迟。可以设置两个FIFO数据字之间的延迟时钟数用于适配低速外设。3. 系统级集成与实战配置要点3.1 GPIO引脚复用与配置陷阱在TMS320x2806x上SPI引脚与GPIO引脚是复用的。上电复位后所有引脚默认都是GPIO功能。因此使用SPI的第一步也是最容易出错的一步就是正确配置GPIO Mux复用寄存器。配置步骤选择外设功能找到对应的GPxMUXn寄存器将SPI引脚如SPISIMOA, SPISOMIA, SPICLKA, SPISTEA所在的位域设置为1使其映射到外设功能而非GPIO。配置输入限定针对输入引脚对于SPISOMI主机输入和SPICLK从机输入这类输入信号必须配置其输入限定器。手册建议对于SPI这类高速同步信号应设置为异步模式无采样窗口。这通过设置对应的GPxQSELn寄存器位为11b来实现。如果错误地配置了同步采样例如基于系统时钟采样在高速通信下极易导致数据采样错误。可选配置上拉/下拉通过GPyPUD寄存器可以控制内部上拉电阻的使能。对于开漏输出或需要确定空闲电平的场景这个配置很重要。通常为了省电和避免冲突如果外部已有上拉电阻建议禁用内部上拉。实操心得我曾遇到一个诡异的通信故障主机发送正常但从机回复的数据偶尔错位。排查了时钟、软件流程都没问题。最后发现是SPISOMIA引脚的GPIO输入限定器被错误地配置成了“带6个采样周期的同步模式”。SPI时钟频率较高这个采样窗口引入了不确定性导致在边沿附近的数据被误采样。将其改为异步模式后问题立刻消失。教训对于高速数字通信引脚输入限定器的配置绝非可有可无必须严格按照外设要求设置。3.2 中断机制深度剖析从标准模式到FIFO模式中断是处理SPI通信异步事件的核心机制。TMS320x2806x的SPI提供了灵活但稍显复杂的中断逻辑理解其演变至关重要。1. 标准非FIFO模式在此模式下SPI只有一个中断向量SPIINT在PIE中可能与SPIRXINT共用。它由两个事件触发INT_FLAGSPISTS.6当一次数据发送/接收完成时置位。这是最常用的中断源用于通知CPU“数据已就绪可以读取或发送下一个”。OVERRUN_FLAGSPISTS.7接收溢出标志。当一次传输完成但上一次接收到的数据还未来得及从SPIRXBUF中读取新数据又准备覆盖它时此位置位。这是一个错误状态意味着你漏数据了。在标准模式下你需要手动查询SPISTS寄存器来判断是哪个事件触发了中断或者分别使能SPIINTENA和OVERRUNINTENA来区分处理。2. FIFO模式启用FIFO后SPIFFENA1中断系统升级为双通道SPIRXINT专用于接收FIFO。当接收FIFO中的数据量RXFFST达到或超过你预设的触发级别RXFFIL时触发此中断。例如你设置RXFFIL4那么每收到4个数据才产生一次中断CPU可以一次性读取这4个数据中断开销降低为原来的1/4。SPITXINT专用于发送FIFO。当发送FIFO中的数据量TXFFST少于或等于你预设的触发级别TXFFIL时触发此中断。通常我们设置TXFFIL0或一个较小值这样当发送FIFO为空或快空时中断产生提醒CPU及时补充待发送数据避免发送流中断。配置流程对比表特性标准模式FIFO模式中断源单一的SPIINT独立的SPIRXINT和SPITXINT触发条件单字收发完成(INT_FLAG)或接收溢出(OVERRUN_FLAG)基于FIFO深度的可编程水位线数据缓冲单字缓冲SPITXBUF/SPIRXBUF16级深度的FIFO适用场景低速、零星数据传输高速、连续、大数据块传输CPU开销高每字一次中断低每批数据一次中断中断服务程序ISR编写要点在标准模式的SPIINTISR中首先要读取SPIRXBUF以清除INT_FLAG读取操作会自动清除该标志。然后检查OVERRUN_FLAG并处理错误。在FIFO模式的SPIRXINTISR中应使用循环语句一次性将接收FIFO中的所有数据通过RXFFST判断数量读取到内存数组中。在FIFO模式的SPITXINTISR中应检查发送FIFO剩余空间并将下一批待发送数据写入发送FIFO。关键无论哪种模式在ISR中操作FIFO或缓冲区后必须手动清除相应的中断标志如SPIFFTX.TXFFINTCLR,SPIFFRX.RXFFINTCLR否则会持续产生中断。3.3 释放CPUDMA与SPI的联动配置当SPI需要搬运的数据量非常大时例如通过SPI向LCD屏刷新一帧图像即使使用FIFO频繁的中断仍然会消耗可观的CPU时间。此时DMA直接存储器访问是终极解决方案。DMA控制器可以在不打扰CPU的情况下自动在SPI数据寄存器和内存之间搬运数据。TMS320x2806x的SPI模块可以产生两个DMA触发事件SPITXDMA当发送FIFO状态TXFFST小于等于触发级别TXFFIL时触发。这通常意味着发送FIFO有空位DMA可以搬送新数据填入。SPIRXDMA当接收FIFO状态RXFFST大于等于触发级别RXFFIL时触发。这通常意味着接收FIFO有数据DMA可以将其搬走。配置DMA-SPI联动的基本步骤使能SPI FIFODMA触发依赖于FIFO功能因此必须先设置SPIFFENA1。配置SPI FIFO触发级别合理设置TXFFIL和RXFFIL。例如对于发送DMA可以设置TXFFIL0这样发送FIFO一有空位就立即请求DMA对于接收DMA可以设置RXFFIL8等收到8个数据再让DMA一次性搬走。配置DMA通道将DMA通道的触发源TRIGSRC配置为SPITXDMA或SPIRXDMA。设置源/目标地址对于发送源地址是内存中的数组目标地址是SPI的发送数据寄存器实际上是FIFO对于接收源地址是SPI的接收数据寄存器目标地址是内存中的数组。设置传输数据量BURST_SIZE,TRANSFER_SIZE。配置传输完成中断以便在DMA完成一整块数据搬运后通知CPU进行后续处理。启动传输使能DMA通道并在SPI端启动传输例如主机模式下向SPITXBUF写入第一个数据或使能DMA自动触发。注意DMA的引入增加了系统的复杂性。要特别注意内存中数据缓冲区的对齐问题16位访问、DMA与CPU对共享数据区的访问冲突通常需要关闭中断或使用双缓冲以及DMA传输完成事件与SPI实际传输完成的同步问题。在调试时可以先使用FIFO中断模式验证数据流正确再引入DMA。4. 核心操作模式与时钟配置详解4.1 主从模式切换与数据流控制主机模式MASTER_SLAVE 1 主机掌控通信的节奏。它负责生成SPICLK并在SPISTE信号有效后启动数据传输。数据从SPISIMO引脚移出同时从SPISOMI引脚移入。主机的SPIBRR寄存器决定了通信波特率。一个关键细节在主机模式下向SPIDAT或SPITXBUF写入数据会立即启动传输如果移位寄存器空闲。传输完成后接收到的数据会自动存入SPIRXBUF并置位INT_FLAG。从机模式MASTER_SLAVE 0 从机被动响应。它从SPICLK引脚接收主机提供的时钟数据从SPISIMO引脚输入从SPISOMI引脚输出。从机的波特率由外部时钟决定但最高不能超过LSPCLK/4。从机模式下的一个易错点从机必须在主机发起时钟之前就将要发送的据写入SPITXBUF进而加载到SPIDAT。如果写晚了从机发送的将是无效数据。TALK位控制从机的SPISOMI输出使能用于多从机总线管理。多从机连接与GPIO模拟SPISTE 一个SPI主机模块通常只提供一个SPISTE输出。要连接多个SPI从设备标准做法是使用多个GPIO引脚来模拟片选信号。配置步骤如下将主机的SPISIMO,SPISOMI,SPICLK与所有从机的对应引脚并联。将每个从机的SPISTE引脚连接到一个独立的、配置为输出模式的GPIO引脚。在软件中在需要与某个从机通信前将该从机对应的GPIO片选引脚拉低有效其他所有GPIO片选引脚拉高无效。进行SPI数据传输。传输完成后将该GPIO片选引脚拉高。这种方法完全由软件管理片选时序非常灵活。但要注意GPIO操作的速度确保在改变片选状态时SPI时钟处于空闲状态避免产生错误的时钟边沿。4.2 时钟相位与极性破解设备兼容性的密码时钟相位CLK_PHASE和极性CLKPOLARITY的组合定义了SPI的四种工作时序模式Mode 0-3。这是SPI配置中最容易混淆的部分也是导致与不同厂家芯片通信失败的首要原因。时钟极性 (CPOL/CKP)定义SPICLK在空闲时的状态。CLKPOLARITY 0: 时钟空闲时为低电平。CLKPOLARITY 1: 时钟空闲时为高电平。时钟相位 (CPHA)定义数据在时钟的哪个边沿被采样捕获。CLK_PHASE 0: 数据在第一个时钟边沿即空闲状态后的第一个跳变沿被采样。CLK_PHASE 1: 数据在第二个时钟边沿被采样。四种模式详解模式CLKPOLARITY (CPOL)CLK_PHASE (CPHA)空闲时钟数据采样沿数据变化沿Mode 000低电平上升沿下降沿Mode 101低电平下降沿上升沿Mode 210高电平下降沿上升沿Mode 311高电平上升沿下降沿如何确定永远以从设备的数据手册为准从设备的手册会明确说明其支持的SPI模式。主设备的配置必须与之严格匹配。一个快速记忆方法是观察从设备数据手册上的时序图看数据线如MOSI在时钟的哪个边沿是稳定的即采样边沿在哪个边沿是允许变化的即输出边沿。主机配置应保证在从机采样的边沿数据是稳定的。实测技巧如果手头没有逻辑分析仪调试时序问题会非常痛苦。强烈建议投资一个基础的逻辑分析仪甚至一些示波器也带串行协议解码功能。用它同时抓取SPICLK、MOSI、MISO三根线的波形可以一目了然地看到数据在哪个时钟边沿被采样是否满足从设备的要求是排查通信问题最直接的手段。4.3 波特率计算与时钟对称性主机模式下波特率由LSPCLK和SPIBRR共同决定。计算公式前面已经给出。这里需要关注一个细节时钟对称性。当(SPIBRR 1)为偶数时产生的SPICLK高低电平占空比是完美的50%对称。 当(SPIBRR 1)为奇数且SPIBRR 3时SPICLK将变得不对称。具体表现为如果CLKPOLARITY 0空闲低则低电平脉冲比高电平脉冲多一个LSPCLK周期。如果CLKPOLARITY 1空闲高则高电平脉冲比低电平脉冲多一个LSPCLK周期。这对通信有影响吗对于绝大多数SPI从设备只要数据建立时间和保持时间满足要求时钟不对称并不影响通信。但是对于一些对时钟占空比非常敏感的高速器件或者某些依赖于精确时钟计数的特殊协议如某些音频Codec可能需要关注这一点。在要求严格对称时钟的场合应选择使(SPIBRR 1)为偶数的分频值。4.4 3线制SPI模式节省一个引脚的技巧标准SPI需要4根线。为了节省引脚TMS320x2806x支持3线模式通过设置SPIPRI.TRIWIRE1启用。在此模式下主机SPISIMO引脚变为双向的SPIMOMI引脚SPISOMI引脚不再被SPI模块使用可复用为GPIO。从机SPISOMI引脚变为双向的SPISISO引脚SPISIMO引脚不再被使用。工作原理在3线模式下发送和接收路径在内部短接。这意味着主机发送的数据也会被自己接收回来。因此在每次发送操作后必须执行一次“哑读”Dummy Read来清除接收缓冲区中的这个“回音”数据。关键控制位TALK当TALK1时SPI模块驱动数据线处于发送状态。当TALK0时SPI模块释放数据线输出高阻处于接收状态。3线模式主机读取从机数据的流程这是一个经典且容易出错的流程主机设置TALK0关闭自身驱动准备接收。主机向SPITXBUF写入一个任意数据哑元。注意由于TALK0这个数据不会被发送到引脚上但写入操作会启动SPI时钟生成。主机产生的SPICLK会触发从机发送数据。从机数据通过双向数据线传回主机。主机等待接收完成标志然后从SPIRXBUF中读取的就是从机发来的真实数据而不是自己写的哑元。注意事项3线模式是半双工的不能同时收发。它适用于那些只需要单向传输或交替收发的场景比如读取一个传感器先发命令字再读数据字。在切换TALK状态时要确保当前传输已经完全结束避免数据冲突。5. 从零开始的SPI配置与调试实战5.1 初始化流程与最佳实践一个健壮的SPI初始化流程应遵循以下步骤特别是要利用好SPISWRESET位置位软件复位将SPICCR.SPISWRESET清零。这将使SPI模块进入复位状态所有状态机、计数器、标志位被清零。在复位状态下进行配置是安全的。配置GPIO复用按照3.1节所述配置相关引脚为SPI功能并设置正确的输入限定模式。配置SPI工作参数SPICCR.SPICHAR: 设置数据位长度如0xF表示16位。SPICCR.CLKPOLARITY和SPICTL.CLK_PHASE: 根据从设备要求设置时钟模式。SPICTL.MASTER_SLAVE: 设置主从模式。SPIBRR: 根据LSPCLK频率和期望波特率计算并设置。SPICTL.TALK: 从机模式下通常初始化为0禁用发送等待主机片选后再使能。可选配置FIFO设置SPIFFTX.SPIFFENA 1使能FIFO。清除FIFO复位位SPIFFTX.TXFIFO 1然后 0SPIFFRX.RXFIFO 1然后 0。设置FIFO中断触发级别SPIFFTX.TXFFIL和SPIFFRX.RXFFIL。设置FIFO发送延迟SPIFFCT.FFTXDLY通常设为0以实现背靠背传输。释放SPI FIFO通道复位SPIFFTX.SPIRST 1。清除状态标志读取SPIRXBUF以清除可能存在的旧数据并检查SPISTS寄存器清除OVERRUN_FLAG和INT_FLAG通过读取SPIRXBUF清除后者。配置中断非FIFO模式使能SPICTL.SPIINTENA和/或SPICTL.OVERRUNINTENA。FIFO模式使能SPIFFTX.TXFFIENA和SPIFFRX.RXFFIENA。在PIE向量表中配置对应的中断服务程序入口。释放软件复位将SPICCR.SPISWRESET置1。此时SPI模块按照新的配置开始运行。主机模式启动传输向SPITXBUF写入第一个数据。重要警告手册中明确提到“Do not change the SPI configuration when communication is in progress.” 绝对不要在通信过程中即SPIDAT正在移位或有数据在缓冲区中动态修改配置寄存器如波特率、时钟模式、数据长度等。这会导致不可预测的行为和通信失败。任何配置变更都应在SPISWRESET0的复位状态下进行。5.2 数据格式处理左对齐与右对齐的玄机当数据字符长度小于16位时通过SPICHAR设置数据的存放位置需要特别注意否则读到的数据会是错乱的。写入时SPIDAT/SPITXBUF数据必须左对齐。也就是说你要发送的最高有效位MSB应该放在16位寄存器的最高位。例如要发送一个8位数据0xAB你应该将其左移8位写入0xAB00。读取时SPIRXBUF数据是右对齐的。接收到的有效数据位位于寄存器的低SPICHAR位。例如接收一个8位数据SPIRXBUF中的值可能是0x00CD其中0xCD就是你需要的8位数据。为什么这样设计这与SPI硬件移位寄存器的工作方式有关。移位寄存器总是从MSB开始移出。当帧长小于16位时硬件需要知道从哪个位置开始移出数据左对齐写入确保了MSB在正确位置以及接收完成后如何将不满16位的数据对齐到缓冲器中右对齐读取方便软件直接使用。操作示例假设配置为8位数据模式SPICHAR 0x7。// 发送数据 0xA5 SpiaRegs.SPITXBUF 0xA5 8; // 左移8位写入0xA500 // 等待发送完成/接收完成 while(SpiaRegs.SPISTS.bit.INT_FLAG ! 1) {} // 读取接收到的数据 Uint16 receivedRaw SpiaRegs.SPIRXBUF; // 假设收到 0x00B6 Uint8 receivedData (Uint8)(receivedRaw 0x00FF); // 取低8位得到 0xB65.3 常见问题排查与调试技巧实录在实际项目中SPI通信失败的原因多种多样。以下是一个基于我个人经验的排查清单按照从简单到复杂的顺序进行电源与物理连接检查所有设备供电是否正常地线是否共地且连接良好线缆是否过长或接触不良这是所有通信问题的第一步。时钟与数据线静默状态现象通信完全无反应。排查用示波器或逻辑分析仪测量SPICLK、MOSI、MISO、SS线。主机初始化后在不发起传输时SPICLK和MOSI应该保持稳定的空闲电平由CLKPOLARITY决定SS线应保持高电平无效。如果MOSI或MISO上有杂乱的脉冲可能是GPIO配置错误未正确设置为SPI功能或软件意外操作了GPIO数据寄存器。片选信号SPISTE现象从机无响应但主机有时钟和数据输出。排查确认主机的片选信号无论是硬件SPISTE还是GPIO模拟在传输期间是否有效低电平。测量其下降沿是否发生在SPICLK第一个边沿之前上升沿是否发生在最后一个时钟边沿之后。确保片选信号没有毛刺。时钟模式CPOL/CPHA不匹配现象能抓到时钟和数据波形但读取的数据全是0xFF、0x00或随机值。排查这是最常见的问题。使用逻辑分析仪对照从设备数据手册的时序图逐一检查时钟空闲电平、数据采样边沿、数据变化边沿是否完全匹配。务必以从机时序为准调整主机配置。波特率过高现象低速时通信正常提高波特率后出错。排查检查主机设置的波特率是否超过从设备支持的最大速率。同时检查LSPCLK的时钟配置是否正确。SPI模块的最高时钟不能超过LSPCLK/4。确保PCB布线没有过长的走线或严重的反射高速信号对信号完整性要求更高。中断与FIFO配置错误现象只能收发一次数据或收发的数据量不对。排查标准模式在中断服务程序中是否读取了SPIRXBUF来清除INT_FLAG是否处理了OVERRUN_FLAGFIFO模式是否使能了SPIFFENAFIFO复位位TXFIFO/RXFIFO是否在初始化时经过了“置1再清0”的复位流程中断触发级别TXFFIL/RXFFIL设置是否合理在ISR中是否清除了TXFFINT或RXFFINT标志通用PIE中断使能、全局中断使能是否打开中断向量表配置是否正确多从机总线冲突现象多个从机时数据互相干扰。排查确保在任何时刻只有一个从机的TALK位为1输出使能。使用GPIO模拟片选时确保在切换片选前将即将变为无效的从机的TALK位清零再将即将有效的从机的TALK位置1。片选信号切换期间SPICLK应保持空闲状态。3线模式数据错乱现象在3线模式下主机读取的数据是自己发送的哑元。排查严格按照4.4节所述的流程操作。最关键的一步在主机发起“读”操作之前必须先将TALK位清零然后再写入哑元启动时钟。如果TALK位为1时写入哑元数据会被发送到总线上并且被自己接收覆盖掉从机的回复。调试利器没有逻辑分析仪调试SPI就像蒙着眼睛走路。一个便宜的USB逻辑分析仪配合Sigrok/PulseView软件能直观显示四路信号的波形、解码出十六进制数据、测量时序参数是定位SPI问题的终极神器。在初始化后先发送一组固定的已知数据如0xAA,0x55,0x01,0x02...用逻辑分析仪抓取波形比对发送和接收的数据能快速将问题定位到硬件连接、时序配置或软件流程中的某一个环节。