深入解析C28x DSP的McBSP多通道缓冲串行端口配置与应用

📅 2026/7/21 10:27:32 👁️ 阅读次数 📝 编程学习
深入解析C28x DSP的McBSP多通道缓冲串行端口配置与应用

1. McBSP核心架构与设计思路拆解

在C28x DSP的众多外设中,多通道缓冲串行端口(McBSP)绝对算得上是“瑞士军刀”级别的存在。它远不止是一个简单的串口,而是一个集成了数据缓冲、时钟生成、帧同步和多通道选择等复杂功能的通信子系统。我第一次接触它是在一个工业电机控制项目里,需要同时与一个高精度编码器和一块音频处理芯片通信,当时就被它灵活的配置能力所吸引,但也为那一堆寄存器感到头疼。今天,我就结合自己踩过的坑和积累的经验,把这套寄存器的配置逻辑和背后的多通道通信原理彻底讲透。

McBSP的设计核心思想是“硬件抽象,软件定义”。它把通信协议中那些繁琐的时序、帧结构、通道管理全部硬件化,然后通过一组寄存器暴露给程序员进行配置。这样做的好处是,一旦配置完成,数据的收发就完全由硬件自动完成,CPU只需在数据就绪时进行搬运,极大地解放了CPU资源,特别适合DSP这种需要密集运算的场景。它的工作原理可以类比为一个高度可编程的“数据流水线装配工”:采样率生成器(SRG)负责提供精确的节拍(时钟CLKG)和开工信号(帧同步FSG);控制寄存器(RCR/XCR)定义了每个“包裹”(数据字)的大小和每批“货物”(数据帧)的结构;而多通道控制寄存器(MCR)则像一个智能分拣系统,决定流水线上128个工位(通道)中,哪些工位需要干活,哪些可以休息。

理解McBSP,关键要抓住三条主线:时钟与帧同步数据格式与控制多通道管理。时钟是心跳,帧同步是呼吸节拍,数据格式是语言规则,多通道则是并发处理能力。接下来,我们就沿着这三条线,深入到每个关键寄存器的比特位中去看个究竟。

2. 时钟与帧同步:通信的节拍器(SRGR & PCR)

任何同步通信的基石都是时钟和帧同步。McBSP的灵活性在这里体现得淋漓尽致,它允许时钟和帧同步信号既来自外部引脚,也来自内部可编程的采样率生成器。

2.1 采样率生成器寄存器(SRGR1, SRGR2)深度解析

采样率生成器是McBSP的“心脏”,它产生内部时钟CLKG和内部帧同步FSG。其配置主要围绕两个寄存器:SRGR1和SRGR2。

SRGR1寄存器相对简单,主要管两件事:

  • CLKGDV (位 7-0):这是时钟分频因子。公式很简单:CLKG频率 = 输入时钟频率 / (CLKGDV + 1)。这里有个新手极易忽略的细节:CLKGDV是一个8位寄存器,最大值255,因此分频范围是1到256。注意CLKGDV不能设为0,否则会导致CLKG频率等于输入时钟频率,在某些高频率下可能超出硬件限制。我通常习惯在初始化时先将其设为最大值(或一个安全值),待其他参数配好后再调整到目标值。
  • FWID (位 15-8):定义内部产生的帧同步脉冲FSG的宽度,单位是CLKG周期。实际脉冲宽度 =FWID + 1。这意味着脉冲宽度可以在1到256个CLKG周期之间调节。在常见的单脉冲帧同步模式下,这个宽度通常设置为1(即FWID=0),表示帧同步信号仅持续一个时钟周期的高(或低)电平。

SRGR2寄存器则更为关键,它决定了采样率生成器的工作模式:

  • FPER (位 11-0):定义帧同步脉冲的周期,即两个帧同步信号上升沿之间的CLKG周期数。实际周期 =FPER + 1。这是一个12位的值,因此周期范围是1到4096个CLKG周期。这里有一个核心概念:一个帧周期内包含的所有数据字(通道)的时钟总数,必须小于或等于FPER定义的长度。你需要根据字长、每帧字数来倒推所需的FPER。

  • FSGM (位 12):此位仅在发送帧同步由内部产生时(PCR.FSXM=1)起作用。它决定了内部FSG信号如何触发发送。

    • FSGM=0:一种“按需”模式。只有当发送数据寄存器DXR的数据被复制到发送移位寄存器XSR时,才会产生一个帧同步脉冲。这种模式适用于非周期性的、数据驱动的发送。
    • FSGM=1:周期模式。发送帧同步完全由采样率生成器产生的FSG信号驱动,周期和宽度由FPER和FWID决定。这是最常用的模式,用于建立稳定的、周期性的数据流。
  • CLKSM 和 SCLKME (位 13, 7):这对组合位决定了采样率生成器的输入时钟源。这是配置的起点,务必理清:

    SCLKMECLKSM输入时钟源典型应用场景
    01LSPCLK (CPU低速时钟)内部时钟源,稳定,无需外部引脚。
    10外部MCLKR引脚接收时钟由外部设备提供,作为系统主时钟。
    11外部MCLKX引脚发送时钟由外部设备提供,或自身输出时钟。

    避坑指南:在配置时钟源前,务必先确认PCR寄存器中对应的时钟引脚(CLKXM, CLKRM)是配置为输入还是输出。例如,如果你选择SCLKME=1, CLKSM=1,希望从MCLKX引脚获取时钟,那么必须设置PCR.CLKXM=0,将MCLKX配置为输入引脚。逻辑矛盾是导致时钟无声无息的常见原因。

  • GSYNC (位 15):这是一个高级功能,仅在外部时钟源(MCLKR)下有效。当GSYNC=1时,CLKG会与外部输入时钟同步,并且FSG脉冲只在检测到外部FSR引脚上有脉冲时才产生,完全忽略内部FPER的设置。这用于让本地McBSP与一个外部主设备的帧结构严格同步,在复杂的多设备TDM网络中非常有用。

2.2 引脚控制寄存器(PCR)的协同配置

PCR寄存器决定了McBSP与外部世界的电气接口和基本模式,必须与SRGR的配置协同工作。

  • 时钟方向与极性 (CLKXM, CLKRM, CLKXP, CLKRP)
    • CLKXM:决定发送时钟CLKX的来源。0=外部输入,1=内部SRG输出。关键点:当CLKXM=1时,MCLKX引脚变为输出,可以给其他设备提供时钟。
    • CLKRM:决定接收时钟MCLKR的来源。0=外部输入,1=内部SRG输出。
    • CLKXP/CLKRP:设置时钟极性。0=数据在上升沿采样,1=数据在下降沿采样。必须确保通信双方(发送和接收设备)的时钟极性设置一致,这是导致数据错位的隐形杀手。
  • 帧同步方向与极性 (FSXM, FSRM, FSXP, FSRP)
    • FSXM/FSRM:决定帧同步信号来源。0=外部引脚,1=内部产生(来自SRG)。
    • FSXP/FSRP:设置帧同步极性。0=高电平有效,1=低电平有效。同样,通信双方必须一致。
  • 数字回环模式 (DLB):此位在PCR的早期位中(图中未展示全)。当DLB=1时,发送器的输出会在内部直接环回到接收器,用于模块自测试,无需外部连线。此时,接收时钟MCLKR的来源会受CLKXM影响,配置时需要查阅手册注意特殊规则。

配置心得:我习惯采用“由内而外”的配置顺序。先想好通信速率,确定CLKGDV;再根据数据帧结构(字长*字数)确定FPER;然后决定时钟和帧同步是由内部SRG产生还是外部提供,据此配置CLKSM/SCLKME和FSGM;最后,通过PCR设置引脚的输入输出方向和极性,与外部设备匹配。这个顺序能有效减少配置冲突。

3. 数据格式与传输控制:定义通信语言(RCR & XCR)

时钟和帧同步搭建了舞台,数据格式控制寄存器则定义了在这个舞台上传递的“语言”规则。接收控制寄存器(RCR1/RCR2)和发送控制寄存器(XCR1/XCR2)的结构是对称的,我们以RCR2和XCR2为例深入讲解,因为它们包含了更丰富的控制位。

3.1 字长与帧长:构建数据包结构

这是最基本也是最重要的配置,直接决定了数据如何被解析。

  • RWDLEN2 / XWDLEN2 (位 7-5):如资料所示,它们定义了相位2的字长。字长选项从8位到32位,覆盖了大多数应用。需要特别注意:字长的设置必须与数据缓冲区的数据类型匹配。例如,如果你配置为16位字长(RWDLEN2=2),那么CPU读取的接收数据寄存器(DRR)就是16位有效的,你应当将其映射到一个int16类型的变量。如果DSP是32位内核,忽略这一点可能导致数据拼接错误。
  • RPHASE / XPHASE (位 15):单/双相位选择。这是McBSP一个强大的特性。
    • 相位=0:单相位帧。整个帧使用单一的字长(由WDLEN1定义)和单一的帧长(由FRLEN1定义)。这是标准模式。
    • 相位=1:双相位帧。一帧数据被分为两个阶段(Phase)。每个阶段可以有自己的字长(WDLEN1, WDLEN2)和自己的字数(FRLEN1, FRLEN2)。这有什么用?一个典型应用是传输“数据头+数据体”的复合帧。例如,Phase1传输1个16位的命令字(XFRLEN1=0,XWDLEN1=2),Phase2传输10个24位的音频样本(XFRLEN2=9,XWDLEN2=4)。硬件自动处理这种异构帧结构,软件无需干预。
  • RFRLEN2 / XFRLEN2 (位 14-8):定义相位2的字数。这里有个关键公式:欲配置的每相位字数 =FRLENx + 1。如果你想在Phase2传输20个字,那么需要设置XFRLEN2 = 19。很多初学者直接写入20,导致帧长度错误。

3.2 数据延迟(RDATDLY / XDATDLY):对齐数据的艺术

数据延迟位(位1-0)可能看起来不起眼,但却在解决实际通信时序问题上至关重要。它定义了在帧同步脉冲有效后,延迟多少个时钟周期才开始传输第一个数据位。

  • 0:无延迟。第一个数据位在帧同步有效的同一个时钟周期就开始传输。
  • 1:1位延迟。这是最常用、也是大多数标准串行协议(如SPI, I2S)所采用的模式。帧同步脉冲先有效,下一个时钟沿到来时,第一位数据才出现在数据线上。这为接收端提供了稳定的建立时间。
  • 2:2位延迟。较少使用,适用于某些特定的定制协议。

实操经验:99%的情况下,对于需要与标准音频编解码器(如TLV320AIC23)或SPI设备通信的场景,DATDLY必须设置为1。如果设为0,很可能因为时序竞争导致第一个数据位丢失或采样错误。我曾花了一整天调试一个“数据总是少一位”的问题,最后发现就是这里配错了。

3.3 压缩扩展(RCOMPAND / XCOMPAND)与帧同步忽略(RFIG / XFIG)

  • 压缩扩展:用于支持µ-law或A-law语音压缩格式,主要用于电信领域。在普通的工业或音频传输中,通常设置为00b(无压缩,MSB先传)。如果你的数据是8位且LSB在先(某些老旧设备),可以设置为01b
  • 帧同步忽略:这是一个安全机制。当FIG=0时,如果在一个帧传输完成前,出现了意外的帧同步脉冲,McBSP会认为发生了错误,中止当前传输并设置错误标志。当FIG=1时,则忽略这个意外脉冲,继续传输。在稳定的、受控的系统中,可以设为1以提高鲁棒性。但在调试阶段,建议先设为0,以便通过错误标志及时发现时序问题。

4. 多通道控制原理与实战配置(MCR)

McBSP的“多通道”能力是其区别于普通SPI/UART的核心价值。它最多支持128个独立的时分复用(TDM)通道。想象一下,一条数据线上,每帧时间被划分为128个时间片(时隙),每个时隙传输一个通道的数据。多通道控制寄存器就是用来管理这128个时隙的开关。

4.1 通道分区模式:2分区 vs 8分区

这是理解多通道配置的第一个关键点,由RMCME(接收)和XMCME(发送)控制。

  • 2分区模式 (RMCME/XMCME = 0):这是最常用的模式。它将128个通道(0-127)分成8个块(Block),每块16个通道。但在此模式下,你只能同时激活其中的两个块(即32个通道),称为分区A和分区B。你需要通过RPABLK/XPABLK(分区A)和RPBBLK/XPBBLK(分区B)来指定当前具体使用哪两个块。例如,你可以设置分区A使用Block 0(通道0-15),分区B使用Block 3(通道48-63)。那么当前帧中,只有这32个通道是“可见”的,可以对其进行使能/屏蔽操作。
  • 8分区模式 (RMCME/XMCME = 1):在此模式下,所有8个块(128个通道)全部“在线”。你可以通过对应的通道使能寄存器(RCERx/XCERx)独立控制每一个通道的开关。这提供了最大的灵活性,但需要管理更多的寄存器位。

选择建议:除非你需要同时处理超过32个活跃通道,否则强烈建议使用2分区模式。它简化了配置,并且你可以通过动态切换RPABLK/XPABLKRPBBLK/XPBBLK来轮询访问所有128个通道。例如,在A分区处理Block 0时,你可以将B分区指向Block 1,待A分区完成后,切换过去处理,实现“乒乓操作”。

4.2 多通道选择模式(XMCM):发送通道的四种状态

接收多通道模式相对简单,由RMCM位控制:0使能所有通道,1进入多通道选择模式,此时只有被RCERx寄存器选中的通道数据才会被接收。

发送多通道模式则复杂得多,由XMCM两位控制,它有4种模式,是配置的难点:

  • 00b所有通道使能且未屏蔽。所有128个通道都会发送数据,无论XCERx寄存器如何设置。这是最简单的模式,但无法关闭任何通道。
  • 01b所有通道被禁用,除非被XCERx选中。这是“白名单”模式。只有那些在XCERx寄存器中对应位被设置为1的通道,才会被使能并发送数据。未被选中的通道,其发送引脚将保持高阻或默认状态(取决于其他设置)。这是最常用的发送控制模式,用于精确控制哪些时隙有数据输出。
  • 10b所有通道使能,但被屏蔽除非被XCERx选中。这是“黑名单”模式。所有通道的硬件都在运行,但只有被XCERx选中的通道,其数据才会被实际推到发送引脚上;未被选中的通道,发送引脚输出被屏蔽(通常为0)。这种模式适用于需要保持时钟和帧同步连续,但只输出部分数据的场景。
  • 11b对称收发模式。这是用于全双工TDM通信的优雅方案。在此模式下,一个通道只有当它被接收使能寄存器(RCERx)使能时,才会被发送器使能。然后,在这个被使能的通道子集中,只有进一步被发送使能寄存器(XCERx)选中的通道,其数据才会被输出。换句话说,RCERx决定了哪些通道“存在”,XCERx决定了在这些“存在”的通道中,哪些是“发言”的。这确保了收发双方在同一组通道上工作,避免了通道错配。

4.3 通道使能寄存器(RCERx/XCERx)的位映射

这是进行通道开关操作的直接接口。在2分区模式下,你只需要操作RCERA/RCERBXCERA/XCERB。每个寄存器16位,对应分区内16个通道。例如,在2分区模式下,RPABLK=0(分区A指向Block 0),那么RCERA的bit 0就对应通道0,bit 1对应通道1,以此类推至bit 15对应通道15。

配置流程示例(2分区模式,发送)

  1. 设置XMCME = 0(2分区模式)。
  2. 设置XMCM = 01b(通道禁用,由XCERx选择使能)。
  3. 设置XPABLK = 0(分区A管理通道0-15)。
  4. 设置XPBBLK = 1(分区B管理通道16-31)。现在,可控制的通道范围是0-31。
  5. XCERA寄存器写入0x0003(二进制...0011)。这意味着使能分区A(即Block 0)中的通道0和通道1。
  6. XCERB寄存器写入0x8000(二进制1000...)。这意味着使能分区B(即Block 1)中的通道31(对应Block 1的第15个通道,即全局通道31)。
  7. 经过以上配置,在整个128通道的TDM帧中,只有通道0、1和31会有数据发送,其余通道的发送引脚处于无效状态。

5. 完整初始化流程与代码实战

理解了各个寄存器后,我们需要一个正确的配置顺序来初始化McBSP。错误的顺序可能导致配置无法生效或产生毛刺。

5.1 推荐初始化步骤

  1. 复位与禁用:首先,将SPCR1/2中的RRSTXRST(接收/发送复位)位清零,确保McBSP处于复位状态。同时,将FRST(帧同步生成器复位)清零。
  2. 配置采样率生成器(SRGR):在模块禁用时,配置CLKGDV、FPER、FWID、CLKSM、SCLKME、FSGM等。特别注意:如果使用内部时钟(CLKXM/CLKRM=1),确保SRG的配置先于引脚模式设置。
  3. 配置引脚控制寄存器(PCR):设置时钟和帧同步的方向(输入/输出)、极性。此时信号还未激活。
  4. 配置数据控制寄存器(RCR/XCR):设置字长、帧长、相位、数据延迟、压缩模式等。
  5. 配置多通道控制寄存器(MCR):设置分区模式、选择模式,并配置分区块。
  6. 配置通道使能寄存器(RCER/XCER):根据需要使能或禁用特定通道。
  7. 使能采样率生成器:设置SPCR2中的GRST=1,释放采样率生成器复位。此时CLKG开始运行。
  8. 等待稳定:插入少量延时(例如,循环等待几个周期),确保CLKG时钟稳定。
  9. 使能帧同步:设置SPCR2中的FRST=1,启动帧同步信号FSG的生成。
  10. 使能收发器:最后,设置SPCR1中的RRST=1和SPCR2中的XRST=1,激活接收和发送逻辑。

5.2 示例代码片段(C语言)

假设我们需要配置McBSP-A,使用内部时钟(LSPCLK=50MHz)生成1MHz的位时钟(CLKG),帧同步频率为8kHz,单相位,16位字长,每帧16个字(即16通道TDM),数据延迟1位,使能通道0和1。

// 假设寄存器地址已映射,例如: volatile struct McBSP_REGS *mcbsp = &McbspaRegs; void McBSP_Config(void) { // 步骤1: 禁用模块,置于复位状态 mcbsp->SPCR1.bit.RRST = 0; mcbsp->SPCR2.bit.XRST = 0; mcbsp->SPCR2.bit.GRST = 0; mcbsp->SPCR2.bit.FRST = 0; // 步骤2: 配置采样率生成器 // CLKG = LSPCLK / (CLKGDV + 1) = 50MHz / (49 + 1) = 1MHz mcbsp->SRGR1.all = 0; mcbsp->SRGR1.bit.CLKGDV = 49; // 分频值 mcbsp->SRGR1.bit.FWID = 0; // 帧同步脉冲宽度 = 1 CLK周期 // FPER = (CLKG频率 / 帧同步频率) - 1 = (1MHz / 8kHz) - 1 = 124 mcbsp->SRGR2.all = 0; mcbsp->SRGR2.bit.FPER = 124; // 帧周期125个CLK周期 mcbsp->SRGR2.bit.FSGM = 1; // 帧同步由采样率生成器周期产生 mcbsp->SRGR2.bit.CLKSM = 1; // 输入时钟源选择... mcbsp->PCR.bit.SCLKME = 0; // ...与SCLKME=0组合,选择LSPCLK // 步骤3: 配置引脚控制寄存器 mcbsp->PCR.all = 0; mcbsp->PCR.bit.CLKXM = 1; // CLKX由内部SRG驱动,输出 mcbsp->PCR.bit.CLKRM = 0; // CLKR为输入(此处未用,可设为0或1) mcbsp->PCR.bit.FSXM = 1; // FSX由内部SRG驱动 mcbsp->PCR.bit.FSRM = 0; // FSR为输入(若需要) mcbsp->PCR.bit.CLKXP = 0; // 时钟上升沿采样 mcbsp->PCR.bit.CLKRP = 0; // 时钟上升沿采样 mcbsp->PCR.bit.FSXP = 0; // 帧同步高电平有效 mcbsp->PCR.bit.FSRP = 0; // 帧同步高电平有效 // 步骤4: 配置数据控制寄存器 // 接收配置 mcbsp->RCR1.all = 0; mcbsp->RCR1.bit.RFRLEN1 = 15; // 每帧16个字 (15+1) mcbsp->RCR1.bit.RWDLEN1 = 2; // 字长16位 mcbsp->RCR2.all = 0; mcbsp->RCR2.bit.RPHASE = 0; // 单相位 mcbsp->RCR2.bit.RDATDLY = 1; // 1位数据延迟 // 发送配置 (与接收对称) mcbsp->XCR1.all = 0; mcbsp->XCR1.bit.XFRLEN1 = 15; mcbsp->XCR1.bit.XWDLEN1 = 2; mcbsp->XCR2.all = 0; mcbsp->XCR2.bit.XPHASE = 0; mcbsp->XCR2.bit.XDATDLY = 1; // 步骤5 & 6: 配置多通道控制与使能 mcbsp->MCR1.all = 0; mcbsp->MCR1.bit.RMCM = 1; // 接收多通道选择模式 mcbsp->MCR1.bit.RMCME = 0; // 2分区模式 mcbsp->MCR1.bit.RPABLK = 0; // 分区A指向Block 0 (通道0-15) mcbsp->MCR1.bit.RPBBLK = 0; // 分区B指向Block 1 (通道16-31),可暂不使能 mcbsp->MCR2.all = 0; mcbsp->MCR2.bit.XMCM = 1; // 01b模式:通道禁用,由XCER选择 mcbsp->MCR2.bit.XMCME = 0; // 2分区模式 mcbsp->MCR2.bit.XPABLK = 0; // 发送分区A指向Block 0 mcbsp->MCR2.bit.XPBBLK = 0; // 发送分区B指向Block 1 // 使能通道0和1 mcbsp->RCERA.all = 0x0003; // 接收使能通道0和1 mcbsp->XCERA.all = 0x0003; // 发送使能通道0和1 mcbsp->RCERB.all = 0x0000; // 分区B通道全部禁用 mcbsp->XCERB.all = 0x0000; // 步骤7-10: 逐步使能模块 mcbsp->SPCR2.bit.GRST = 1; // 释放采样率生成器复位 DELAY_US(10); // 等待时钟稳定(具体时间需计算) mcbsp->SPCR2.bit.FRST = 1; // 启动帧同步生成 mcbsp->SPCR1.bit.RRST = 1; // 使能接收器 mcbsp->SPCR2.bit.XRST = 1; // 使能发送器 }

6. 高级应用与疑难排查实录

6.1 动态切换多通道分区

在2分区模式下,你可以实现通道的动态扩展。例如,系统需要处理64个通道,但硬件只支持32个通道同时激活。你可以这样做:

  1. 初始化时,设置分区A管理Block 0(通道0-15),分区B管理Block 1(通道16-31)。
  2. 在中断服务程序或主循环中,检查RCBLK/XCBLK(当前活动块)寄存器。
  3. 当发现活动块即将切换(例如,从Block 0切换到Block 1)时,在另一个分区(分区B)空闲时,重新配置RPABLK/XPABLK,将其指向下一个需要的块(例如Block 2,通道32-47)。
  4. 如此循环,实现通道0-47的轮询处理。这需要精细的时序控制,确保在配置改变时不会破坏正在进行的传输。

6.2 常见问题排查清单

  1. 问题:无数据收发,或数据全为0。

    • 检查时钟:用示波器测量MCLKX/CLKX和MCLKR/CLKR引脚是否有时钟信号?频率是否正确?极性是否符合预期?这是第一步,也是最关键的一步。
    • 检查复位状态:确认RRSTXRST已置1。确认GRSTFRST已按正确顺序置1。
    • 检查帧同步:测量FSX/FSR引脚是否有脉冲?脉冲宽度和周期是否正确?是否与数据对齐(检查DATDLY)?
  2. 问题:数据错位(例如,16位数据的高8位和低8位反了)。

    • 检查字长与缓冲区:确保RWDLEN/XWDLEN设置的数据位宽与CPU访问数据寄存器(DRR/DXR)时使用的数据类型匹配(16位还是32位)。
    • 检查压缩扩展模式:确认RCOMPAND/XCOMPAND是否被误设置为µ-law或A-law模式。
    • 检查字节序:某些情况下,需要软件进行字节交换。
  3. 问题:只有部分通道有数据,或通道数据混乱。

    • 检查多通道配置:确认RMCM/XMCM模式设置是否正确。确认RCERx/XCERx寄存器的位是否准确使能了目标通道。
    • 检查分区配置:在2分区模式下,确认RPABLK/XPABLKRPBBLK/XPBBLK是否指向了正确的通道块。RCERx/XCERx的位是对应分区内的相对通道,而非全局通道号。
    • 检查帧长度:确认RFRLEN1/XFRLEN1设置的字数是否大于或等于你希望使能的最高通道号。例如,如果你使能了通道31,那么���长度至少需要32个字。
  4. 问题:通信不稳定,偶尔丢数据。

    • 检查溢出/下溢:查询SPCR1中的RFULL(接收溢出)或XEMPTY(发送下溢)标志。这通常是因为CPU处理数据的速度跟不上McBSP的硬件速度。确保及时读取DRR或写入DXR。
    • 检查时钟抖动:如果使用外部时钟,检查其质量。过大的抖动会导致采样错误。
    • 检查中断服务程序:如果使用中断,确保ISR执行时间足够短,没有丢失后续中断。可以考虑使用DMA来搬运数据,彻底解放CPU。

6.3 与DMA协同工作

对于高速、连续的数据流(如音频),强烈建议使用DSP的DMA控制器与McBSP配合。你可以将McBSP的接收/发送事件作为DMA的触发源。这样,每收到一个数据字或每发送一个数据字,DMA会自动将其从DRR搬运到内存,或从内存搬运到DXR,完全无需CPU干预。配置时,需要注意McBSP的数据寄存器是16位还是32位,并相应设置DMA的传输宽度。同时,在多通道模式下,DMA需要搬运的是整个帧的数据,因此需要正确设置DMA的传输数据量(Burst Size)为每帧的字数。

调试McBSP是一个需要耐心和逻辑的过程。我的习惯是:先从最简单的环回测试开始(配置为内部环回或短接DX-DR引脚),确保基础配置正确;然后逐步增加复杂度,如使能内部时钟、帧同步,最后再配置多通道。每次修改少量配置,并用示波器或逻辑分析仪观察关键信号(CLK, FS, DX),是定位问题最有效的方法。这份寄存器配置指南和避坑经验,希望能帮你驯服这颗强大而复杂的通信引擎。