1. QSSI接口核心机制与设计思路
在嵌入式系统开发中,同步串行接口(Synchronous Serial Interface, SSI),尤其是其最普遍的实现形式SPI(Serial Peripheral Interface),是连接微控制器与传感器、存储器、显示屏等外设的“高速公路”。我接触过不少芯片的SPI模块,但像TI Tiva系列微控制器中的Quad SSI(QSSI)这样功能丰富、设计精巧的模块,确实值得深入聊聊。它不仅仅是传统SPI的简单实现,更通过引入FIFO缓冲、高级传输模式和多数据线并行等机制,将串行通信的效率和灵活性提升到了一个新的层次。理解QSSI,本质上是在理解如何平衡硬件效率与软件复杂度,以及如何针对不同应用场景选择最优的通信策略。
传统SPI通信中,一个核心痛点在于处理器核心与外设速度不匹配带来的频繁中断或轮询开销。比如,主控以50MHz运行,而SPI时钟可能只有1MHz,每传输一个字节,CPU都可能被中断或需要主动检查状态,大量时间浪费在等待和上下文切换上。QSSI模块内置的FIFO(First-In, First-Out)缓冲区,就是为解决这个问题而生的硬件“蓄水池”。它允许数据在硬件层面进行暂存和排队,让CPU可以一次性写入或读取多个数据,从而大幅减少总线占用和中断频率,这是提升系统整体响应能力和能效的关键设计。
除了基础的FIFO,QSSI真正吸引我的地方在于其“高级模式”:Bi-SSI(双线)和Quad-SSI(四线)。标准SPI是全双工,但只使用两条数据线(MOSI和MISO)。在需要极高吞吐量的场景,如驱动高分辨率显示屏或读写QSPI Flash时,两条线的带宽可能成为瓶颈。Bi-SSI和Quad-SSI模式通过将数据线扩展到2条或4条进行并行传输,理论上能在相同时钟频率下将数据吞吐量提升2倍或4倍。但这里有一个非常重要的设计取舍:在Bi-SSI和Quad-SSI模式下,通信是半双工的。这意味着同一组数据线不能同时进行收发,需要在发送和接收之间进行切换。这种设计权衡了引脚资源、硬件复杂度和带宽需求,非常典型。理解何时该用全双工的标准模式,何时该切换到半双工的高速模式,是进行硬件选型和驱动优化的基本功。
最后,帧格式的选择直接决定了你能否与目标外设“对上话”。QSSI支持Freescale SPI和TI同步串行两种主要帧格式,每种格式下还有时钟极性(SPO)和相位(SPH)的组合变化。这四种组合(CPOL/CPHA)构成了SPI的四种模式,是几乎所有SPI设备数据手册都会明确规定的。而TI同步串行格式则有其独特的帧同步脉冲。选择错误的格式或模式,通信根本无法建立。更复杂的是,在高级模式(Bi/Quad-SSI)下,帧格式的选择是受限的,这常常是调试时容易踩坑的地方。因此,深入理解每种帧格式的时序细节,并掌握在QSSI模块中正确配置它们的方法,是打通通信链路的第一步。
2. 接收FIFO的深度解析与实战要点
接收FIFO是QSSI模块数据流入的“第一站”,它的稳定工作是一切可靠通信的基础。根据文档,QSSI的接收FIFO是一个16位宽、8个位置深的缓冲区。这个“16位宽”很有意思,它意味着每个FIFO单元可以存放一个16位的数据。但在实际使用中,我们传输的数据宽度可以是4到16位(传统模式)或固定的8位(高级模式)。硬件是如何处理这个位宽差异的呢?实际上,无论你设置的数据位宽是多少,接收到的数据都会被存放到FIFO单元的低位部分,高位部分在非16位模式下通常无效或补零。CPU通过读取SSIDR(SSI数据寄存器)来消费FIFO中的数据,每读一次,就弹出一个数据项。
这里有一个至关重要的机制:FIFO满时的流控。当接收FIFO已满(即8个位置都存有数据),而此时主设备或从设备又接收到新数据时,硬件会“按住”数据,暂停时钟或通过其他方式通知发送方等待,直到FIFO中有空位为止。这个硬件流控机制避免了数据溢出丢失,对于保证通信可靠性至关重要。在软件设计时,我们需要通过查询状态寄存器(如SSISR中的RNE位)或利用中断,确保在FIFO快满或已有数据时及时读取,维持数据流的畅通。
一个特别需要注意的细节出现在主模式接收数据时。文档明确指出:“SSI only provides an SSIClk while transmitting data.” 这意味着,QSSI模块只在发送数据时才产生时钟。那么,当主机只想读取从机数据而不发送时,时钟从哪里来?解决方案是一个“哑写”(dummy write)操作。在启动接收之前,主CPU必须先向SSIDR寄存器执行一次写操作(写入的数据内容通常无关紧要,如0x00或0xFF)。这个写操作会触发QSSI模块开始生成时钟信号,从机在时钟驱动下才会将数据发送出来,并存入主机的接收FIFO。忘记这个“哑写”是新手调试SPI主机接收时最常见的错误之一,会导致时钟线毫无动静,自然也就收不到任何数据。
注意:在传统模式(Legacy Mode)下,用于高级模式的
SSInXDAT1引脚功能就是标准的SSInRX(主入从出,MISO)。硬件引脚是复用的,但功能由模式决定,配置GPIO复用功能时需对照芯片数据手册的引脚映射表,确保将引脚配置到正确的QSSI功能上。
2.1 FIFO中断与超时机制的应用策略
仅仅知道FIFO的存在还不够,高效地使用它需要借助中断机制。QSSI可以产生多种中断,与接收FIFO直接相关的有:接收FIFO服务中断(当FIFO中的数据量达到或超过半满时触发)、接收超时中断、以及接收溢出中断。
接收FIFO服务中断是最常用的。你可以设置一个阈值,例如当FIFO中数据达到4个(半满)或更多时产生中断。这样,你的中断服务程序(ISR)可以一次读取多个数据,而不是每收到一个字节就中断一次,极大地降低了CPU中断负载。配置方法是设置SSIIM(中断屏蔽)寄存器中对应的位。
接收超时(Timeout)中断是一个很实用的功能,用于处理数据流不连续的场景。它的工作原理是:一旦接收FIFO非空(RNE=1),一个32个SSIClk周期的倒计时器就开始工作。每当有新数据写入FIFO,计时器就会重置。如果长达32个时钟周期都没有新数据进来,计时器归零,就会产生超时中断。这个中断告诉你:“当前这批数据应该已经接收完了,可以来处理了”。这在接收不定长数据包时特别有用,避免了软件轮询或等待。
接收溢出中断则是一个错误指示。当接收FIFO已满,但硬件又试图写入新数据时,就会发生溢出,相应的错误标志位会被置位。如果使能了中断,也会触发。发生溢出通常意味着你的软件读取速度跟不上硬件接收速度,需要检查你的中断服务程序效率,或者考虑使用DMA来搬运数据。
在实际编程中,我的习惯是:对于高速、连续的数据流,使能接收FIFO半满中断,并配合DMA;对于低速、间歇性的数据,使用接收超时中断来判断一帧数据的结束。同时,初始化后一定会使能溢出中断,并将其ISR设计为记录错误日志并复位FIFO,这能快速定位通信异常。
3. 高级模式(Bi-SSI/Quad-SSI)的配置与半双工实战
高级模式是QSSI提升吞吐量的利器,但其配置和操作逻辑与传统SPI有显著不同,需要仔细梳理。
3.1 模式选择与核心配置寄存器
Bi-SSI和Quad-SSI模式的启用完全由SSICR1寄存器中的MODE位段控制。同时,DIR方向位决定了当前传输是发送(TX)还是接收(RX)。这是理解其半双工特性的关键:
- 发送模式(DIR=0):数据引脚被配置为输出,CPU向TX FIFO写数据,QSSI模块将数据通过多根数据线移出。在此模式下,接收(RX)FIFO被自动禁用,因为你不会收到数据。
- 接收模式(DIR=1):数据引脚被配置为输入,QSSI模块从多根数据线上采样数据存入RX FIFO。此时,你需要通过“哑写”TX FIFO来产生时钟,驱动从设备发送数据。
高级模式(Advanced SSI)则有些特殊。当MODE=0x3且DIR=0(发送)时,它和Bi/Quad-SSI的发送模式一样,禁用RX FIFO。但当DIR=1(接收)时,高级模式却可以工作在全双工状态。文档对此描述有些绕,我的理解是:MODE=0x3更像是一个“扩展模式”开关,具体的双工/半双工行为由DIR位和具体的数据引脚使用情况共同决定。对于纯粹的Bi/Quad-SSI,半双工是硬性规定。
一个必须遵守的配置铁律是:在Bi-SSI或Quad-SSI模式下,SSICR0寄存器中的DSS(数据大小选择)字段必须设置为0x7,即8位数据。这是硬件设计的要求。如果你忘记设置,QSSI模块会回退到传统模式,行为将不可预测。在8位模式下,你写入TX FIFO的数据包占据其低8位([7:0]),而高8位中的[15:13]这三个比特被用来编码本次传输的操作模式(0x1=Bi-SSI,0x2=Quad-SSI,0x3=Advanced SSI)。这意味着,你需要在软件层面组装一个16位的值写入FIFO。例如,要使用Quad-SSI模式发送数据0x5A,你需要写入TX FIFO的值是(0x2 << 13) | 0x5A,即0x405A。
3.2 帧开始与结束的控制:FSSHLDFRM与EOM位
在多字节传输中,帧同步信号SSInFss(通常作为片选CS)的行为至关重要。QSSI提供了精细的控制,通过SSICR1中的FSSHLDFRM位和TX FIFO条目中的EOM(End Of Message)位来实现。
FSSHLDFRM位控制SSInFss信号在字节间的行为:
FSSHLDFRM = 0:在每个字节传输后,SSInFss信号都会拉高(变为无效),下一个字节开始时再拉低。这适用于需要严格以字节为单位控制从设备的场景。FSSHLDFRM = 1:只要TX FIFO中还有数据,SSInFss信号就保持低电平(有效)。只有当TX FIFO完全清空,传输彻底结束时,SSInFss才拉高。这用于传输一个完整的、连续的多字节数据块。
EOM位则嵌入在TX FIFO的每个数据条目中(位12)。它标志着一个帧的结束。当硬件处理到某个TX FIFO条目,且其EOM位为1时,它会在该数据包传输完成后,将SSInFss信号拉高。这个机制允许你在一个FIFO队列里混合多个长短不一的数据帧,并通过设置EOM位来告诉硬件在哪里断帧。例如,你需要先发送一个3字节的命令帧,再发送一个10字节的数据帧。你可以将第三个字节的EOM位置1,将第十个字节的EOM位置1。这样,硬件会自动在命令帧和数据帧之间拉高一下SSInFss。
实操心得:在连续发送大量数据时,我通常将
FSSHLDFRM设为1,并只在最后一个数据的EOM位置1,让SSInFss在整个传输期间保持有效,获得最高的传输效率。而在需要与严格遵循字节使能协议的外设通信时,则设置FSSHLDFRM为0。EOM位非常强大,但要注意,它是在数据被写入TX FIFO的那个时钟周期被清除的,所以你需要为每个想标记为帧尾的数据单独设置。
3.3 模式切换的允许与禁止
文档明确指出了事务序列的组合规则,这是硬件序列器设计的约束:
- 传统SSI模式:如果配置为此模式,不建议在单次事务中切换到任何其他高级模式。
- 允许的序列:
- 高级SSI模式后接Bi-SSI模式。
- 高级SSI模式后接Quad-SSI模式。
- 高级SSI模式 -> Bi-SSI模式 -> 高级SSI模式。
- 高级SSI模式 -> Quad-SSI模式 -> 高级SSI模式。
- 不鼓励的切换:在单次事务中,不建议在Quad-SSI和Bi-SSI模式之间直接切换。
这意味着,高级SSI模式(MODE=0x3)是切换的“枢纽”或“安全模式”。如果你想从传统模式进入多线模式,或者在不同多线模式间切换,最好先经过高级SSI模式过渡。违反这些规则可能导致不可预知的引脚行为或数据错误。
4. 高速时钟模式(HSCLKEN)与性能优化
当QSSI工作在主模式时,可以启用高速时钟模式来进一步提升时序性能,这对于高时钟频率下的稳定采样尤其重要。启用该模式的方法是设置SSICR1寄存器中的HSCLKEN位。
这个模式的原理是“时钟环回”(clock loopback)。通常,主设备产生的SSInCLK输出到引脚,经过PCB走线后到达从设备,这个物理延迟会导致主设备内部采样点与从设备数据变化点之间存在偏差。在高速下,这个偏差可能吃掉宝贵的数据建立/保持时间。
开启HSCLKEN后,QSSI模块会将输出到引脚的SSInCLK信号环回内部,作为一个名为HSPEEDCLK的采样时钟。接收数据不再直接用系统时钟或分频后的时钟采样,而是用这个环回的HSPEEDCLK采样。由于HSPEEDCLK和实际到达从设备的时钟同源且路径更接近,用它来采样返回的数据(SSInRX),可以更精确地对齐时钟与数据的相位关系,相当于在内部做了时序补偿,从而允许系统运行在更高的SPI时钟频率下。
关键配置顺序:文档特别强调,为了高速模式正常工作,
HSCLKEN位必须在任何SSI数据传输开始之前设置,或者在对QSSI模块进行复位之后设置。同时,必须在设置HSCLKEN之前,确保SSICR1中的SSE(SSI使能)位已经置1。错误的顺序会导致功能异常。
5. 帧格式的深度剖析与配置指南
帧格式决定了数据位在时钟线上的排列规则,是主从设备能够正确解码彼此数据的基础。QSSI支持两种基础帧格式,由SSICR0寄存器的FRF位选择。
5.1 TI同步串行帧格式
这是一种TI特有的格式。其最大特征是:在每次数据传输开始时,SSInFss(帧同步信号)会先产生一个持续一个时钟周期的高电平脉冲,然后才开始传输数据位。在整个数据帧传输期间,SSInFss保持低电平。数据在SSInClk的上升沿移出,在下落沿被采样。
这种格式的优点是帧起始边界非常清晰,通过一个独立的脉冲来标记,抗干扰能力相对较强。它通常用于TI自家的音频编解码器等器件。在配置时需要注意,在此格式下,时钟极性(SPO)和相位(SPH)通常是固定的(根据器件手册),不像Freescale SPI那样有四种组合。
5.2 Freescale SPI帧格式
这是业界最通用的SPI格式,也是我们平时接触最多的。其核心在于时钟极性(CPOL, SPO)和时钟相位(CPHA, SPH)的四种组合(Mode 0-3)。SSInFss在此格式下通常作为低有效的片选信号(CS),在整帧数据传输期间保持有效(低电平)。
- SPO (Clock Polarity):
0:空闲时,时钟线SSInClk为低电平。1:空闲时,时钟线SSInClk为高电平。
- SPH (Clock Phase):
0:数据在时钟的第一个边沿(即SSInClk从空闲状态跳变到有效状态的边沿)被采样,在第二个边沿切换。1:数据在时钟的第二个边沿被采样,在第一个边沿切换。
这四种模式必须与从设备的数据手册要求严格匹配。一个快速记忆方法是:SPH=0时,数据在时钟边沿的“开头”采样;SPH=1时,在“中间”采样。而SPO决定了时钟空闲时的状态。
一个至关重要的限制:当使用**高级模式(Advanced/Bi-/Quad-SSI)**时,只允许使用Freescale SPI格式,且必须配置为SPO=0, SPH=0(即Mode 0)。这是硬件设计上的约束。如果你需要在高级模式下通信,必须确保你的从设备支持Mode 0。
下表总结了不同模式下的帧格式支持情况:
| 操作模式 | 支持的帧格式 | 允许的SPO/SPH配置 | 备注 |
|---|---|---|---|
| 传统模式 (Legacy) | TI格式, Freescale格式 | SPO=0/1, SPH=0/1 (四种组合) | 全功能支持 |
| 高级/Bi-/Quad-SSI模式 | 仅Freescale格式 | 仅 SPO=0, SPH=0 (Mode 0) | 硬件强制要求 |
5.3 帧格式时序图解读与关键节点
文档提供了丰富的时序图,理解它们对于调试硬件问题至关重要。我们以最常用的Freescale SPI Mode 0 (SPO=0, SPH=0) 为例,拆解其单次传输的时序:
- 空闲期:
SSInClk为低,SSInFss为高,数据线为高阻态。 - 帧开始:主机拉低
SSInFss。这使能从设备的输出。 - 第一个半时钟周期:主机将第一位数据(MSB)放到
SSInTx线上。从设备也可能同时将其第一位数据放到SSInRx线上(取决于具体器件)。 - 第一个时钟上升沿:这是数据采样边沿。主从设备在此刻采样对方数据线上的电平,即锁存输入的数据位。
- 第一个时钟下降沿:这是数据切换边沿。主从设备在此刻将各自要发送的下一位数据放到数据线上。
- 后续位传输:重复步骤4和5,直到LSB传输完毕。
- 帧结束:在最后一个位(LSB)被采样后的一个时钟周期,主机拉高
SSInFss。
在连续传输(Back-to-back)时,Mode 0的行为需要注意:如果SPH=0,有些从设备要求在字节间SSInFss有一个短暂的高电平脉冲来锁存数据。因此,即使连续发送,主机也可能需要在字节间短暂拉高SSInFss。具体行为取决于FSSHLDFRM位的设置和从设备的要求。
6. DMA集成与高效数据搬运
对于大批量数据传输,使用CPU通过中断来搬运FIFO中的数据效率太低,直接内存访问(DMA)是必选项。QSSI模块与Tiva芯片的μDMA控制器紧密集成,提供了独立的发送和接收DMA通道。
启用DMA的步骤:
- 首先,通过
RCGCSSI和RCGCGPIO等寄存器使能QSSI和对应GPIO模块的时钟,并完成引脚复用配置(这是所有QSSI操作的前提)。 - 配置μDMA控制器,为QSSI的发送和/或接收通道设置好源地址、目的地址、传输数据量等。
- 在QSSI端,通过
SSIDMACTL寄存器使能DMA通道:- 设置
RXDMAE位使能接收DMA。 - 设置
TXDMAE位使能发送DMA。
- 设置
- (可选)在
SSIIM寄存器中使能DMA完成中断(DMARXIM/DMATXIM)。
DMA请求逻辑:
- 发送通道:当发送FIFO中至少有1个空位置时,会产生单次传输请求;当有4个或以上空位置时,会产生突发(Burst)传输请求。
- 接收通道:当接收FIFO中有至少1个数据时,会产生单次传输请求;当有4个或以上数据时,会产生突发传输请求。
μDMA控制器会根据你的配置(单次或突发模式)来响应这些请求,自动在内存和QSSI FIFO之间搬运数据,完全解放CPU。
一个关键的软件处理点:发送DMA完成中断的处理。当μDMA完成从内存到TX FIFO的数据搬运后,SSIRIS寄存器中的DMATXRIS位会被置位。这个标志位不能通过简单地写SSIICR寄存器的DMATXIC位来清除。正确的清除流程是:
- 在DMA完成中断服务程序(ISR)中,首先清除
SSIDMACTL寄存器的TXDMAE位(禁用发送DMA)。 - 然后,设置
SSIICR寄存器的DMATXIC位(写1清除中断)。 - 当你需要再次启动DMA发送时,必须重新设置
TXDMAE位。
这个“先禁用再清除”的流程是为了确保在清除中断标志时,DMA通道处于确定的状态,避免残留请求导致中断标志立即被再次置起。这是一个容易忽略的细节,不按此操作会导致DMA完成中断无法被正确清除,陷入持续中断。
性能注意:文档提到,在Bi-SSI或Quad-SSI主模式下,当SSICLK频率高于系统时钟的1/6时,使用μDMA会在每个字节传输间插入等待状态。这是因为μDMA访问SRAM的仲裁延迟以及SSI输出吞吐量增加导致的。在设计高带宽应用时,需要评估此因素对实际传输速率的影响。
7. QSSI初始化、配置流程与实战示例
一份可靠的初始化代码是通信成功的基石。以下是基于文档的通用初始化步骤,我结合自己的经验补充了细节和注释:
7.1 基础初始化与配置流程
使能模块时钟:通过系统控制模块的
RCGCSSI寄存器使能目标QSSI模块(例如SSI0)的时钟。同时,通过RCGCGPIO使能连接QSSI引脚的那个GPIO端口的时钟。配置GPIO引脚复用:
- 找到数据手册的引脚复用表,确定
SSIClk,SSIFss,SSIRx,SSITx等信号对应的具体GPIO引脚(例如,PF0, PF1, PF2, PF3)。 - 设置对应GPIO引脚
AFSEL(交替功能选择)位为1。 - 在
GPIOPCTL寄存器中,配置PMCn(端口控制)字段,将QSSI功能映射到这些引脚上。 - 设置
GPIODEN位,使能引脚的数字功能。 - 强烈建议:根据情况配置上拉/下拉电阻。特别是如果
SSIClk空闲状态为高(SPO=1),务必将该引脚配置为内部上拉,以避免初始状态浮空。
- 找到数据手册的引脚复用表,确定
配置QSSI控制寄存器(关键步骤): a.确保SSE=0:如果是从复位初始化,先清除
SSICR1的SSE位,关闭模块。 b.设置主从模式: - 主模式:SSICR1 = 0x0000.0000- 从模式(输出使能):SSICR1 = 0x0000.0004- 从模式(输出禁用):SSICR1 = 0x0000.000Cc.选择时钟源:通过SSICC寄存器选择系统时钟或精确内部振荡器(PIOSC)等。 d.设置时钟分频:写入SSICPSR寄存器,设置时钟预分频器(CPSDVSR)。此值需为偶数,范围2-254。 e.配置SSICR0寄存器:这是核心配置。 -SCR(串行时钟速率):与SSICPSR共同决定最终比特率。 -SPH,SPO:选择Freescale SPI的时钟模式。 -FRF:选择帧格式(0为Freescale,1为TI)。 -DSS:数据位大小(传统模式4-16位,高级模式固定为0x7即8位)。(可选)配置DMA:如前述步骤配置μDMA和
SSIDMACTL。使能QSSI:将
SSICR1寄存器的SSE位置1,模块开始工作。
7.2 配置计算实例与代码片段
假设我们需要将QSSI0配置为主机,Freescale SPI Mode 0 (SPO=0, SPH=0),比特率1 Mbps,数据位8位,系统时钟20 MHz。
比特率计算: 公式:SSIClk = SysClk / (CPSDVSR * (1 + SCR))代入:1 MHz = 20 MHz / (CPSDVSR * (1 + SCR))为了得到整数分频,我们选择CPSDVSR = 2,则(1+SCR) = 10,所以SCR = 9。
SSICR0寄存器值计算:
DSS = 0x7(8位数据)FRF = 0x0(Freescale格式)SPO = 0,SPH = 0SCR = 0x9将这些字段组合起来(具体位域参考数据手册),假设SSICR0寄存器位[15:8]是SCR,[7:6]是SPH/SPO等,那么计算出的值可能是0x0000.09C7(具体值需根据寄存器位域掩码计算,此处为示例)。
C语言初始化代码示例(基于TI TivaWare库风格):
#include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "driverlib/ssi.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/sysctl.h" void QSSI0_Master_Init(void) { // 1. 使能外设时钟 SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // 假设SSI0在GPIO A口 // 等待外设就绪(良好习惯) while(!SysCtlPeripheralReady(SYSCTL_PERIPH_SSI0)); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA)); // 2. 配置GPIO引脚复用 // PA2 -> SSI0Clk, PA3 -> SSI0Fss, PA4 -> SSI0Rx, PA5 -> SSI0Tx GPIOPinConfigure(GPIO_PA2_SSI0CLK); GPIOPinConfigure(GPIO_PA3_SSI0FSS); GPIOPinConfigure(GPIO_PA4_SSI0RX); GPIOPinConfigure(GPIO_PA5_SSI0TX); GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5); // 3. 配置并启用SSI // 主模式, Mode 0, 1 Mbps, 系统时钟20MHz, 数据位8位 SSIConfigSetExpClk(SSI0_BASE, 20000000, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8); // 4. 使能SSI模块 SSIEnable(SSI0_BASE); }这段代码使用了TI的驱动库来简化寄存器操作。关键函数SSIConfigSetExpClk内部会计算CPSDVSR和SCR值,并配置SSICR0和SSICPSR寄存器。
7.3 高级模式配置示例
假设我们需要先以Advanced SSI模式发送2字节,再切换到Bi-SSI模式发送2字节。以下是基于直接寄存器操作的思路:
- 首先,完成上述基础初始化,并确保
DSS=8。 - 配置
SSICR1寄存器:设置MODE=0x3(Advanced SSI),FSSHLDFRM=1(帧保持),MS=0(主模式)。 - 准备发送数据到TX FIFO:
- 第一个字节(Advanced SSI模式):数据 =
(0x3 << 13) | data1。EOM位先设为0。 - 第二个字节(结束帧):数据 =
(0x3 << 13) | data2 | (1 << 12)。这里(1 << 12)即设置EOM=1,表示Advanced SSI帧结束。 - 写入这两个16位数据到
SSIDR。
- 第一个字节(Advanced SSI模式):数据 =
- 此时,硬件会自动发送这两个字节,并在第二个字节后拉高
SSInFss。 - 在
SSInFss拉高后(可通过查询状态或中断判断),无需重新初始化,直接更改SSICR1的MODE位为0x1(Bi-SSI),DIR=0(发送)。 - 准备Bi-SSI数据:
- 第三个字节(Bi-SSI模式):数据 =
(0x1 << 13) | data3。EOM=0。 - 第四个字节(结束帧):数据 =
(0x1 << 13) | data4 | (1 << 12)。 - 写入TX FIFO。
- 第三个字节(Bi-SSI模式):数据 =
- 硬件会以Bi-SSI模式发送这两个字节。
这个过程演示了如何利用FIFO中的模式位和EOM位,在单次FIFO队列中组织混合模式的多帧传输。关键在于确保模式切换符合文档允许的序列(此例中Advanced -> Bi-SSI是允许的)。