详解TI DSP McBSP配置SPI模式:寄存器设置与实战代码
2026/7/21 21:47:37 网站建设 项目流程

1. McBSP配置SPI模式的核心思路与寄存器概览

在嵌入式开发里,SPI(串行外设接口)是连接传感器、存储芯片、显示屏等外设的“老熟人”。它简单、高效,一个主设备带着几个从设备就能跑起来。但当你手头的处理器是德州仪器(TI)的TMS320系列DSP,特别是需要用到其内置的McBSP(多通道缓冲串行端口)来模拟SPI时,事情就变得有点“硬核”了。McBSP本身是个功能强大的通用同步串行口,要让它乖乖扮演SPI的角色,就得通过一系列寄存器进行“角色扮演”式的精细配置。这不像直接用硬件SPI模块那样简单,但一旦掌握,灵活性极高。

为什么用McBSP模拟SPI?有时候芯片自带的硬件SPI接口数量不够,或者引脚被其他功能占用了,而McBSP通常有富余。更重要的是,McBSP的时钟和帧同步信号高度可配,能适应各种非标准的SPI时序要求。不过,它的配置寄存器多,位域复杂,稍有不慎通信就会失败。核心思路就是通过设置特定的控制位,让McBSP的时钟工作在“停止模式”,并正确分配引脚功能,使其行为符合SPI协议的四线制(CLK, MOSI, MISO, CS)或三线制要求。

整个配置围绕着几个关键寄存器展开:

  • SPCR1 (Serial Port Control Register 1)SPCR2:这是总开关,负责复位、使能整个串口、接收器、发送器和采样率发生器,并启用关键的“时钟停止模式”。
  • PCR (Pin Control Register):决定McBSP相关引脚(CLKX, CLKR, FSX, FSR, DX, DR)是作为串口功能还是通用IO。
  • RCR1/RCR2 (Receive Control Registers)XCR1/XCR2 (Transmit Control Registers):定义数据帧的格式,比如字长、帧长、数据延迟等。在SPI模式下,帧通常很简单。
  • SRGR1/SRGR2 (Sample Rate Generator Registers):当McBSP作为SPI主设备时,用来生成内部时钟(CLKG),进而产生SPI时钟(SCLK)。

配置的核心是理解McBSP如何映射到SPI的四根线上:

  • 主设备模式:McBSP的CLKX引脚输出时钟(SPI SCLK),DX引脚输出主出从入数据(SPI MOSI),DR引脚接收主入从出数据(SPI MISO),FSX引脚可配置为输出片选信号(SPI CS/NSS)。
  • 从设备模式:McBSP的CLKX引脚变为输入,接收外部主设备提供的时钟(SPI SCLK),DR引脚接收主出从入数据(SPI MOSI),DX引脚输出主入从出数据(SPI MISO),FSX引脚作为输入,接收外部片选信号(SPI CS/NSS)。

接下来,我们就深入寄存器,看看如何一步步完成这个“角色扮演”。

2. 关键寄存器位详解与配置逻辑

配置McBSP为SPI模式,不是简单地填几个值,而是要理解每个关键位背后的物理意义和时序影响。这里我们把官方手册里的表格打散,结合实操逻辑重新梳理。

2.1 时钟停止模式:SPI的基石

SPI通信的特点是,时钟只在数据传输期间有效,数据间隙时钟线保持固定电平(高或低)。这与McBSP默认的连续时钟模式不同。因此,首要任务就是启用“时钟停止模式”。

  • CLKSTP (SPCR1[12:11]):这是SPI模式的“总闸”。

    • 00b01b:禁用时钟停止模式,用于非SPI通信。
    • 10b:启用时钟停止模式,无时钟延迟。这是最常用的SPI模式之一。
    • 11b:启用时钟停止模式,有时钟延迟。用于某些需要时钟相位偏移的SPI模式。
    • 为什么必须设置?此模式使McBSP的时钟行为符合SPI协议,在数据包间停止时钟,并在内部将接收时钟(MCLKR)与发送时钟(MCLKX)连接起来,这对于SPI全双工通信至关重要。
  • CLKXP (PCR[1]) 和 CLKRP (PCR[0]):这对兄弟决定了时钟极性和采样边沿,直接对应SPI的CPOL和CPHA。

    • CLKXP:控制CLKX引脚上的时钟极性。
      • 0:时钟空闲时为低电平,第一个跳变沿为上升沿。
      • 1:时钟空闲时为高电平,第一个跳变沿为下降沿。
    • CLKRP:控制数据在MCLKR引脚上的采样边沿。注意,在时钟停止模式下,MCLKR在内部与MCLKX相连。
      • 0:在MCLKR的下降沿采样接收数据(DR)。
      • 1:在MCLKR的上升沿采样接收数据(DR)。
    • 组合与SPI模式的关系
      • CLKSTP=10b, CLKXP=0, CLKRP=0:SPI模式0 (CPOL=0, CPHA=0)。时钟空闲低,数据在第一个边沿(上升沿)采样。
      • CLKSTP=11b, CLKXP=0, CLKRP=1:SPI模式1 (CPOL=0, CPHA=1)。时钟空闲低,数据在第二个边沿(下降沿)采样。
      • CLKSTP=10b, CLKXP=1, CLKRP=0:SPI模式2 (CPOL=1, CPHA=0)。时钟空闲高,数据在第一个边沿(下降沿)采样。
      • CLKSTP=11b, CLKXP=1, CLKRP=1:SPI模式3 (CPOL=1, CPHA=1)。时钟空闲高,数据在第二个边沿(上升沿)采样。
    • 实操心得:一定要先确认你的SPI从设备(如传感器、Flash芯片)支持哪种模式,然后据此配置CLKXP和CLKRP。最常见的组合是模式0和模式3。CLKSTP选择10b还是11b,决定了是否有那半个时钟周期的延迟,这对应CPHA是0还是1。

2.2 主从模式的核心区别:谁控制时钟和片选

主设备和从设备的配置差异,主要体现在时钟和帧同步(在SPI中用作片选)信号的方向上。

  • CLKXM (PCR[2]):时钟方向控制位。

    • 主模式:必须设为1。这意味着CLKX引脚为输出,由内部的采样率发生器驱动。主设备要主动产生时钟。
    • 从模式:必须设为0。这意味着CLKX引脚为输入,接收外部主设备提供的时钟。
    • 为什么这样设置?这定义了数据收发的基准。主设备提供时钟,所有从设备以此为准进行同步。
  • FSXM (PCR[3]):帧同步(FSX)方向控制位。在SPI语境下,FSX通常作为片选(CS/SS)信号。

    • 主模式:通常设为1。FSX引脚为输出,由McBSP内部产生,用于选择从设备。
    • 从模式:必须设为0。FSX引脚为输入,接收外部主设备发来的片选信号。
    • 注意:主模式下,你也可以将FSXM设为0,然后用一个普通的GPIO口来手动控制片选,这在需要精细控制片选时序时更灵活。
  • FSGM (SRGR2[11]):帧同步生成模式。此位仅在主模式下且FSXM=1时需要考虑

    • 0:每次数据从DXR1传输到XSR1时,发送器都会在FSX引脚上产生一个帧同步脉冲。这对于SPI主设备非常合适,因为它意味着每次启动传输都会自动产生一个有效的片选信号。
    • 1:帧同步由采样率发生器按固定周期产生。这在多通道、固定帧率的音频应用中常用,但SPI通信中一般不这么用。
    • 实操建议:在SPI主模式下,简单起见,设置FSGM = 0。这样,你只需要操作DXR寄存器,片选信号会自动管理。

2.3 数据延迟:对齐数据与时钟的关键

数据延迟(XDATDLY和RDATDLY)决定了数据位相对于帧同步信号(片选有效)开始时刻的偏移。在SPI中,这至关重要。

  • XDATDLY (XCR2[1:0]):发送数据延迟。
  • RDATDLY (RCR2[1:0]):接收数据延迟。
  • SPI模式下的强制要求
    • 主模式XDATDLY = 01b,RDATDLY = 01b。即1比特延迟。这是为了在片选信号有效后,留出一个时钟周期的建立时间,确保数据稳定。
    • 从模式XDATDLY = 00b,RDATDLY = 00b。即0比特延迟。从设备必须在片选有效后立即响应,数据在第一个时钟边沿���绪。
  • 为什么必须遵守?这是由SPI协议和McBSP在时钟停止模式下的硬件时序决定的。如果设置错误(例如在主模式下设为0),可能导致第一个数据位无法被正确捕获;设为2则在标准SPI中无意义。手册明确说明,在时钟停止模式下,0或2的延迟值是“未定义的”。

2.4 采样率发生器:主设备的时钟心脏

当McBSP作为主设备时,需要自己产生SPI时钟。这个时钟来源于DSP的CPU时钟,通过采样率发生器分频得到。

  • CLKSM (SRGR1[7]):通常设为1,表示采样率发生器时钟(CLKG)由CPU时钟驱动。
  • CLKGDV (SRGR1[7:0]):这是关键的分频系数。SPI时钟频率计算公式为:SPI_CLK = CPU_CLK / (2 * (1 + CLKGDV))例如,CPU时钟为150MHz,想要得到10MHz的SPI时钟,则CLKGDV = (150MHz / (2 * 10MHz)) - 1 = 6.5。取整为7,实际频率约为150 / (2*8) = 9.375MHzCLKGDV的取值范围是1-255
  • SCLKME (PCR[11]):在大多数TMS320F2833x等器件上,此位应设为0,选择CPU时钟作为采样率发生器的源。

注意:配置采样率发生器相关寄存器(SRGR1/2)必须在采样率发生器复位(GRST=0)的情况下进行。修改完后,再释放复位(GRST=1)。

3. 分步配置流程与代码示例

理解了关键位之后,我们来看一个完整的、可操作的配置流程。这个流程遵循“先复位,再配置,最后使能”的原则,确保配置过程稳定。

3.1 通用配置流程(主/从模式均需遵循)

  1. 复位阶段

    • 将发送器、接收器、采样率发生器全部置于复位状态。这是为了防止在配置过程中模块产生不可控的操作。
    // 假设 McBSPa 的寄存器基地址为 McbspaRegs McbspaRegs.SPCR2.bit.XRST = 0; // 复位发送器 McbspaRegs.SPCR1.bit.RRST = 0; // 复位接收器 McbspaRegs.SPCR2.bit.GRST = 0; // 复位采样率发生器 // 确保帧同步逻辑也复位 McbspaRegs.SPCR2.bit.FRST = 0;
  2. 引脚功能配置

    • 将相关引脚从通用IO模式切换到McBSP功能模式。这通常通过GPIO多路复用控制寄存器(GPxMUX)完成。具体哪个引脚对应哪个功能,需要查阅芯片的数据手册。
    // 例如,配置GPIO12为MCBSPA_CLKX功能 GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 1; // 假设MUX值1对应MCBSPA_CLKX // 配置GPIO13为MCBSPA_DX, GPIO14为MCBSPA_DR, GPIO15为MCBSPA_FSX GpioCtrlRegs.GPAMUX1.bit.GPIO13 = 1; GpioCtrlRegs.GPAMUX1.bit.GPIO14 = 1; GpioCtrlRegs.GPAMUX1.bit.GPIO15 = 1;
  3. 核心寄存器配置(区分主从)

    • 这是最核心的一步,根据上述章节的详解,设置PCR、SPCR1、RCR、XCR、SRGR等寄存器。下面给出具体示例。

3.2 SPI主设备配置示例

假设我们需要配置McBSP-A为SPI主设备,模式0(CPOL=0, CPHA=0),时钟频率10MHz(CPU时钟150MHz),8位数据位,帧同步低有效。

void McBSP_SPI_Master_Init(void) { // 1. 全局和引脚复位 (已在之前步骤完成) // McbspaRegs.SPCR2.all = 0x0000; // McbspaRegs.SPCR1.all = 0x0000; // 2. 配置引脚控制寄存器 (PCR) McbspaRegs.PCR.bit.CLKXM = 1; // CLKX 输出 (主设备) McbspaRegs.PCR.bit.FSXM = 1; // FSX 输出 (主设备产生片选) McbspaRegs.PCR.bit.CLKSM = 1; // 采样率发生器时钟源为CPU时钟 (通常固定) // 以下两位决定SPI模式 McbspaRegs.PCR.bit.CLKXP = 0; // 时钟极性:空闲低,上升沿启动 (CPOL=0) McbspaRegs.PCR.bit.CLKRP = 0; // 接收时钟极性:下降沿采样 (CPHA=0) McbspaRegs.PCR.bit.FSXP = 1; // FSX (片选) 低有效 // 3. 配置接收控制寄存器 (RCR) McbspaRegs.RCR1.bit.RWDLEN1 = 0b000; // 接收字长:8位 (RWDLEN1=000b) McbspaRegs.RCR1.bit.RFRLEN1 = 0b0000000; // 接收帧长:1个字 (RFRLEN1=0) McbspaRegs.RCR2.bit.RDATDLY = 0b01; // 接收数据延迟:1比特 (SPI主模式必须) McbspaRegs.RCR2.bit.RPHASE = 0; // 单相位帧 // 4. 配置发送控制寄存器 (XCR) McbspaRegs.XCR1.bit.XWDLEN1 = 0b000; // 发送字长:8位 McbspaRegs.XCR1.bit.XFRLEN1 = 0b0000000; // 发送帧长:1个字 McbspaRegs.XCR2.bit.XDATDLY = 0b01; // 发送数据延迟:1比特 (SPI主模式必须) McbspaRegs.XCR2.bit.XPHASE = 0; // 单相位帧 // 5. 配置采样率发生器 (SRGR) - 产生SPI时钟 // SPI SCLK = CPU_CLK / [2 * (1 + CLKGDV)] // 设 CPU_CLK = 150MHz, 目标 SCLK = 10MHz // CLKGDV = (150e6 / (2 * 10e6)) - 1 = 6.5 -> 取7 McbspaRegs.SRGR1.bit.CLKGDV = 7; // 分频系数 McbspaRegs.SRGR2.bit.FSGM = 0; // 帧同步由DXR->XSR传输产生 (适合SPI) // 其他SRGR2位如FPER、FWID在SPI模式下通常被覆盖,可忽略或设默认值 // 6. 配置串口控制寄存器 (SPCR) - 启用时钟停止模式 McbspaRegs.SPCR1.bit.CLKSTP = 0b10; // 启用时钟停止模式,无延迟 (对应CPHA=0) // 7. 使能采样率发生器 McbspaRegs.SPCR2.bit.GRST = 1; // 释放采样率发生器复位 // 等待至少2个CLKG周期稳定。简单做法是插入少量空指令或短延时。 asm(" RPT #10 || NOP"); // 示例:空操作等待 // 8. 使能发送器和接收器 McbspaRegs.SPCR2.bit.XRST = 1; // 使能发送器 McbspaRegs.SPCR1.bit.RRST = 1; // 使能接收器 // 再次等待稳定 asm(" RPT #10 || NOP"); // 9. (可选) 使能帧同步逻辑。对于SPI主设备,FSX由发送器自动产生。 // 如果FSGM=0,当数据写入DXR启动传输时,FSX会自动变低。 // 因此FRST位在简单SPI主模式下通常保持0即可,FSX由每次传输自动触发。 // McbspaRegs.SPCR2.bit.FRST = 1; // 如果需要周期性帧同步才启用 }

3.3 SPI从设备配置示例

配置McBSP-A为SPI从设备,模式0,8位数据。

void McBSP_SPI_Slave_Init(void) { // 1. 全局和引脚复位 McbspaRegs.SPCR2.bit.XRST = 0; McbspaRegs.SPCR1.bit.RRST = 0; McbspaRegs.SPCR2.bit.GRST = 0; McbspaRegs.SPCR2.bit.FRST = 0; // 2. 配置引脚控制寄存器 (PCR) McbspaRegs.PCR.bit.CLKXM = 0; // CLKX 输入 (从设备接收外部时钟) McbspaRegs.PCR.bit.FSXM = 0; // FSX 输入 (从设备接收外部片选) McbspaRegs.PCR.bit.CLKSM = 1; // 采样率发生器时钟源为CPU时钟 // SPI模式0 McbspaRegs.PCR.bit.CLKXP = 0; // 根据主设备时钟极性设置,假设主设备是空闲低 McbspaRegs.PCR.bit.CLKRP = 0; // 根据主设备时钟相位设置,下降沿采样 McbspaRegs.PCR.bit.FSXP = 1; // 假设外部片选低有效 // 3. 配置接收控制寄存器 (RCR) McbspaRegs.RCR1.bit.RWDLEN1 = 0b000; // 8位 McbspaRegs.RCR1.bit.RFRLEN1 = 0b0000000; // 1字帧 McbspaRegs.RCR2.bit.RDATDLY = 0b00; // 从设备必须为0比特延迟! McbspaRegs.RCR2.bit.RPHASE = 0; // 4. 配置发送控制寄存器 (XCR) McbspaRegs.XCR1.bit.XWDLEN1 = 0b000; // 8位 McbspaRegs.XCR1.bit.XFRLEN1 = 0b0000000; // 1字帧 McbspaRegs.XCR2.bit.XDATDLY = 0b00; // 从设备必须为0比特延迟! McbspaRegs.XCR2.bit.XPHASE = 0; // 5. 配置采样率发生器 (SRGR) - 从设备也需要使能,用于内部同步 // CLKGDV应设置为1,让CLKG以最高速率(CPU时钟/2)运行,以可靠同步外部时钟。 McbspaRegs.SRGR1.bit.CLKGDV = 1; // 关键!���设备需快速内部时钟同步外部信号 // 6. 配置串口控制寄存器 (SPCR) - 启用时钟停止模式 McbspaRegs.SPCR1.bit.CLKSTP = 0b10; // 模式0,无延迟 // 7. 使能采样率发生器 McbspaRegs.SPCR2.bit.GRST = 1; asm(" RPT #10 || NOP"); // 8. 使能发送器和接收器 McbspaRegs.SPCR2.bit.XRST = 1; McbspaRegs.SPCR1.bit.RRST = 1; asm(" RPT #10 || NOP"); // 从设备无需也不应设置FRST=1,帧同步(片选)由外部主设备提供。 }

3.4 数据收发操作

配置完成后,数据的收发就相对简单了。

  • 发送数据:将数据写入发送数据寄存器DXR1(如果是16位以上数据,还有DXR2)。一旦写入,如果发送器已就绪且片选条件满足(主模式下会自动拉低FSX),数据就会开始移位输出。
    McbspaRegs.DXR1.all = data_to_send; // 写入要发送的数据
  • 接收数据:轮询接收就绪标志RRDY(在SPCR1.bit.RRDY),或者使用中断。当RRDY为1时,从接收数据寄存器DRR1中读取数据。
    while(McbspaRegs.SPCR1.bit.RRDY != 1) { // 等待接收完成 } received_data = McbspaRegs.DRR1.all; // 读取接收到的数据
  • 全双工通信:SPI是全双工的,发送的同时也在接收。通常的操作是:写入DXR1启动一次传输,然后等待RRDY置位,再读取DRR1,得到的是上一次传输时从设备发回的数据。要实现连续传输,需要注意缓冲区:DXRXSR,以及RSRRBR再到DRR的双缓冲机制。

4. 常见问题、调试技巧与避坑指南

配置McBSP为SPI模式时,很容易遇到通信失败。以下是我在实际项目中踩过坑后总结出的排查清单和经验。

4.1 通信完全无反应

  • 检查引脚复用:这是最容易忽略的一步!确保GPxMUX寄存器已正确配置,将物理引脚从GPIO模式切换到McBSP功能模式。用示波器或逻辑分析仪测量CLKX、FSX、DX引脚,如果没有任何波形,首先怀疑这里。
  • 确认复位与使能顺序:严格遵循“全部复位 -> 配置寄存器 -> 使能GRST -> 短暂延时 -> 使能XRST/RRST”的流程。顺序错乱可能导致模块处于不确定状态。
  • 验证时钟与片选信号方向
    • 主模式:CLKX和FSX必须是输出。测量CLKX引脚,应该有时钟信号(即使没有数据传输,在时钟停止模式下可能没有,但一旦启动传输应有)。FSX应在每次写入DXR后产生一个负脉冲(如果FSXP=1)。
    • 从模式:CLKX和FSX必须是输入。确保外部主设备提供的时钟和片选信号已正确连接到这些引脚,并且电平符合预期(CLKXP, FSXP)。
  • 检查采样率发生器:主模式下,计算CLKGDV值是否正确,SPI时钟频率是否在从设备支持的范围内。从模式下,CLKGDV必须设为1。

4.2 数据错位或采样错误

  • 首要怀疑:CLKSTP、CLKXP、CLKRP组合:这三位必须与SPI从设备的模式(CPOL, CPHA)严格匹配。用逻辑分析仪同时捕获主设备的CLK、MOSI和从设备的MISO,对照SPI模式时序图仔细比对第一个数据位的出现时刻和采样边沿。
    • 一个快速验证方法:如果怀疑模式不对,可以尝试另一种常见组合。例如,从模式0(CLKXP=0, CLKRP=0, CLKSTP=10b)切换到模式3(CLKXP=1, CLKRP=1, CLKSTP=11b),看看问题是否变化。
  • 确认数据延迟(XDATDLY/RDATDLY)
    • 主模式必须是01b。如果设成00b,数据会提前半个时钟周期出现,可能导致从设备在第一个时钟边沿采样时数据还未稳定。
    • 从模式必须是00b。如果设成01b,从设备的数据输出会晚一个时钟周期,主设备会采样到错误数据。
  • 检查字长(RWDLEN1/XWDLEN1):确保与通信双方约定的数据位数一致。8位设备就设成000b。如果设成16位(010b),而对方发8位,会导致帧同步错误或数据拼接错误。

4.3 帧同步(片选)信号问题

  • 主模式FSX无输出
    • 检查FSXM是否设为1(输出)。
    • 检查FSGM是否设为0。如果FSGM=1,则需要配置FPERFWID来产生周期性帧同步,这不适用于典型的SPI片选控制。SPI片选通常是每个数据包一个脉冲,所以FSGM=0是更简单的选择。
    • 确保已经执行了一次数据写入DXR1的操作。FSGM=0时,FSX脉冲是由DXRXSR的传输触发的。
  • 从设备不响应
    • 检查FSXP极性是否与主设备片选信号极性匹配。常见是低有效(FSXP=1)。
    • 关键点:McBSP作为SPI从设备时,要求主设备在每个数据包传输前重新断言(拉低)片选信号,传输完成后释放(拉高)。它不支持片选一直保持低电平。如果主设备将片选一直拉低,McBSP从设备将无法识别新数据包的开始。

4.4 使用逻辑分析仪进行调试

这是最有效的调试手段。将逻辑分析仪的通道连接到SPI的四根线上(主:SCLK, MOSI, MISO, CS;从:对应连接)。设置解码器为SPI,并正确配置极性(CPOL, CPHA)。

  • 看什么
    1. 有无波形:最基础,确认硬件连接和引脚功能正确。
    2. 时序参数:测量SCLK频率、数据建立时间(Data Setup)、数据保持时间(Data Hold)是否满足从设备要求。McBSP产生的时序通常很规整。
    3. 数据内容:解码出的十六进制数据是否与你发送/期望的一致。可以同时发送一个固定的测试模式(如0xAA或0x55),便于观察。
    4. 帧同步/片选:观察CS信号是否在每个数据包前有效,包结束后无效。脉冲宽度是否覆盖了整个数据包。

4.5 软件层面的注意事项

  • 双缓冲机制:McBSP有DXR/XSRRSR/RBR/DRR两级缓冲区。写入DXR后,数据不会立即发送,要等到XSR为空时才传输过去并开始发送。读取DRR得到的是已经完整接收并存放在RBR里的数据。编程时要注意状态位(XRDY,RRDY)或使用DMA/中断,避免覆盖或丢失数据。
  • 多字节传输:对于超过一个字长(如16位)的数据,需要拆分成多个SPI传输。每个传输都会产生独立的FSX脉冲(如果FSGM=0)。如果你需要在一个片选有效期内连续传输多个字,可能需要采用FSGM=1并配置长帧模式,或者更常见的,使用GPIO手动控制FSX引脚在一个批次传输期间保持有效。
  • 初始化代码的位置:确保McBSP的初始化代码在系统时钟稳定之后执行。如果时钟配置不正确或尚未稳定,采样率发生器计算出的SPI时钟会不准。

配置McBSP为SPI是一个细致活,寄存器多,关联复杂。最好的学习方法就是结合手册、参考代码,然后用逻辑分析仪实际抓取波形,将理论配置与实际的电信号一一对应起来。一旦调通,这套强大的串口就能在各种SPI通信任务中稳定可靠地工作。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询