深入解析SPI通信协议:从基础时序到PXD10 DSPI高级配置实战
1. 从基础到实战:SPI通信协议的核心原理与设计考量
搞嵌入式开发,尤其是跟各种传感器、存储芯片、显示屏打交道,SPI(Serial Peripheral Interface)这个协议你肯定绕不过去。它不像I2C那样有复杂的地址机制和应答位,也不像UART那样需要事先约定好波特率。SPI给我的感觉更像是一种“直来直去”的同步对话:主设备说“开始”,然后双方就按照一个共同的节拍交换数据,简单粗暴,但效率极高。很多新手觉得SPI简单,无非就是四根线,但真到了调试阶段,遇到数据错位、通信不稳定时,才发现里面关于时钟极性和相位的门道,以及那些微妙的时间参数,才是决定成败的关键。今天,我就结合自己这些年调试SPI设备的经验,特别是基于像Freescale(现NXP)PXD10这类微控制器上功能强大的DSPI(Deserial Serial Peripheral Interface)模块,来深挖一下SPI的“灵魂”——时序,以及如何通过高级配置让它服服帖帖地为你工作。
SPI本质上是一个基于移位寄存器的同步串行通信接口。一个典型的SPI总线包含四根信号线:
- SCK (Serial Clock): 由主设备产生的时钟信号,是所有数据收发的节拍器。
- MOSI (Master Out Slave In): 主设备数据输出,从设备数据输入。
- MISO (Master In Slave Out): 从设备数据输出,主设备数据输入。
- CS/SS (Chip Select / Slave Select): 片选信号,由主设备控制,用于选择与哪个从设备通信。通常低电平有效。
它的工作模式非常直观:主设备通过拉低对应从设备的CS线来发起通信,然后产生SCK时钟。数据在SCK的每个时钟沿,从主设备的移位寄存器通过MOSI线移出,同时从设备的数据通过MISO线移入主设备的移位寄存器。一个时钟周期完成一位数据的交换,8个或16个时钟周期后,就完成了一个字节或一个字的数据传输。这种全双工的特性意味着主设备在发送数据的同时也在接收数据,效率很高。
但SPI协议本身并没有一个严格的国际标准,这导致了不同厂商的芯片对数据采样和锁存的时刻可能有不同的要求。这就是CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)这两个参数存在的意义。它们共同定义了四种SPI模式(Mode 0-3),你需要根据从设备的数据手册来正确配置主设备,否则通信根本无法建立。
- CPOL (时钟极性): 定义SCK线在空闲状态(即CS无效,无数据传输时)的电平。
- CPOL = 0: SCK空闲时为低电平。
- CPOL = 1: SCK空闲时为高电平。
- CPHA (时钟相位): 定义数据在SCK的哪个边沿被采样(捕获),以及在哪个边沿被改变(输出)。
- CPHA = 0: 数据在SCK的第一个边沿(对于CPOL=0是上升沿,对于CPOL=1是下降沿)被采样,在相反的边沿被改变。
- CPHA = 1: 数据在SCK的第二个边沿被采样,在第一个边沿被改变。
为了更直观,我们可以把这四种模式想象成两种主要的“对话节奏”。当CPHA=0时,从设备会在SCK的第一个边沿就准备好数据(在MOSI上),主设备也在第一个边沿采样MISO上的数据。这要求CS有效到第一个SCK边沿之间有一个稳定的建立时间。而当CPHA=1时,数据的变化发生在第一个边沿,采样发生在第二个边沿,这样数据有半个时钟周期的稳定时间,对时序的要求相对宽松一些。在实际项目中,我遇到的大部分SPI Flash(如W25Q系列)常用Mode 0和Mode 3,而一些传感器可能使用Mode 1或Mode 2,所以第一件事永远是核对从设备的数据手册。
1.1 为什么时序细节如此致命?
理解了基本模式,我们再来看看那些容易被忽略但至关重要的时间参数。它们直接关系到信号在物理线路上的传播、建立和保持时间是否满足要求。在PXD10的DSPI模块手册中,你会频繁看到tCSC、tASC、tDT这些参数。
- tCSC (CS to SCK Delay): 从片选信号CS有效到第一个SCK时钟边沿开始之间的延迟。这个参数至关重要,它给了从设备一个“准备时间”。当主设备拉低CS后,从设备内部的逻辑需要时间来识别这个选择信号并准备好在数据线上进行响应。如果
tCSC太短,从设备可能还没准备好,主设备就开始发送时钟了,导致第一个甚至前几个数据位出错。手册中通常会给出一个最小值,实际配置时应留有一定余量。 - tASC (After SCK Delay): 在最后一个SCK时钟边沿之后,到CS信号被拉高(无效)之间的延迟。这个参数保证了最后一个数据位有足够的时间被从设备稳定地锁存。想象一下,如果最后一个时钟边沿一结束,CS立刻被拉高,从设备可能还没来得及完成最后一位数据的处理,导致数据传输不完整。
- tDT (Delay After Transfer): 在一次传输(一帧数据)结束,CS被拉高后,到下一次传输开始(CS再次被拉低)之间的最小空闲时间。这个参数在多字节连续读写或者与多个从设备切换时特别重要。它确保了总线有足够的时间回到空闲状态,避免了连续操作之间的信号串扰。有些器件对
tDT有明确要求,例如两次写操作之间必须等待一定时间。
这些延迟参数在简单的SPI主控中可能是固定的,但在像PXD10 DSPI这样的高级模块中,它们通常是可编程的。工程师可以通过配置DSPIx_CTARn(Clock and Transfer Attribute Register)寄存器中的PBR(Prescaler)和BR/DT(Scaler)字段来精确控制tCSC、tASC和tDT的时间长度,从而适配各种速度不同、时序要求各异的从设备。这种灵活性是高级SPI控制器价值的核心体现。
注意:在调试初期,如果通信不稳定,除了检查CPOL/CPHA,务必用逻辑分析仪或示波器抓取CS、SCK、MOSI、MISO的波形,重点测量
tCSC和tASC是否满足从设备数据手册的要求。很多时候问题就出在这里。
2. 超越标准模式:PXD10 DSPI模块的高级配置解析
很多初阶的微控制器SPI模块只支持标准的四种模式,但在处理一些“个性十足”的外设,或者需要优化通信效率、降低CPU中断负载时,标准模式可能就不够用了。Freescale/NXP的DSPI模块提供了一系列增强功能,让SPI通信变得更加可控和强大。我们结合PXD10的手册内容,重点剖析几个关键的高级特性。
2.1 修改的传输格式(MTFE)与精确的采样点控制
在标准SPI模式下,数据的采样点(对于主设备是读MISO的时刻,对于从设备是读MOSI的时刻)是固定的:要么在奇数边沿,要么在偶数边沿,由CPHA决定。但有些特殊的从设备,其数据有效窗口可能不在标准的采样边上。DSPI的修改传输格式(Modified Transfer Format, MTFE)就是为了应对这种情况。
当设置MTFE=1时,DSPI允许你更精细地控制主设备和从设备的采样点。手册中的Figure 11-16和Figure 11-17分别展示了CPHA=0和CPHA=1时,MTFE模式下的时序。
以CPHA=0, MTFE=1为例(Figure 11-16):此时,主设备对从设备数据(Slave SOUT,即MISO)的采样点被“延迟”了。它不再在第一个SCK边沿采样,而是在第三个SCK边沿才开始采样(奇数边沿),并持续在后续的奇数边沿采样。而从设备对主设备数据(Master SOUT,即MOSI)的采样则发生在偶数边沿。最后一个数据位的采样更为特殊:从设备在最后一个SCK边沿采样,而主设备则在最后一个SCK边沿之后的半个SCK周期处采样,此时SCK上已经���有可见的边沿。
这种配置有什么用呢?它主要用于匹配那些数据建立时间(Data Setup Time)和保持时间(Data Hold Time)要求比较非常规的从设备。通过将主设备的采样点推后,相当于给了从设备输出的数据更长的稳定时间,确保主设备采样时数据是绝对可靠的。关键在于,启用MTFE模式后,你必须非常仔细地分析整个SPI链路的时序预算(timing budget),确保SCK到CS的延迟(tCSC)大于或等于半个SCK周期,否则时序会乱套。这通常需要结合系统时钟频率、SCK分频系数以及从设备的时序参数进行综合计算。
2.2 连续选择格式(CONT):提升多帧传输效率
在标准SPI操作中,每传输一帧数据(比如一个8位或16位命令),CS信号都会经历“拉低->传输->拉高”的过程。如果我们需要连续发送多个字节(例如向Flash芯片写入一页数据),这种频繁的CS切换会产生大量的tCSC和tDT延迟,降低有效数据传输率。
DSPI的连续选择格式(Continuous Selection)就是为了解决这个问题。通过设置命令字中的CONT位,你可以控制CS信号在多帧传输之间的行为。
- CONT = 0 (非连续模式): 这是默认行为。每帧传输结束后,CS信号会恢复到其空闲状态(由
DSPIx_MCR寄存器中的PCSIS字段定义)。在帧与帧之间,会插入完整的tDT延迟。如图11-18所示,在两帧4位数据传输之间,CS有明显的拉高间隙。 - CONT = 1 (连续模式): 如果下一帧传输的目标从设备(即使用的PCS信号)与当前帧相同,那么CS信号将在整个多帧传输期间保持有效(拉低)。帧与帧之间没有
tDT延迟,SCK时钟可能会在帧间产生一个短暂的、不传输数据的周期(其长度为tASC + tCSC)。如图11-19所示,两帧数据背靠背传输,CS持续有效。
连续模式极大地提升了块传输的效率,特别适合大数据量的读写操作。但这里有一个重要的坑需要注意:手册明确警告,在连续选择模式下,如果在帧与帧之间切换CTAR寄存器(改变波特率、CPOL/CPHA等)或改变激活的PCS信号(切换从设备),可能会导致传输错误。正确的做法是,在切换CTAR或PCS之前,先通过设置CONT=0来结束当前连续序列,让CS信号恢复空闲,然后再配置新参数并开始新的传输序列。
2.3 时钟极性切换与连续SCK模式
另一个高级特性是帧间时钟极性切换。在某些应用场景中,你可能需要先后与两个要求不同CPOL模式的从设备通信。DSPI支持在非连续传输的帧之间切换CPOL。如图11-20所示,当一帧传输结束(CS拉高)后,SCK会在下一帧CS有效前的一个系统时钟周期(时间‘A’)改变其空闲状态电平(即切换CPOL)。而‘B’时间段(CS有效到第一个SCK边沿)则是用户可编程的tCSC延迟。这个功能省去了你在软件上先关闭SPI模块、修改配置、再重新初始化的麻烦,实现了更流畅的多设备协议切换。
对于某些需要持续时钟的从设备(例如某些类型的ADC或音频编解码器),DSPI提供了连续SCK模式(通过设置DSPIx_MCR.CONT_SCKE)。在此模式下,SCK时钟信号会持续运行,即使没有数据传输。这满足了那些依赖连续时钟进行内部操作或同步的从设备的需求。需要注意的是:
- 连续SCK模式仅支持
CPHA = 1。如果设置了CPHA=0,该设置会被忽略。 - 启用连续SCK后,
tCSC和tASC延迟被禁用,传输后延迟tDT被固定为1个SCK周期。 - 设计上要求在使用连续SCK时,所有传输使用相同的波特率。在连续SCK运行时切换
CTAR(即波特率)可能导致错误。 - 一个潜在的陷阱:如图11-22所示,在连续SCK且
CONT=1时,如果发送FIFO为空,或者DSPI进入了停止状态,SCK可能会在CS保持有效的情况下继续运行,但SOUT线被拉高。这可能导致从设备误将高电平当作数据位接收,从而读取错误数据。因此,在使用此模式时,必须确保数据流的连续性,避免FIFO下溢。
2.4 中断与DMA:解放CPU的关键
在高速或大数据量SPI通信中,如果每个字节的收发都靠CPU查询标志位或产生中断来处理,CPU负载会非常重,系统效率低下。DSPI模块提供了丰富的中断和DMA请求机制来应对这个问题。
DSPI主要有6种可以触发中断或DMA请求的条件,如表11-25所列:
- 传输队列结束(EOQF): 当执行到命令字中设置了
EOQ(End Of Queue)位的帧时,表示一个传输队列结束,可以触发中断。这常用于管理一组复杂的预定义传输序列。 - 发送FIFO非满(TFFF): 当发送FIFO(TX FIFO)未满时,可以触发中断或DMA请求,通知CPU或DMA控制器可以填充新的数据。这是实现高效流式传输的关键。
- 帧传输完成(TCF): 每一帧数据传输完成时都可以触发一个中断。适用于需要对每帧数据进行精确处理的场景。
- 发送FIFO下溢(TFUF): 仅在SPI从模式下检测。当作为从机时,TX FIFO已空但外部主机发起了传输,就会发生下溢并可能触发中断。
- 接收FIFO非空(RFDF): 当接收FIFO(RX FIFO)中有数据时,触发中断或DMA请求,通知CPU或DMA控制器来读取数据。同样是大数据接收的核心机制。
- 接收FIFO溢出(RFOF): 当RX FIFO和移位寄存器都已满,又有新数据移入时,发生溢出并可能触发中断。
其中,TFFF和RFDF可以配置为触发DMA请求。这是提升性能的“神器”。你可以设置一个DMA通道关联到TFFF事件。当TFFF标志置位(TX FIFO有空位),DMA控制器会自动从内存中搬运下一个要发送的数据块到DSPI的TX FIFO,完全不需要CPU干预。同样,RFDF事件可以触发另一个DMA通道,将RX FIFO中的数据自动搬运到内存指定区域。这样,CPU只需要在传输开始前配置好DMA描述符(包含源/目标地址、数据量等),在传输结束后处理一个完成中断即可,期间可以处理其他任务,极大地提高了系统吞吐量和实时性。
3. PXD10 DSPI模块的实战配置与寄存器详解
理论说得再多,不如动手配置一遍来得实在。下面我们就以PXD10的DSPI模块为例,一步步拆解如何配置一个稳定可靠的SPI主设备通信。我会把重点放在那些容易出错的寄存器位和配置流程上。
3.1 核心寄存器概览与初始化流程
DSPI的配置主要围绕几个核心寄存器展开:
- DSPIx_MCR (Module Configuration Register): 模块总控制寄存器。用于使能DSPI、配置为主/从模式、设置FIFO、控制连续SCK、设置CS空闲状态等。
- DSPIx_CTARn (Clock and Transfer Attributes Register): 这是SPI通信的“心脏”,每个CTAR寄存器定义了一套完整的通信参数。PXD10支持多个CTAR(CTAR0-CTAR7),可以在不同帧之间快速切换。其关键字段包括:
CPOL,CPHA: 定义SPI模式。PBR,BR: 波特率预分频器和分频器,共同决定SCK频率。fSCK = fSYS / [(PBR) * (BR)]。例如,PBR=2,BR=4,系统时钟64MHz,则fSCK = 64MHz / (2*4) = 8MHz。PCSSCK,CSSCK: 用于计算tCSC(CS到SCK延迟)。PASC,ASC: 用于计算tASC(SCK后延迟)。PDT,DT: 用���计算tDT(传输后延迟)。
- DSPIx_SR (Status Register): 状态寄存器,包含TFFF(TX FIFO非满)、RFDF(RX FIFO非空)、TCF(传输完成)、EOQF(队列结束)等标志位。
- DSPIx_RSER (DMA/Interrupt Request Select and Enable Register): 中断/DMA请求选择使能寄存器。在这里配置哪些事件(TFFF, RFDF等)能产生中断或DMA请求。
- DSPIx_PUSHR (PUSH TX FIFO Register): 写入此寄存器将数据压入TX FIFO,准备发送。其高16位是命令字(Command),包含CTAS(选择哪个CTAR)、CONT、EOQ等;低16位是数据。
- DSPIx_POPR (POP RX FIFO Register): 读取此寄存器将从RX FIFO弹出接收到的数据。
一个典型的DSPI主模式初始化流程如下:
- 时钟与引脚配置: 首先使能DSPI模块的系统时钟,并通过SIUL模块将对应的SCK、MOSI、MISO、PCSx引脚配置为DSPI功能。
- 软复位与模块配置: 向
DSPIx_MCR写入配置值。通常步骤是:设置MSTR=1(主模式),CONT_SCKE=0(禁用连续SCK,除非需要),DIS_TXF=0和DIS_RXF=0(使能TX/RX FIFO)。有时会先设置MDIS=1进入模块禁用模式进行安全配置,然后再清除。 - 配置CTAR寄存器: 根据从设备要求,计算并设置
DSPIx_CTAR0(或其他CTARn)的CPOL、CPHA、PBR、BR、PCSSCK、CSSCK、PASC、ASC、PDT、DT等字段。这是最关键的一步。 - 配置中断/DMA: 如果需要,配置
DSPIx_RSER寄存器,使能相应事件的中断或DMA请求。在中断服务程序或DMA完成回调中处理数据。 - 填充数据并启动传输: 将数据(和包含CTAS、CONT等信息的命令字)写入
DSPIx_PUSHR。一旦数据进入TX FIFO,DSPI会在CS信号有效后自动开始传输。
3.2 波特率与延迟参数的计算实例
手册中的Table 11-26和Table 11-27提供了在特定系统频率下,不同PBR、BR组合对应的波特率,以及不同PBR、DT组合对应的延迟值。但我们需要掌握其计算方法,以应对不同的系统时钟。
波特率计算: 公式为:SCK Baud Rate = fSYS / [(PBR) * (BR)]其中,PBR和BR是寄存器中编码值对应的实际分频系数。手册中PBR字段的编码00对应系数2,01对应3,10对应5,11对应7。BR字段的编码0000对应系数2,0001对应4,以此类推,最大可对应系数32768。 例如,系统时钟fSYS = 100 MHz,我们希望得到约5MHz的SCK。我们可以选择PBR=2(编码00),BR=10(编码0100,对应系数10)。计算:100MHz / (2 * 10) = 5 MHz。我们需要将00写入CTARn[PBR]位,将0100写入CTARn[BR]位。
延迟时间计算:tCSC、tASC、tDT的计算公式类似:Delay = (PBR * DT) / fSYS这里的PBR和DT也是编码值对应的实际系数。PBR的编码与波特率计算中的含义相同(2,3,5,7)。DT的编码从0000(系数2)到1111(系数65536)。 例如,fSYS = 100 MHz,需要约1us的tCSC。1us = 1000 ns。我们可以选择PBR=5(编码10),DT=50(编码0101,对应系数50?这里需要注意,手册表格中DT的编码与系数的映射可能与BR不同,需查表确认)。计算:(5 * 50) / 100MHz = 2500 ns / 100e6 = 0.025 us?显然不对。这里是一个常见的困惑点:手册Table 11-27的注释说明计算基于100MHz系统频率,且PBR的系数就是1,3,5,7,DT的系数就是第二列的值。所以更可靠的方法是直接查表。例如,需要约1us的延迟,在PBR=5那一列,找到最接近1000ns的值是102.4 us?不对,单位是ns。看表,PBR=5, DT=2048时,延迟为102.4 us,这太大了。实际上,PBR=5, DT=2时,延迟为100.0 ns。要得到1us(1000ns),需要PBR=5, DT=20,但DT的系数是离散的。我们可以选择PBR=1, DT=1024,得到10.2 us,或者PBR=3, DT=512,得到15.4 us。结论:延迟时间的可配置粒度是离散的,需要根据可用选项选择最接近目标值的配置。如果从设备要求最小tCSC为50ns,那么查表选择PBR=1, DT=2(20.0 ns)可能不满足,需要选择PBR=1, DT=4(40.0 ns)或更长的值。
实操心得:在项目初期,如果时序要求不是极端严格,可以先将
tCSC和tASC设置为较大的值(例如查表选择一个几百ns到1us的值),确保通信能建立。待通信稳定后,再根据从设备手册要求的最小值,尝试逐步减小这些延迟参数,以优化通信速度。同时,一定要用示波器验证实际波形是否符合预期。
3.3 FIFO指针管理与DMA队列切换
对于使用DMA进行大数据量传输的场景,理解FIFO的指针机制和队列切换流程至关重要。手册第11.9.1节详细描述了如何安全地切换DMA队列。
DSPI的TX FIFO和RX FIFO是循环缓冲区。TXNXTPTR指向TX FIFO中下一个将要被传输的数据位置,POPNXTPTR指向RX FIFO中下一个将被读取的数据位置。TXCTR和RXCTR则分别指示两个FIFO中当前有效数据的条目数。
当使用DMA进行连续传输时,我们通常会设置两个或多个描述符队列(比如队列A和队列B)。当队列A的数据传输完毕(通过设置命令字中的EOQ位标记),DSPI会设置EOQF状态位,并进入STOPPED状态,停止收发。此时,我们需要安全地切换到队列B。流程如下:
- 等待当前队列结束: 检测到
EOQF标志置位。 - 禁用DMA通道: 在eDMA控制器中,禁用与DSPI TX FIFO和RX FIFO关联的DMA通道的请求。防止DMA在切换过程中继续访问旧的描述符。
- 清空FIFO: 通过设置
DSPIx_MCR中的CLR_TXF和CLR_RXF位,清空TX和RX FIFO。这是一个好习惯,确保没有残留数据影响新队列。 - 更新DMA描述符: 将DMA通道的源/目标地址、数据量等指向新的队列(队列B)。
- 重置传输计数器(可选): 如果需要,可以通过命令字或直接写
DSPIx_TCR寄存器来重置传输计数器。 - 重新使能DMA通道: 在eDMA控制器中重新使能DMA通道请求。
- 清除EOQF标志,重启传输: 写1清除
DSPIx_SR中的EOQF位,这将使DSPI退出STOPPED状态,DMA会开始从新的队列(队列B)向FIFO填充数据,传输自动继续。
这个流程确保了在切换数据源或目标时,不会发生DMA错误或数据错位。关键点在于,在修改DMA描述符指针之前,必须确保DSPI和DMA都已停止对当前队列的操作(通过EOQF和禁用DMA通道),这是一个典型的“停止-修改-启动”原子操作序列。
4. 常见问题排查与调试技巧实录
即使按照手册配置,SPI通信依然可能出问题。下面分享一些我实际调试中遇到的典型问题及排查思路。
4.1 通信完全无响应或数据全错
- 症状: 逻辑分析仪上看到SCK、MOSI有波形,但MISO没反应,或者读回的数据全是0xFF或0x00。
- 排查步骤:
- 检查物理连接: 这是最基础也最容易被忽略的。确保MOSI、MISO没有接反(有些板子标记可能不清),CS线连接正确且已被主设备拉低。
- 确认电源和地: 确保从设备供电正常。
- 核对CPOL和CPHA:这是最常见的原因。用逻辑分析仪抓取CS、SCK、MOSI波形。对照从设备数据手册的时序图,第一个数据位是在SCK的第一个边沿还是第二个边沿变化?是在上升沿还是下降沿采样?据此确定正确的CPOL和CPHA。一个技巧:如果怀疑模式不对,可以尝试四种模式逐一测试(Mode 0, 1, 2, 3)。
- 检查SCK频率: 是否过高?超过从设备支持的最大频率?尝试将波特率分频到最低(如100kHz以下)进行测试。
- 检查CS时序: 测量
tCSC(CS有效到第一个SCK边沿)是否太短?尝试在CTAR中增加PCSSCK和CSSCK的值,增大tCSC。 - 检查从设备是否需特定命令唤醒: 有些SPI器件(如某些传感器)在上电后处于睡眠模式,需要先发送一个特定的“唤醒”命令才会响应。
4.2 数据错位或偶尔出错
- 症状: 通信大部分时间正常,但偶尔会读错一个字节,或��多字节传输时数据整体偏移了一位。
- 排查步骤:
- 检查
tASC和tDT: 用逻辑分析仪放大观察帧结尾。tASC(最后一个SCK边沿到CS拉高)是否太短?从设备可能没锁存最后一位。tDT(帧间CS高电平时间)是否太短?可能导致从设备内部状态未完全复位。适当增加这些延迟。 - 检查FIFO和中断/DMA配置: 如果是用中断或DMA,检查是否发生了FIFO溢出(RFOF)或下溢(TFUF)。确保中断服务程序或DMA搬运速度能跟上SPI传输速率。对于高速传输,优先使用DMA而非中断。
- 检查电源噪声和地线: 高速SPI信号对噪声敏感。确保电源滤波良好,信号线尽量短,并远离噪声源。如果布线过长,考虑在MOSI/MISO上串联一个小电阻(如22-100欧姆)以减少振铃。
- 检查多从设备总线冲突: 如果总线上有多个从设备,确保任何时候只有一个CS有效。检查是否有从设备的MISO输出使能逻辑有问题,在不被选中时未进入高阻态,导致总线冲突。
- 检查
4.3 使用高级功能(MTFE, CONT)时的问题
- 症状: 启用MTFE或CONT模式后,通信失败。
- 排查步骤:
- MTFE模式: 再次确认从设备是否真的需要这种非标准采样模式。仔细计算并测量
tCSC,确保其大于等于半个SCK周期(tCSC >= 1/(2 * fSCK))。用逻辑分析仪验证主从设备的采样点是否与预期一致。 - CONT模式: 检查在多帧连续传输中,是否无意中修改了
CTAR或切换了PCS。记住,在CONT=1的序列中不要做这些操作。如果需要改变参数,先用一帧CONT=0的传输结束当前序列。 - 连续SCK模式: 确认从设备确实需要连续时钟。检查在数据流间隙(如DMA填充延迟),SOUT线是否被意外拉高导致从设备误读。可以通过确保TX FIFO始终有数据(使用DMA乒乓缓冲)或在不需时钟时禁用连续SCK模式来避免。
- MTFE模式: 再次确认从设备是否真的需要这种非标准采样模式。仔细计算并测量
4.4 调试工具与技巧
- 逻辑分析仪是你的最佳伙伴: 投资一个带SPI协议解码功能的逻辑分析仪(如Saleae)。它能直观地显示CS、SCK、MOSI、MISO上的波形,并自动解码出十六进制或二进制数据,极大提升调试效率。重点关注CS边沿与SCK边沿的相对位置、数据变化和采样的边沿。
- 示波器看细节: 当怀疑信号质量问题时(如过冲、振铃、上升沿太慢),用示波器观察。确保信号幅值达到逻辑电平要求,边沿干净。
- 软件模拟作为最后手段: 在极端情况下,如果硬件SPI模块问题无法定位,可以尝试用GPIO模拟SPI时序(Bit-banging)。虽然慢,但可以完全控制每一个时序细节,帮助你确认是硬件配置问题还是从设备本身的问题。
- 充分利用状态寄存器: 在调试代码中,定期读取
DSPIx_SR寄存器,检查TFFF、RFDF、TCF、EOQF、TFUF、RFOF等标志位。它们能告诉你FIFO状态、传输进度和错误信息。 - 从极简配置开始: 先不要启用FIFO、DMA、MTFE等高级功能。用最简单的轮询方式,发送一个已知命令(如读器件ID),确保最基本的通信能通。然后再一步步添加FIFO、中断、DMA等功能,每加一步都进行测试。
SPI通信的稳定性建立在精准的时序控制之上。PXD10的DSPI模块提供了极其丰富的控制手段,从基本的模式选择到精细的延迟调整,再到高效的DMA传输。吃透这些配置项背后的原理,结合扎实的调试方法,就能让SPI这条“高速通道”在各种嵌入式应用中稳定可靠地运行。记住,数据手册是你的第一参考资料,而逻辑分析仪的波形则是检验配置正确与否的终极标准。多动手,多测量,那些看似复杂的时序参数,最终都会成为你手中驯服外设的得力工具。
