1. McBSP配置SPI的核心思路与协议适配
在嵌入式系统开发中,串行外设接口(SPI)因其简单、高效和全双工的特性,成为连接微控制器与传感器、存储器、显示模块等外设的首选协议。然而,当你手头的DSP,比如TI的TMS320系列,其标配的串行通信模块是多通道缓冲串行端口(McBSP)时,事情就变得有趣了。McBSP原生是为复杂的多通道、时分复用音频通信设计的,功能强大但寄存器配置也相对复杂。将其“驯服”为SPI接口,本质上是在一个通用、灵活的硬件框架上,通过精准的寄存器配置,模拟出SPI协议所需的特定时序和行为模式。
这个过程的核心思路,我称之为“协议映射”。SPI协议有四个关键信号:串行时钟(SCLK)、主出从入(MOSI/SIMO)、主入从出(MISO/SOMI)和从设备使能(SS/STE)。而McBSP的信号线是:发送时钟(CLKX)、接收时钟(CLKR)、发送数据(DX)、接收数据(DR)、发送帧同步(FSX)和接收帧同步(FSR)。配置的第一步,就是在脑海里完成这张映射表。作为SPI主设备时,McBSP的CLKX输出时钟信号,DX输出MOSI数据,DR接收MISO数据,而FSX则扮演从设备使能(STE)的角色。作为从设备时,CLKX和FSX变为输入,分别接收外部主设备提供的时钟和片选信号。
但仅仅信号映射是不够的。SPI协议要求时钟在数据包传输间隙保持静止(即“时钟停止”模式),而标准的McBSP时钟是连续运行的。这就是配置中的第一个关键点:启用时钟停止模式(CLKSTP)。这个模式是McBSP为兼容SPI协议专门设计的,它允许内部时钟生成器在无数据传输时暂停,并在每个数据包开始时重新启动,完美契合了SPI的时序要求。此外,SPI的时钟极性(CPOL)和相位(CPHA)决定了数据采样的边沿,这对应到McBSP的时钟极性位(CLKXP, CLKRP)和数据延迟位(XDATDLY, RDATDLY)。理解这四者之间的关系,是配置成功与否的决定性因素。简单来说,CPOL决定了时钟空闲状态的高低,CPHA决定了数据在第一个还是第二个时钟边沿被采样,而McBSP则通过组合CLKSTP、CLKXP/CLKRP和DATDLY来精确实现这四种模式。
因此,整个配置过程远非简单地填几个寄存器值。它要求开发者深入理解SPI的时序逻辑,并清晰知晓如何通过McBSP的各个控制位来“雕刻”出这些时序。这就像用一套高级的木工工具去制作一个简单的榫卯,工具的所有复杂功能中,你只需要精准地使用其中几个关键部分。接下来的章节,我将带你一步步拆解这个“雕刻”过程,从复位流程到每一个关键寄存器的比特含义,并结合我多年调试中踩过的坑,让你不仅能配得通,更能理解为什么这么配。
2. 关键寄存器深度解析与配置逻辑
配置McBSP为SPI模式,本质上是对一系列寄存器进行精确编程。官方手册的表格列出了必需的位设置,但知其然更要知其所以然。下面我将这些关键寄存器分成几类,深入剖析每个配置项背后的设计意图和物理意义,这能帮助你在调试异常时,快速定位问题根源。
2.1 时钟系统配置:CLKSTP、CLKXP/CLKRP与DATDLY的协同
这是SPI配置中最核心、也最容易出错的部分。它共同决定了时钟波形和数据采样的时序关系。
时钟停止模式(CLKSTP,位于SPCR1[12:11]):这是启用SPI兼容模式的“总开关”。CLKSTP=10b表示启用无延迟的时钟停止模式,CLKSTP=11b则表示启用带半个时钟周期延迟的时钟停止模式。这个“延迟”直接对应SPI的时钟相位(CPHA)。当CLKSTP=11b时,第一个数据位的驱动/采样会相对于时钟有效边沿延迟半个周期,这通常用于实现CPHA=1的模式。一个至关重要的细节:一旦启用了时钟停止模式(CLKSTP非00),McBSP内部会自动将接收时钟(MCLKR)连接到发送时钟(CLKX)上。这意味着在SPI模式下,你只需要关心CLKX这一路时钟,CLKR的配置会被内部覆盖,这简化了连接,但也意味着你不能为收发设置独立的时钟源。
时钟极性(CLKXP与CLKRP,分别位于PCR寄存器和SPCR1):CLKXP控制CLKX引脚上的时钟极性。CLKXP=0表示时钟空闲时为低,有效边沿为上升沿;CLKXP=1则相反,空闲高,有效下降沿。CLKRP控制接收时钟MCLKR的极性,但在时钟停止模式下,由于MCLKR内部连接到了CLKX,CLKRP的实际作用是翻转内部用于采样数据的时钟边沿。这一点非常关键。组合CLKSTP、CLKXP和CLKRP,才能完整定义SPI的四种模式。例如,要实现最常用的SPI模式0(CPOL=0, CPHA=0),通常需要设置CLKSTP=10b(无延迟),CLKXP=0(空闲低,上升沿有效),CLKRP=0(在上升沿采样数据)。
数据延迟(XDATDLY与RDATDLY,位于XCR2和RCR2):这个参数定义了帧同步信号有效后,数据位开始传输或采样前的时钟延迟位数。对于SPI主模式,必须设置为01b(1位延迟)。这是因为在SPI协议中,片选信号(对应FSX)有效后,通常需要等待一个时钟周期,数据位才开始在第一个时钟边沿出现。如果设置为00b(0延迟),数据会在帧同步有效的同一个时钟边沿就绪,这与标准SPI时序不符。设置为10b(2位延迟)在SPI模式下是未定义的,会导致通信失败。对于SPI从模式,则必须设置为00b,因为从设备需要在主设备提供的时钟边沿上立即响应数据。
注意:时钟极性/相位匹配的实战经验很多SPI从设备(如传感器、Flash芯片)的时序图标注的是基于其自身SCLK和CS引脚的视角。当你配置McBSP作为主设备时,你的
CLKXP和CLKRP设置,生成的是McBSP引脚上的波形。务必使用示波器同时测量McBSP的CLKX、FSX和DX引脚,将实测波形与从设备数据手册的时序图进行比对,确保空闲电平、有效边沿和数据建立/保持时间完全匹配。仅靠记忆“模式0对应某组配置”很容易出错,因为不同厂商对“模式”的定义可能有细微差别。
2.2 主从模式切换的核心:CLKXM与FSXM
这两个位是区分主从模式的关键开关,位于PCR寄存器。
时钟模式(CLKXM):
- 主模式(Master):
CLKXM = 1。此配置下,McBSP的采样率发生器(Sample Rate Generator)被启用,并从CPU时钟分频产生CLKG。CLKG驱动CLKX引脚输出,成为整个SPI网络的时钟源。此时,MCLKX引脚被配置为输出。 - 从模式(Slave):
CLKXM = 0。此配置下,MCLKX引脚被配置为输入,接收外部主设备提供的时钟信号。采样率发生器虽然仍需使能(用于内部逻辑同步),但其生成的CLKG不再驱动CLKX引脚,而是用于同步外部输入的异步时钟。
帧同步模式(FSXM):
- 主模式:
FSXM = 1。FSX引脚配置为输出。通常结合FSGM=0,使得每次数据从DXR1传输到XSR1(即每次写入发送缓冲区)时,自动在FSX引脚上产生一个帧同步脉冲(即SPI的片选信号)。FSXP位用于设置该脉冲的有效电平,通常设为1(低电平有效)。 - 从模式:
FSXM = 0。FSX引脚配置为输入,用于接收外部主设备发出的片选信号。
一个容易忽略的要点:在从模式下,虽然FSX和CLKX都来自外部,但McBSP要求主设备必须在每一次数据传输前都重新断言(拉低)FSX信号,并在传输完成后释放(拉高)。它不支持FSX(片选)持续保持低电平的SPI变种。如果你的主设备是持续拉低片选的,那么McBSP作为从设���将无法正确工作。
2.3 采样率发生器(SRG)的配置
即使是在从模式下,采样率发生器也必须被使能(GRST=1)。它的作用不是产生通信时钟,而是产生一个高速的内部时钟CLKG(通常配置为CPU时钟的一半),用于同步McBSP内部逻辑与外部输入的、可能异步的SPI时钟和帧同步信号。这保证了内部状态机能够可靠地捕捉外部信号边沿。
- 时钟源与分频(CLKSM, SCLKME, CLKGDV):通常设置
CLKSM=1且SCLKME=0,选择CPU时钟作为SRG的源。CLKGDV是分频系数,CLKG频率 = CPU时钟频率 / (CLKGDV + 1)。在从模式下,为了获得最好的同步性能,通常将CLKGDV设为1,让CLKG以最高频率(CPU时钟/2)运行。在主模式下,CLKGDV则决定了你输出的SPI时钟频率,需要根据外设要求和CPU频率计算得出。
3. 分步配置流程与实操代码示例
理解了原理之后,我们来看具体的配置步骤。官方手册的流程(复位->配置->使能)是黄金准则,必须严格遵守,否则可能导致不可预测的行为。下面我结合代码片段(以C语言为例,适用于TMS320F2833x系列)进行详解。
3.1 配置流程详解
步骤1:将发送器、接收器和采样率发生器置于复位状态这是配置的起点,确保在修改关键寄存器时,串口处于静止状态。
// 假设 McBSPa 的寄存器基地址已映射为 McBspaRegs McBspaRegs.SPCR2.bit.XRST = 0; // 发送器复位 McBspaRegs.SPCR1.bit.RRST = 0; // 接收器复位 McBspaRegs.SPCR2.bit.GRST = 0; // 采样率发生器复位步骤2:配置影响SPI操作的相关寄存器这是核心配置阶段。务必确保步骤1的复位已完成(通常插入少量NOP指令或等待循环),再开始配置。
// 首先,通过PCR寄存器配置引脚功能和时钟/帧同步模式 McBspaRegs.PCR.bit.CLKXM = 1; // 1=主模式(输出时钟), 0=从模式(输入时钟) McBspaRegs.PCR.bit.FSXM = 1; // 1=主模式(输出FSX), 0=从模式(输入FSX) McBspaRegs.PCR.bit.CLKXP = 0; // 时钟极性: 0=空闲低,上升沿有效 McBspaRegs.PCR.bit.FSXP = 1; // FSX极性: 1=低电平有效(常用作片选) McBspaRegs.PCR.bit.CLKRP = 0; // 接收时钟极性,需与CLKXP和CLKSTP配合 // 配置SPCR1中的时钟停止模式和数据格式 McBspaRegs.SPCR1.bit.CLKSTP = 2; // 10b, 启用时钟停止模式(无延迟),对应CPHA=0 // McBspaRegs.SPCR1.bit.CLKSTP = 3; // 11b, 启用时钟停止模式(有延迟),对应CPHA=1 // 配置接收控制寄存器RCR1/RCR2 McBspaRegs.RCR1.bit.RWDLEN1 = 0; // 接收字长,0=8位,根据SPI数据长度设置 McBspaRegs.RCR1.bit.RFRLEN1 = 0; // 接收帧长度,(0+1)=1个word每帧,SPI通常单字传输 McBspaRegs.RCR2.bit.RDATDLY = 0; // 接收数据延迟,从模式必须为0 // McBspaRegs.RCR2.bit.RDATDLY = 1; // 主模式必须为1 // 配置发送控制寄存器XCR1/XCR2 McBspaRegs.XCR1.bit.XWDLEN1 = 0; // 发送字长,需与接收字长一致 McBspaRegs.XCR1.bit.XFRLEN1 = 0; // 发送帧长度 McBspaRegs.XCR2.bit.XDATDLY = 0; // 发送数据延迟,从模式必须为0 // McBspaRegs.XCR2.bit.XDATDLY = 1; // 主模式必须为1 // 配置采样率发生器SRGR(设置SPI时钟频率-仅主模式需要) // 假设CPU时钟SYSCLKOUT = 150MHz, 需要SPI时钟 = 10MHz // CLKGDV = (SYSCLKOUT / (2 * 期望的SPI_CLK)) - 1 // 注意:CLKG频率 = SYSCLKOUT / (CLKGDV + 1)。在时钟停止模式下,SPI_SCLK = CLKG / 2。 // 因此,期望的SPI_CLK = SYSCLKOUT / (2 * (CLKGDV + 1)) // 推导出:CLKGDV = (SYSCLKOUT / (2 * SPI_CLK)) - 1 // 代入:CLKGDV = (150e6 / (2 * 10e6)) - 1 = (7.5) - 1 = 6.5 -> 取整为6或7,需实测调整 McBspaRegs.SRGR2.bit.CLKSM = 1; // 使用CPU时钟作为SRG源 McBspaRegs.SRGR1.bit.CLKGDV = 6; // 分频值,计算得到 McBspaRegs.SRGR2.bit.FSGM = 0; // FSX由DXR->XSR拷贝自动产生(适用于SPI主模式) McBspaRegs.SRGR2.bit.FPER = 0; // 帧周期,在FSGM=0时忽略步骤3:使能采样率发生器在配置好所有寄存器后,首先释放采样率发生器的复位。
McBspaRegs.SPCR2.bit.GRST = 1; // 使能采样率发生器 DELAY_US(1); // 短暂等待,确保SRG时钟稳定。等待时间需大于2个CLKG周期。步骤4:使能发送器和接收器等待SRG稳定后,再使能收发单元。
// 如果是CPU控制数据传输 McBspaRegs.SPCR2.bit.XRST = 1; // 使能发送器 McBspaRegs.SPCR1.bit.RRST = 1; // 使能接收器 DELAY_US(1); // 再次等待逻辑稳定 // 如果是DMA控制数据传输,则先配置并启动DMA通道,然后再置位XRST和RRST步骤5:(仅主模式)使能帧同步逻辑对于SPI主模式,需要在数据就绪后,手动触发或自动产生帧同步(片选)信号。如果配置了FSGM=0,则每次写入DXR都会自动产生FSX脉冲。如果需要更复杂的控制,可以设置FSGM=1并通过设置FRST=1来启动周期性的帧同步,但这在简单SPI通信中不常用。
// 如果FSGM=0,此步非必须,因为DXR->XSR的拷贝会自动产生FSX。 // 如果FSGM=1,且需要内部产生帧同步,则: // McBspaRegs.SPCR2.bit.FRST = 1;3.2 主从模式配置差异总结表
为了更清晰地对比,我将关键配置差异总结如下:
| 配置项 | SPI 主模式 (Master) | SPI 从模式 (Slave) | 说明 |
|---|---|---|---|
| CLKXM | 1 (输出) | 0 (输入) | 决定时钟引脚方向 |
| FSXM | 1 (输出) | 0 (输入) | 决定帧同步(片选)引脚方向 |
| CLKGDV | 根据所需SPI时钟计算 | 通常设为1 | 主模式用于分频生成时钟;从模式用于内部同步 |
| XDATDLY | 01b (1位延迟) | 00b (0延迟) | 关键!主从模式必须不同 |
| RDATDLY | 01b (1位延迟) | 00b (0延迟) | 关键!主从模式必须不同 |
| FSXP | 通常为1 (低有效) | 通常为1 (低有效) | 片选信号极性,需与外设匹配 |
| 时钟源 | 内部SRG生成 | 外部主设备提供 | - |
| FSX信号 | 由McBSP自动产生(FSGM=0)或软件控制 | 由外部主设备提供 | 从模式要求每个数据包前FSX需重新有效 |
实操心得:配置顺序的“坑”我最常遇到的诡异问题,都出在配置顺序上。绝对不要在收发器或SRG还在运行(未复位)时修改PCR、SRGR、RCR、XCR等关键配置寄存器。不稳定的状态可能导致配置锁死或引脚输出异常。标准的“先全复位->配寄存器->先启SRG->再启收发”流程必须遵守。另外,在使能SRG(GRST=1)后,务必等待足够长时间(至少几个微秒,或查询某个状态位)再使能XRST和RRST,确保内部时钟已稳定。
4. 数据收发操作与DMA配合
配置好McBSP的SPI模式后,数据收发操作相对直接,但细节决定成败。
4.1 CPU轮询方式
这是最简单的方式,适用于低速或非实时传输。
发送数据:
- 等待发送就绪标志
XRDY变为1(表示DXR寄存器空)。 - 将数据写入
DXR寄存器。 - 写入操作会自动启动一次传输(如果FSGM=0,同时会触发FSX脉冲)。
接收数据:
- 等待接收就绪标志
RRDY变为1(表示DRR寄存器中有新数据)。 - 从
DRR寄存器读取数据。
// 示例:CPU轮询发送一个字节并接收一个字节 void McBSP_SPI_Transfer(uint16_t txData, uint16_t *rxData) { // 等待发送缓冲区空 while(McBspaRegs.SPCR2.bit.XRDY != 1); // 写入发送数据,触发传输 McBspaRegs.DXR1.all = txData; // 等待接收数据就绪 while(McBspaRegs.SPCR1.bit.RRDY != 1); // 读取接收数据 *rxData = McBspaRegs.DRR1.all; }注意:McBSP的DXR和DRR是16位寄存器。即使你配置为8位字长,数据也存放在低8位。写入DXR和读取DRR的操作会自动处理移位和缓冲。
4.2 DMA中断方式
对于高速、连续或大数据量传输,使用DMA是必须的,它能极大解放CPU。McBSP的发送和接收事件可以作为DMA的触发源。
配置要点:
- 先配置McBSP,再配置DMA:确保McBSP的SPI模式已正确配置并处于复位状态(XRST=RRST=0)。
- DMA通道配置:需要两个DMA通道,一个用于发送(由XEVT事件触发),一个用于接收(由REVT事件触发)。源/目的地址分别指向你的数据缓冲区(内存)和McBSP的DXR/DRR寄存器。
- 使能顺序: a. 配置并使能DMA通道。 b. 使能McBSP的采样率发生器(GRST=1)并等待稳定。 c. 使能McBSP的发送器和接收器(XRST=1, RRST=1)。 d. 此时,一旦CPU或DMA向DXR写入第一个数据,整个SPI通信流程就会由DMA自动接管。
// 伪代码示例:DMA配置思路 void Init_SPI_DMA(void) { // 1. 停止McBSP收发器和SRG (已在配置流程中完成) // 2. 配置DMA通道 DmaRegs.CH1.CONTROL.bit.SRC_DIR = 0; // 源地址不变(指向DDR) DmaRegs.CH1.CONTROL.bit.DST_DIR = 1; // 目的地址不变(指向McBSP.DXR) DmaRegs.CH1.SRC_ADDR = (uint32_t)&txBuffer[0]; DmaRegs.CH1.DST_ADDR = (uint32_t)&McBspaRegs.DXR1.all; DmaRegs.CH1.TRANSFER_SIZE = BUFFER_SIZE; DmaRegs.CH1.MODE.bit.PERINT_EN = 1; // 使能传输完成中断 DmaRegs.CH1.MODE.bit.PER_SEL = DMA_TRIG_McBSPA_XEVT; // 由McBSP发送事件触发 // 类似配置接收DMA通道(CH2),触发源为DMA_TRIG_McBSPA_REVT,源地址为McBSP.DRR,目的地址为rxBuffer // 3. 使能DMA通道 DmaRegs.CH1.CONTROL.bit.RUN = 1; // DmaRegs.CH2.CONTROL.bit.RUN = 1; // 4. 使能McBSP SRG和收发器(见3.1节步骤3&4) // 5. 启动传输:向DXR写入第一个数据(可由CPU完成,或配置DMA自动启动) McBspaRegs.DXR1.all = txBuffer[0]; }DMA配置的陷阱:务必注意DMA的传输大小(TRANSFER_SIZE)单位是“字”(16位),与你配置的SPI字长无关。如果你的SPI是8位模式,但传输100个字节,那么DMA的TRANSFER_SIZE应该设置为50(100字节 / 2字节每字)。地址递增模式也要根据你的缓冲区是
uint16_t数组还是uint8_t数组来仔细设置。
5. 高级话题:多级缓冲与错误处理
5.1 利用多级缓冲实现连续流
McBSP拥有两级缓冲:对于发送,有DXR(数据发送寄存器)和XSR(发送移位寄存器);对于接收,有RSR(接收移位寄存器)和RBR(接收缓冲寄存器),最后是DRR。这种结构允许你在当前字正在移位发送/接收时,准备下一个要发送的字或读取上一个已接收的字,从而实现无缝连续传输。在DMA配合下,这种缓冲机制能高效处理数据流。
5.2 关键状态位与错误处理
可靠的通信必须包含错误检测和处理。McBSP提供了几个重要的状态和错误标志位:
- XRDY/RRDY:发送/接收就绪标志。最常用于轮询。
- XEMPTY:发送移位寄存器(XSR)空标志。当XSR为空且DXR也无数据时置位。如果通信中途DMA数据供应不上导致XEMPTY变空,可能意味着数据欠载。
- RSYNCERR/ XSYNCERR:接收/发送同步错误。当出现意外的帧同步脉冲(FSR/FSX)时置位。在SPI从模式下,如果主设备的片选信号时序不规则,可能触发此错误。处理方式:检查
(R/X)FIG位(帧同步忽略位)的设置。如果希望忽略意外同步脉冲继续传输,可设置(R/X)FIG=1;如果希望检测到错误并中断,则设置(R/X)FIG=0,并在中断服务程序中读取该状态位并清除错误。 - RFULL/ XFULL:接收/发送过载标志。当接收缓冲器RBR满(且DRR仍未读取),或DXR满(且XSR仍未空)时置位。这通常意味着CPU或DMA处理数据的速度跟不上SPI的速率,会导致数据丢失。解决方法:优化数据搬运代码,提高中断或DMA响应优先级,或降低SPI波特率。
一个健壮的中断服务程序(ISR)应该检查这些错误位:
interrupt void McBSPA_RX_ISR(void) { // 检查接收错误 if(McBspaRegs.SPCR1.bit.RSYNCERR == 1) { // 处理同步错误:记录日志,复位接收器等 McBspaRegs.SPCR1.bit.RSYNCERR = 0; // 写1清除标志位(某些型号需写1清零) } if(McBspaRegs.SPCR2.bit.RFULL == 1) { // 处理接收溢出错误 // ... 可能需要丢弃缓冲区数据或复位通信 } // 正常数据接收处理 uint16_t data = McBspaRegs.DRR1.all; // ... 将data存入用户缓冲区 // 清除中断标志(具体操作取决于PIE模块配置) PieCtrlRegs.PIEACK.all = PIEACK_GROUP8; }6. 调试技巧与常见问题排查
即使按照手册配置,第一次尝试也常常失败。以下是基于大量调试经验总结的排查清单。
问题1:完全没有波形输出(主模式)
- 检查顺序:确认是否严格遵循了配置流程?特别是
GRST=1之后是否等待了足够时间(>2个CLKG周期)再设置XRST=1和RRST=1?一个简单的办法是在使能GRST后添加一个毫秒级的延时。 - 检查时钟:用示波器测量MCLKX引脚。如果完全没有时钟,首先检查
CLKXM是否设为1(输出),CLKSTP是否非0(10b或11b)。然后检查采样率发生器配置CLKGDV是否过大导致分频后时钟极慢。计算一下预期的时钟频率,并用示波器验证。 - 检查片选:测量FSX引脚。确保
FSXM=1,FSXP设置正确(通常为1,低有效)。尝试手动向DXR写一个数据,观察FSX是否有低电平脉冲产生。如果没有,检查FSGM位是否设置为0。
问题2:有时钟和片选,但数据线(DX)没有输出,或数据错误
- 检查数据延迟:这是最高频的配置错误。主模式下
XDATDLY必须为01b。如果设为00b,数据会在FSX有效的同一个边沿就改变,大多数SPI从设备无法识别。如果设为10b,则行为未定义。 - 检查字长和缓冲区:确认
XWDLEN1和RWDLEN1设置与你的数据位宽一致(8位=000b)。检查你写入DXR的数据是否在正确的比特位置(例如,对于8位数据,应放在低8位)。 - 检查多通道模式:确保
RMCM(接收多通道选择)和XMCM(发送多通道选择)位为0,除非你明确在使用多通道功能。这些模式会禁用某些通道,导致数据无法发出。
问题3:从模式无法响应主设备
- 检查输入配置:确认
CLKXM=0且FSXM=0,将引脚正确配置为输入。 - 检查数据延迟:从模式下
RDATDLY和XDATDLY必须为00b。这是与主模式最大的不同。 - 检查片选信号:确认主设备提供的FSX(片选)信号是每个数据包都有效的脉冲,而不是持续低电平。McBSP从模式要求每个数据包前都有新的帧同步脉冲。
- 检查内部同步时钟:从模式下,
CLKGDV通常设为1,以确保内部CLKG足够快,能可靠同步外部异步信号。如果SPI主时钟很快(接近CPU时钟的一半),可能需要调整CLKGDV或提高CPU时钟。
问题4:通信一段时间后出错或停止
- 检查溢出/欠载:监控
RFULL和XEMPTY标志。如果出现,说明数据生产或消费的速率不匹配。考虑使用DMA并确保其优先级足够高,或增加数据缓冲区大小。 - 检查同步错误:检查
RSYNCERR和XSYNCERR。如果频繁出现,检查硬件连接是否有噪声导致��外的帧同步脉冲,或者主/从设备的时序是否符合McBSP的要求。 - 静电与干扰:SPI对长距离布线敏感。确保时钟和数据线长度尽可能短,并远离噪声源。在高速情况下,可能需要端接电阻。
调试必备工具:
- 示波器/逻辑分析仪:这是最重要的工具。同时观察CLKX、FSX、DX、DR四根线,对照SPI协议时序图,一眼就能看出时钟极性、相位、数据延迟是否正确,数据是否对齐。
- 寄存器查看窗口:在调试器中实时查看McBSP所有关键寄存器的值,确认配置与预期一致。
- GPIO调试法:在关键步骤(如执行完复位、配置、使能后)用GPIO引脚输出一个脉冲,用示波器确认代码执行流和时序。
配置McBSP为SPI是一个需要耐心和细致的过程,尤其是第一次操作时。最好的方法是先从一个最简单的、已知良好的主设备或从设备开始,用示波器验证每一个配置步骤产生的信号,然后再与目标设备连接。一旦你成功调通一次,理解了每个寄存器位背后的波形意义,以后再遇到类似的配置就会得心应手。记住,嵌入式开发中,时序就是一切,而示波器是你窥视时序的眼睛。