news 2026/7/26 15:03:05

SPI接口原理与CC27xx实战:从基础到高效配置与调试

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SPI接口原理与CC27xx实战:从基础到高效配置与调试

1. SPI接口核心原理与工作模式深度解析

SPI,全称Serial Peripheral Interface,中文常译为串行外设接口。它本质上是一种同步、全双工、基于主从架构的串行通信总线。说人话就是,它像一条双向、有节奏的数据流水线,一个“老板”(主设备)指挥着“员工”(从设备)在统一的节拍下,同时进行收发数据。这种设计让它比I2C、UART等异步协议在速度上有着先天优势,特别适合对实时性要求高、数据吞吐量大的场景,比如读写高速Flash、驱动高分辨率显示屏,或者与高速ADC/DAC进行数据交换。

它的物理连接通常只需要四根线,这也是它“简单”美誉的由来:

  • SCLK (Serial Clock):时钟信号,由主设备产生,是所有数据传输的节拍器。每个时钟脉冲对应一位数据的移入或移出。
  • CS/SS (Chip Select / Slave Select):片选信号,由主设备控制。通常低电平有效,主设备通过拉低对应从设备的CS线来“点名”它,告诉它:“接下来我要和你通话了”。这是SPI支持一主多从的关键。
  • PICO/MOSI (Peripheral In Controller Out / Master Out Slave In):主设备输出、从设备输入的数据线。数据从主设备流向从设备。
  • POCI/MISO (Peripheral Out Controller In / Master In Slave Out):从设备输出、主设备输入的数据线。数据从从设备流回主设备。

这里要特别提一下信号命名。在TI的CC27xx文档中,使用了PICO/POCI而非更常见的MOSI/MISO。这其实更精确地描述了信号在“控制器”(Controller,即主设备)和“外设”(Peripheral,即从设备)视角下的角色,避免了“主/从”可能带来的混淆。PICO就是“外设入,控制器出”,无论谁是主谁是从,这根线永远是数据进入外设、离开控制器的方向。

SPI协议的精髓,或者说最容易让人困惑的地方,在于时钟极性(CPOL, Clock Polarity)和时钟相位(CPHA, Clock Phase)的配置。这两个参数决定了时钟信号在空闲时的状态,以及数据在时钟的哪个边沿被采样(捕获)。

  • 时钟极性 (CPOL/SPO):定义SCLK在空闲时的电平。
    • CPOL = 0:空闲时SCLK为低电平。
    • CPOL = 1:空闲时SCLK为高电平。
  • 时钟相位 (CPHA/SPH):定义数据在时钟的哪个边沿被采样。
    • CPHA = 0:数据在时钟的第一个边沿(对于CPOL=0是上升沿,对于CPOL=1是下降沿)被采样。
    • CPHA = 1:数据在时钟的第二个边沿被采样。

这两者的四种组合(模式0-3)必须与从设备(如传感器、存储器)的时序要求严格匹配,否则通信必然失败。模式0(CPOL=0, CPHA=0)和模式3(CPOL=1, CPHA=1)是最常用的两种。

注意:很多初学者会在这里栽跟头。务必查阅你所用外设的数据手册,确认其要求的SPI模式。一个常见的快速判断方法是:观察数据手册的时序图,看数据线(MOSI/MISO)的变化是发生在时钟边沿之前还是之后。如果数据在时钟边沿之前就稳定了(即建立时间满足),那么采样边沿就是该时钟边沿。

除了标准的Motorola SPI格式,CC27xx的SPI模块还支持TI同步串行格式和MICROWIRE格式。TI格式的特点是CS信号会在每个数据帧传输前产生一个高脉冲,而MICROWIRE则是一种半双工协议,传输以主设备发送的一个8位控制字开始,随后从设备才返回数据,常用于一些老式的串行EEPROM。

2. CC27xx SPI模块架构与核心功能拆解

CC27xx的SPI模块不是一个简单的移位寄存器,而是一个高度集成、功能丰富的通信控制器。理解其内部架构,是进行高效、可靠配置的基础。

模块的核心可以看作由几个关键部分组成:时钟生成单元双缓冲FIFO数据传输逻辑中断与事件系统,以及可选的CRC校验单元µDMA接口。它们协同工作,将CPU从繁重的字节搬运工作中解放出来。

2.1 可编程时钟系统与速率计算

SPI的通信速率直接由SCLK的频率决定。CC27xx的SPI时钟源是CLKSVT,典型频率为48MHz。模块通过两级分频来产生最终的SCLK:

  1. 预分频器 (PRESC):位于SPI.CLKCFG0寄存器,分频系数为1到8。
  2. 串行时钟速率分频器 (SCR):位于SPI.CLKCFG1寄存器,分频值为1 + SCR,其中SCR可配置范围为0到1023。

因此,SCLK的频率计算公式非常明确:SCLK频率 = CLKSVT频率 / [PRESC × (1 + SCR)]

例如,要产生一个1MHz的SPI时钟,使用48MHz的CLKSVT。我们可以先设PRESC=4,这样得到12MHz。然后需要再分频12倍得到1MHz,即1+SCR=12,所以SCR=11。配置PRESC=4SCR=11即可。

实操心得:在满足从设备最高时钟速率的前提下,尽量选择较高的PRESC值。因为PRESC分频发生在SCR之前,更高的PRESC意味着对CLKSVT的初次分频更大,有时能获得更精确的最终时钟,减少抖动。同时,务必遵守文档中的硬性规定:CLKSVT的频率必须至少是SCLK频率的两倍。

2.2 FIFO机制与数据流管理

FIFO(先进先出)缓冲区是提升SPI通信效率的关键。CC27xx的SPI模块包含独立的TX FIFO和RX FIFO。

  • 动态宽度:这是一个非常巧妙的设计。当数据帧大小(DSS)配置为4到8位时,每个FIFO是16个位置深、8位宽。当数据帧大小配置为9到16位时,硬件会自动将FIFO重组为8个位置深、16位宽。这最大限度地利用了存储资源,无论传输8位还是16位数据,都能有效缓冲多个数据帧。
  • TX FIFO操作:CPU或µDMA将待发送的数据写入SPI.TXDATA寄存器,数据即进入TX FIFO。发送逻辑会按顺序从FIFO中取出数据,串行化后从PICO引脚发出。模块提供了“重复发送”功能(通过SPI.CTL1.REPTX配置),允许将FIFO中的最后一个数据帧自动重复发送多次,这对于需要连续发送相同命令(如清屏指令)或从某些设备读取大量数据时特别有用。
  • RX FIFO操作:从POCI引脚接收到的串行数据,经移位寄存器转换为并行数据后,被存入RX FIFO。CPU或µDMA通过读取SPI.RXDATA寄存器来从FIFO中取出数据。
  • FIFO刷新:通过设置SPI.CTL0.FIFORST位,可以原子性地将TX和RX FIFO的读写指针重置为0,实现快速清空。这里有一个至关重要的坑点:FIFO刷新操作必须在没有任何SPI事务正在进行时触发。如果在一个传输过程中执行刷新,你需要在此次传输完全结束后,再次执行一次刷新操作,才能确保FIFO指针正确归零,否则后续传输可能出错。

2.3 中断与µDMA高效协作

为了不让CPU频繁轮询FIFO状态,SPI模块提供了丰富的中断源和强大的µDMA支持。

中断源包括:

  • TX FIFO服务中断:当TX FIFO中的数据量低于设定的阈值时触发,提示CPU可以填充更多数据。
  • RX FIFO服务中断:当RX FIFO中的数据量达到设定的阈值时触发,提示CPU可以读取数据。
  • RX FIFO超时中断:在从设备模式下,如果SCLK时钟在设定时间内没有活动,而RX FIFO中仍有数据,则触发。
  • RX FIFO溢出中断:RX FIFO已满,但仍有新数据收到时触发,意味着数据丢失。
  • TX FIFO空中断:TX FIFO完全空时触发。
  • 传输完成中断(DMA完成/空闲中断)。

所有这些中断在逻辑“或”之后,产生一个总的SPI中断信号提交给系统事件 fabric。你可以通过SPI.IMASK寄存器来屏蔽不需要的中断源。

µDMA集成是实现高效数据搬运的利器。SPI模块为TX和RX路径提供了独立的DMA通道请求。

  • TX DMA:当TX FIFO有空间时,会发出DMA请求。可以配置为“单次请求”(每有一个空位就请求一次)或“突发请求”(当空位达到一定数量时请求一次),后者能减少DMA触发次数,提升总线效率。
  • RX DMA:当RX FIFO中有数据时,会发出DMA请求。同样支持单次或突发模式。

通过合理配置µDMA描述符,你可以实现“乒乓缓冲”、“循环传输”等高级数据流,让SPI在后台持续传输数KB甚至数MB的数据,而CPU仅在开始和结束时介入,极大节省了CPU资源,降低了系统功耗。

注意事项:文档中明确建议,对于TX/RX FIFO的服务,应优先使用µDMA而非CPU中断。如果不得不用CPU处理中断,务必同时使能TXEMPTY(发送完)和RXOVF(接收溢出)中断作为“安全网”。因为在某些极端情况下(如中断被长时间关闭),CPU可能错过FIFO阈值中断,此时TXEMPTY和RXOVF可以作为一个故障安全机制,防止数据丢失或发送停滞。

2.4 CRC校验保障数据完整性

在要求高可靠性的通信中(如无线固件升级、关键传感器数据读取),SPI模块内置的硬件CRC引擎是个宝藏功能。它支持CRC8-CCITT和CRC16-CCITT两种校验算法。

其工作流程是:

  • 发送端:CRC计算单元逻辑上位于SPI.TXDATA寄存器和TX FIFO之间。每次CPU写入发送数据到TXDATA时,数据既存入FIFO,也实时更新内部的SPI.TXCRC状态寄存器。当一帧或一个数据块发送完毕后,软件读取TXCRC的值,得到该数据块的CRC校验和,然后将这个校验和作为普通数据写入TXDATA发送给对方。
  • 接收端:CRC计算单元逻辑上位于RX FIFO和SPI.RXDATA寄存器之间。每次CPU从RXDATA读取接收数据时,数据既从FIFO读出,也实时更新内部的SPI.RXCRC状态寄存器。接收完数据块和发送方传来的CRC校验和后,软件可以读取RXCRC。如果传输无误,在将对方发来的CRC校验和也纳入计算后,最终的RXCRC值应为0。

重要限制:硬件CRC功能设计用于8位或16位数据帧。虽然硬件不会强制检查,但软件上应遵循:当数据帧配置为8位时,可选择CRC8或CRC16;当数据帧配置为16位时,必须选择CRC16。使用不匹配的CRC位数会导致校验失败。

3. CC27xx SPI模块配置与编程实战

理解了原理和架构,现在我们来手把手进行配置。以下是一个典型的SPI主设备(控制器)初始化流程,假设我们要以模式0(CPOL=0, CPHA=0)、2MHz速率与一个SPI Flash通信。

3.1 初始化步骤详解

  1. 引脚复用配置:这是第一步,也是最容易忽略的一步。CC27xx的引脚功能是通过I/O控制器(IOC)模块动态映射的。你需要找到SCLK、CS、PICO、POCI对应的物理GPIO引脚编号(例如DIO_12DIO_13等),然后通过配置相应的IOCFGn寄存器,将这些引脚的功能设置为SPI。具体寄存器字段请参考CC27xx的IOC章节。

    // 伪代码示例:将DIO_12,13,14,15配置为SPI引脚 HWREG(IOC_BASE + IOCFG_12) = PIN_FUNC_SPI_SCLK; HWREG(IOC_BASE + IOCFG_13) = PIN_FUNC_SPI_CS; HWREG(IOC_BASE + IOCFG_14) = PIN_FUNC_SPI_PICO; HWREG(IOC_BASE + IOCFG_15) = PIN_FUNC_SPI_POCI;
  2. 关闭SPI模块:在修改关键配置(如工作模式、帧格式)前,先确保SPI模块处于禁用状态(SPI.CTL1.EN = 0)。

  3. 配置基本参数

    • 主/从模式:设置SPI.CTL1.MS = 1,选择控制器(主)模式。
    • 数据帧大小:根据外设要求设置SPI.CTL0.DSS。例如,对于8位数据,设置为0x7(因为DSS值=帧位数-1)。
    • 帧格式:设置SPI.CTL0.FRF。对于标准Motorola SPI 4线模式,设为0x0
    • 时钟极性与相位:设置SPI.CTL0.SPOSPI.CTL0.SPH。对于模式0,两者都设为0。
    • 字节序:设置SPI.CTL1.MSB,通常设为1(MSB先发送)。
  4. 配置时钟:根据前面计算的公式,设置SPI.CLKCFG0.PRESCSPI.CLKCFG1.SCR。例如,对于48MHz源时钟生成2MHz SCLK,可以设PRESC=4(分频至12MHz),SCR=5(再分频6倍至2MHz,因为1+SCR=6)。

  5. 配置FIFO中断阈值:通过SPI.IFLS.TXSELRXSEL设置触发中断的FIFO水平。例如,设置TXSEL为1/2FIFO深度,RXSEL为1/4FIFO深度,可以在数据量适中时及时通知CPU或DMA。

  6. (可选)配置µDMA:如果使用DMA,需要配置SPI的DMA控制寄存器SPI.DMACR,使能TX和/或RX DMA请求,并设置请求类型(单次/突发)。同时,在µDMA控制器侧配置相应的通道描述符,指定源地址(发送时为内存数组,接收时为SPI.RXDATA)、目标地址(发送时为SPI.TXDATA,接收时为内存数组)、数据量等。

  7. (可选)配置CRC:如果需要,设置SPI.CTL1中与CRC相关的位(如PEN使能奇偶校验,但注意硬件CRC是常开的),并确保数据帧大小与CRC多项式选择匹配。

  8. 使能SPI模块:最后,将SPI.CTL1.EN位设为1,模块开始工作。

3.2 数据收发编程模型

配置完成后,数据的收发主要有三种模式:

1. 轮询模式: 最简单,但效率最低。CPU不断查询状态寄存器(SPI.STA)中的BUSY位或TXFE(TX FIFO空)、RXFF(RX FIFO满)等位。

// 轮询发送一个字节 void SPI_SendBytePolling(uint8_t data) { // 等待TX FIFO有空间 while (!(HWREG(SPI_BASE + SPI_STA) & STA_TXFE_MASK)) { // 空循环等待 } // 写入数据 HWREG(SPI_BASE + SPI_TXDATA) = data; // 如果需要,可以等待发送完成(BUSY位变低) // while (HWREG(SPI_BASE + SPI_STA) & STA_BUSY_MASK); }

2. 中断模式: 效率较高。配置好FIFO阈值中断后,在中断服务程序(ISR)中填充TX FIFO或读取RX FIFO。

// SPI中断服务例程(简化版) void SPI_IRQHandler(void) { uint32_t mis = HWREG(SPI_BASE + SPI_MIS); // 读取屏蔽后的中断状态 if (mis & MIS_RX_MASK) { // RX FIFO达到阈值,读取数据 while (!(HWREG(SPI_BASE + SPI_STA) & STA_RXFE_MASK)) { // 直到RX FIFO空 g_rx_buffer[rx_index++] = HWREG(SPI_BASE + SPI_RXDATA); } } if (mis & MIS_TX_MASK) { // TX FIFO低于阈值,填充数据 while (!(HWREG(SPI_BASE + SPI_STA) & STA_TXFF_MASK) && (tx_index < tx_length)) { // 直到TX FIFO满或数据发完 HWREG(SPI_BASE + SPI_TXDATA) = g_tx_buffer[tx_index++]; } } // ... 清除中断标志 }

3. µDMA模式: 效率最高,CPU干预最少。只需初始化DMA描述符,启动SPI和DMA传输,然后在DMA传输完成中断中处理即可。

// 配置µDMA描述符用于SPI发送(概念性代码) void ConfigureSPITxDMA(uint32_t *src_buffer, uint32_t size) { // 设置DMA控制结构:源地址=src_buffer,目的地址=SPI.TXDATA // 传输大小=size,源地址递增,目的地址固定,使用基本传输模式 // 使能SPI的TX DMA请求 HWREG(SPI_BASE + SPI_DMACR) |= DMACR_TXDMAE_MASK; // 启动DMA传输 }

3.3 片选(CS)与高级控制

CS信号的管理对于可靠通信至关重要。CC27xx提供了硬件CS控制功能(SPI.CTL0.HWCSN)。当使能后,在Motorola 4线模式下,硬件会自动控制CS信号,在TX FIFO中所有数据(以及可选的CRC)传输完毕之前,保持CS为低电平。这简化了软件操作,并确保了传输的原子性。

另一个高级功能是命令/数据控制(Command/Data Control),常用于驱动LCD屏等设备。通过设置SPI.CTL1.CDENCDMODE,可以利用CS线的高低电平来区分传输的是命令还是数据。例如,设置CDMODE=1,则下一次通过TXDATA写入的数据字节会在CS为低(命令模式)下发送,之后CS自动恢复为高(数据模式)。这省去了软件手动控制CS引脚电平的步骤。

4. 常见问题排查与调试技巧实录

在实际开发中,SPI通信不出数据是最常见的问题。下面是一个系统性的排查清单和我的实战心得。

问题1:完全无通信,用逻辑分析仪看不到SCLK或数据信号。

  • 排查步骤
    1. 电源与引脚:确认从设备已上电,且电压电平与CC27xx的GPIO电平(通常3.3V)兼容。
    2. 引脚配置百分之九十的问题出在这里!再次用万用表或示波器确认你配置的DIO引脚是否正确输出了SPI功能。一个快速验证方法是,将引脚先配置为GPIO输出模式,手动拉高拉低,看电平是否变化,排除硬件连接问题。
    3. SPI使能:确认SPI.CTL1.EN位已设置为1。
    4. 时钟配置:检查PRESCSCR的计算与配置是否正确。SCLK频率是否在从设备支持的范围内?用示波器测量SCLK引脚实际输出频率。
    5. 主从模式:确认SPI.CTL1.MS位设置正确(主设备设为1)。

问题2:有SCLK时钟,但数据线(PICO/POCI)上没有波形。

  • 排查步骤
    1. TX FIFO状态:在发送数据前,检查SPI.STA.TXFE位是否为1(TX FIFO空,可以写入)。写入数据后,检查SPI.STA.BUSY位是否变为1。
    2. CS信号:在4线模式下,CS信号是否被正确拉低?检查硬件连接,如果使用软件GPIO控制CS,确保时序正确(通常在传输前拉低,传输后拉高)。
    3. 数据写入:确认你是向SPI.TXDATA寄存器写入数据,而不是其他寄存器。写入的数据格式(如8位/16位)是否与DSS配置匹配?
    4. 从设备是否响应:如果是在读数据,POCI上没有波形,可能是从设备没有正确响应。检查从设备的CS、电源,以及它是否支持当前的SPI模式(CPOL, CPHA)。

问题3:能收到数据,但数据是错的(全0、全1、或错位)。

  • 排查步骤
    1. 时钟模式(CPOL/CPHA)这是最可能的原因!务必确保主从设备的CPOL和CPHA设置完全一致。用逻辑分析仪捕获时序图,对照数据手册检查数据采样边沿。
    2. 字节序(MSB/LSB):检查SPI.CTL1.MSB位设置,确保数据位的发送顺序与从设备期望的一致。
    3. 数据帧大小:确认SPI.CTL0.DSS设置的数据位数与从设备每次传输的位数一致。例如,很多16位ADC要求一次传输16位数据,如果配置成8位,就会错位。
    4. 时钟速度过快:过高的SCLK速率可能导致从设备建立/保持时间不满足,产生误码。尝试降低SCLK频率。
    5. 信号完整性:长导线、未端接的线路可能引起信号振铃或边沿退化。在高速率下,尽量缩短走线,并在必要时考虑串联端接电阻。

问题4:使用DMA时,传输不完整或卡住。

  • 排查步骤
    1. DMA使能:确认SPI.DMACR中的TXDMAE和/或RXDMAE位已使能。
    2. DMA描述符配置:仔细检查DMA源/目标地址、传输数量、地址增量模式是否正确。一个常见错误是目标地址没有设置为外设寄存器地址(如SPI.TXDATA),或者传输数量单位错误(是字节数还是字数?)。
    3. FIFO阈值与DMA请求:检查SPI.IFLS的阈值设置是否与DMA的“突发请求”配置匹配。如果FIFO阈值设得太浅,而DMA期望的突发量很大,可能导致DMA请求不触发。
    4. 中断冲突:确保SPI中断和DMA传输完成中断的优先级和清除逻辑正确,避免相互阻塞。

调试技巧实录

  1. 逻辑分析仪是你的最佳伙伴:一个支持SPI协议解码的逻辑分析仪(如Saleae)能直观地显示SCLK、CS、MOSI、MISO上的波形和解析出的数据值,一眼就能看出时序、数据是否正确,是排查SPI问题的终极利器。
  2. 寄存器打印调试法:在初始化关键步骤后和通信前后,通过调试器或串口打印关键寄存器的值(如CTL0CTL1CLKCFG0/1STA),与预期值对比。
  3. 简化测试:遇到复杂问题,先回归最简单配置。用轮询模式、最低速率、发送固定的已知数据模式(如0xAA, 0x55),排除中断、DMA、高速率等因素的干扰。
  4. 利用Loopback模式:CC27xx SPI支持内部环回测试模式(通过SPI.CTL1相关位配置)。在此模式下,发送的数据会被内部直接环回到接收端。这是验证SPI模块自身配置、驱动程序底层是否正确的最快方法,无需连接外部设备。

最后,关于CC27xx SPI模块一个特别需要注意的点是**延迟采样(Delayed Sampling)**功能。当你的PCB走线较长或负载较重,导致POCI引脚上的数据相对SCLK有较大延迟时,主设备可能在正确的时刻采样到的是上一个比特的数据。这时可以通过配置SPI.CLKCFG1.DSAMPLE字段,将采样点延迟若干个CLKSVT时钟周期。通常,在最高SPI速率下,尝试设置为1或2就能有效补偿延迟。这个功能只在控制器模式下可用,是解决高速SPI通信中数据眼图闭合问题的有效硬件手段。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/26 15:00:58

终极缠论可视化分析插件:通达信用户的量化交易革命

终极缠论可视化分析插件&#xff1a;通达信用户的量化交易革命 【免费下载链接】Indicator 通达信缠论可视化分析插件 项目地址: https://gitcode.com/gh_mirrors/ind/Indicator 缠论作为中国技术分析领域的重要理论&#xff0c;以其严谨的结构和精准的市场判断而著称。…

作者头像 李华
网站建设 2026/7/26 15:00:33

技术群组安全风险分析与安全技术交流渠道指南

最近在技术社区里&#xff0c;经常看到一些教程文章末尾附带着"有大神的宝宝们也可以看视频末的大神二维码加群哦"这样的邀请。表面上看&#xff0c;这是技术分享者与学习者建立联系的友好方式&#xff0c;但背后却隐藏着不少值得开发者警惕的风险。 作为技术从业者…

作者头像 李华
网站建设 2026/7/26 14:59:30

完全免费解锁Wand专业版功能:Wand-Enhancer终极配置指南

完全免费解锁Wand专业版功能&#xff1a;Wand-Enhancer终极配置指南 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer Wand-Enhancer是一款专为Wand&…

作者头像 李华
网站建设 2026/7/26 14:58:55

如何在3分钟内掌握misakaX:解锁iOS终极自定义的免费高效工具

如何在3分钟内掌握misakaX&#xff1a;解锁iOS终极自定义的免费高效工具 【免费下载链接】misakaX iOS /iPadOS 16.0 - 18.0 / 18.1 beta 4, An ultimate customization tool, uilitizing the bug that makes TrollRestore possible. 项目地址: https://gitcode.com/gh_mirro…

作者头像 李华
网站建设 2026/7/26 14:58:12

AI如何助力研究生开题报告:从问题定位到创新设计

1. 开题报告的本质与常见误区刚读研那会儿&#xff0c;我也以为开题报告就是个形式主义流程——直到被导师打回第五稿时才明白&#xff0c;这份文档实际是研究项目的"施工图纸"。它要解决的痛点非常明确&#xff1a;把飘在空中的灵感落地为可执行的方案。根据指导过2…

作者头像 李华