1. 项目概述与核心价值
如果你在嵌入式系统开发中用过SPI,大概率经历过这样的场景:主控芯片需要从传感器持续读取数据,或者向外部存储器写入大量配置信息。传统的SPI操作,每次传输都需要CPU介入——要么轮询状态标志位,要么处理中断来搬运数据。当数据量一大,或者系统实时性要求一高,CPU就会被这些琐碎的I/O操作牢牢绑住,宝贵的计算资源全耗在了“搬砖”上,真正该干的算法处理、逻辑控制反而没时间做了。这就是传统SPI在复杂应用中的瓶颈。
为了解决这个问题,德州仪器(TI)在其许多高性能微控制器(如TMS320F28x系列)中,引入了一个增强型的串行外设接口模块:多缓冲串行外设接口,也就是我们常说的MibSPI。这个名字里的“多缓冲”和“DMA”是它的灵魂。它不仅仅是一个通信接口,更是一个自带智能搬运工和管家(DMA控制逻辑)的数据高速公路收费站。一旦你设置好规则——比如“把这块内存的数据通过SPI通道1发给传感器A,收来的数据放到那块内存”——DMA和中断系统就能在后台自动、高效地完成所有数据传输和状态通知,让CPU彻底解放出来。
这篇文章,我就结合手册和实际调车经验,为你深入拆解MibSPI模块中两个最核心、也最容易让人困惑的机制:DMA和中断。我会详细解释它们在多缓冲模式下的工作原理、配置方法,以及如何避开那些我踩过的坑。无论你是正在评估芯片选型,还是已经上手调试却卡在了数据传输效率上,相信这篇近万字的干货都能给你带来清晰的思路和可直接复用的代码框架。
2. MibSPI多缓冲模式架构精解
在深入DMA和中断之前,我们必须先理解MibSPI的“多缓冲”到底是什么意思。这决定了整个数据流的管理方式,是理解后续所有高级特性的基础。
2.1 传统SPI模式 vs. 多缓冲模式
传统SPI(或称兼容模式)通常只提供一个或两个数据寄存器(如SPIDAT0,SPIBUF)。发送时,CPU把数据写入SPIDAT;接收时,CPU从SPIBUF读取数据。每个字的传输都可能需要CPU参与,效率低下。
而MibSPI的核心创新在于,它在模块内部集成了一块专用的多缓冲RAM。这块RAM被划分为多个缓冲区(Buffer),每个缓冲区都关联着一个传输组(Transfer Group, TG)。你可以把这块RAM想象成一个邮局的分拣中心,每个缓冲区就是一个专属邮箱(TX RAM用于发件,RX RAM用于收件)。
关键概念:传输组一个传输组(TG)定义了一次完整的数据传输事务。它包含了一系列属性:
- 数据源/目标:指向多缓冲RAM中特定的发送(TX)和接收(RX)缓冲区。
- 传输控制:数据长度、时钟格式、片选信号、是否使用DMA等。
- 状态与链接:当前传输状态,以及指向下一个要执行的TG的指针(实现链式传输)。
多缓冲模式的核心思想是预配置。在数据传输开始前,你可以通过CPU,提前把要发送的数据填充到TX RAM的各个缓冲区,并为每个缓冲区配置好对应的TG控制信息(比如用哪个片选、什么时钟模式)。同时,你也为接收数据预留好RX RAM的缓冲区。之后,你只需要启动传输序列,MibSPI模块就会根据TG的配置,自动地、按顺序地执行发送和接收,CPU在此期间几乎可以完全不管。
2.2 DMA在多缓冲模式中的角色与结构
DMA是多缓冲模式高效运转的引擎。手册里提到“完全消除了CPU干预的必要性”,其底气就来自于这套可编程的DMA控制逻辑。
2.2.1 DMA通道与请求线的映射逻辑
这是理解MibSPI DMA配置的关键,也是容易配置出错的地方。手册中的逻辑结构图(Figure 24-3)抽象但重要,我用更直白的方式解释一下:
DMA通道:MibSPI支持最多8个独立的DMA通道(对应SEND和RECEIVE)。每个通道都可以被独立编程,负责在系统内存(如SRAM)和MibSPI内部的多缓冲RAM之间搬运数据。注意,在多缓冲模式下,DMA的源或目的地只能是多缓冲RAM,而不能像兼容模式那样直接操作
SPIDAT0/1或SPIBUF寄存器。DMA请求线:模块提供了最多16条DMA请求线(
DMA_REQ(0)到DMA_REQ(15))。你可以把每条请求线看作一条“呼叫DMA控制器来干活”的专属热线。映射关系:核心在于“任何DMA通道的请求,都可以被编程路由到任何一条DMA请求线上”。这是通过
RXDMA_MAPx和TXDMA_MAPx寄存器(x为通道号0-7)来配置的。例如,你可以将通道0的发送完成事件映射到DMA_REQ(0),而将通道0的接收完成事件映射到DMA_REQ(1)。这样,DMA控制器就能通过不同的请求线,区分不同通道、不同方向的事件。缓冲区标识符:每个缓冲区在多缓冲RAM中都有一个唯一的
BUFID。DMA通道的配置里需要指定它服务于哪个BUFID的缓冲区。TXDMA_ENAx和RXDMA_ENAx这些使能位,就是用来激活特定缓冲区对应的DMA通道功能。
为什么这样设计?这种灵活的映射机制,使得一个复杂的SPI通信网络能够被精细化管理。假设你的系统有3个SPI从设备:一个高速ADC(设备A)、一个Flash存储器(设备B)、一个显示屏(设备C)。你可以:
- 分配DMA通道0和1给设备A(一发一收)。
- 分配DMA通道2给设备B的发送(因为可能是写入命令后读取,发送更频繁)。
- 将它们的请求分别映射到不同的DMA请求线。
- 这样,DMA控制器可以并行处理多个数据流请求,优先级也可以分别设置,避免了请求冲突和阻塞。
2.2.2 大块数据传输的实现
手册提到,每个DMA通道通过配置DMAxCTRL、DMAxCOUNT和DMACTNTLEN寄存器,能够实现单缓冲区最多32字无中断传输,甚至通过计数机制实现高达64K字的连续传输。
实操要点与配置解析:
DMAxCTRL:控制DMA传输的突发(Burst)大小。一次突发传输是DMA控制器在不释放总线的情况下连续进行的多次数据传输。设置为最大值可以减少总线仲裁开销,提升效率。但需注意,过大的突发可能会阻塞其他总线主设备(如CPU)的访问,需要根据系统总线架构权衡。DMAxCOUNT:这是一个关键寄存器。它定义了针对当前缓冲区,需要传输的数据字数量。注意,这个计数是针对BUFID所指向的那个缓冲区而言的。DMACTNTLEN:这个寄存器定义了整个DMA传输序列的总长度,或者说是需要遍历的缓冲区数量。它和DMAxCOUNT配合,实现了“传输完一个缓冲区的指定数量数据后,自动跳转到下一个缓冲区”的链式操作。
配置示例:从SPI Flash连续读取4KB数据假设SPI Flash数据位宽为8位,但我们按16位(1字=2字节)访问。4KB = 4096字节 = 2048字。
- 我们在多缓冲RAM中定义一个足够大的RX缓冲区(或循环使用多个小缓冲区)。
- 设置对应DMA通道的
DMAxCOUNT = 2048(需要传输的字数)。 - 设置
DMACTNTLEN来控制是否使用多个缓冲区链表。如果只用一个缓冲区,此处配置相对简单;如果用链表,则需要正确初始化每个缓冲区的控制字段和链接指针。 - 启动DMA和SPI传输后,DMA控制器会自动将SPI接收到的2048个字搬运到指定的系统内存,期间无需CPU干预。
注意:这里的“无中断”指的是在传输这64K字的数据块过程中,DMA控制器本身不需要CPU干预来重新配置。但传输完成或出错时,仍然可以通过中断通知CPU。这是“块传输”和“事件通知”的分离,是高效系统的典型设计。
3. MibSPI中断系统深度剖析
中断是CPU感知DMA和SPI状态的眼睛。MibSPI的中断系统设计得非常细致,支持两级向量化中断,允许你对不同重要性的事件进行分级处理。
3.1 两级向量化中断机制
MibSPI提供两个中断线,通常对应到CPU的中断优先级0(高优先级)和中断优先级1(低优先级)。几乎所有可中断的事件(错误、完成、挂起等)都可以被编程分配到这两条线的任意一条上。
这样设计的好处是“责任分离”:
- Level 1(高优先级):你可以分配传输错误(如位错误、失步、超时等)。这些错误需要立即处理,否则可能导致数据永久丢失或系统状态异常。
- Level 0(低优先级):你可以分配正常的数据传输完成(TX空、RX满、TG完成)和传输挂起中断。这些事件处理时效性要求稍低,系统可以在完成高优先级任务后从容处理。
通过SPILVL和TGINTLVL等寄存器,你可以自由地将不同中断源映射到不同级别。例如,在代码初始化时,你可能会这样配置:
// 将所有的错误中断(BITERR, DESYNC, PARITYERR, TIMEOUT, DLENERR, RXOVRN)设置为高优先级(Level 1) SpiaRegs.SPILVL.bit.BITERR_LVL = 1; SpiaRegs.SPILVL.bit.DESYNC_LVL = 1; // ... 其他错误标志同理 // 将传输完成(TG finished)和传输挂起(TG suspended)中断设置为低优先级(Level 0) SpiaRegs.TGINTLVL.bit.TG1FIN_LVL = 0; // 假设TG1完成中断 SpiaRegs.TGINTLVL.bit.TG1SUS_LVL = 0; // 假设TG1挂起中断这样一来,当错误发生时,CPU会立即跳转到高优先级中断服务程序(ISR)进行错误恢复(如重发、记录日志、报警)。而当一次数据块传输完成时,CPU则在低优先级ISR中安全地将数据从缓存区取出进行处理,不会被错误处理流程打断。
3.2 多缓冲模式下的特有中断
在多缓冲模式下,传统的“发送空”、“接收满”中断(SPIINT0中的使能位)不再使用,取而代之的是更贴合TG概念的中断:
- TG完成中断:当一个传输组(TG)的所有缓冲区数据都发送/接收完毕后触发。这是最常用的中断,用于通知CPU一批数据已经处理完毕。
- TG挂起中断:这是MibSPI一个非常实用的特性。当一个TG的某个缓冲区被配置为“挂起”模式(等待
TXFULL或RXEMPTY标志),且条件满足时触发。这常用于实现流量控制或同步操作。例如,主设备发送数据给从设备,但从设备的接收缓冲区满了(RXFULL),从设备可以挂起传输,主设备的MibSPI会触发挂起中断,从而让主设备暂停发送,等待从设备就绪。 - 接收溢出中断:当新接收到的数据要写入RX RAM的某个缓冲区,但该缓冲区的
RXEMPTY标志为0(表示旧数据还未被CPU取走)时,会发生覆盖,此时RXOVR标志置位,并可能产生中断。这是一个严重的错误中断,意味着数据丢失,通常意味着你的数据处理速度跟不上接收速度,或者DMA/中断配置有误。 - 传输错误中断:包括位错误、失步、奇偶校验错误、长度错误、超时等。这些错误标志位于
SPIFLG寄存器中。
中断向量识别: 当发生中断时,除了查看中断标志位,TGINTVECT0和TGINTVECT1寄存器会存储导致中断的TG编号。这对于管理多个并发的TG非常有用。在中断服务程序中,你应该首先读取这些向量寄存器,快速定位是哪个TG引发的中断,然后进行针对性处理。
3.3 中断处理流程与避坑指南
一个健壮的中断服务程序(ISR)应该遵循以下流程:
- 确定中断源:读取
SPIFLG寄存器检查错误标志,读取TGINTVECT0/1确定是哪个TG完成或挂起。务必在ISR开始时读取并保存这些值,因为后续的清除操作可能会改变它们。 - 处理高优先级错误:如果
SPIFLG中有错误标志置位,应立即处理。例如,超时错误可能需要重新初始化SPI通信;奇偶校验错误可能需要请求重发数据。处理完后,必须手动清除对应的错误标志位(向该位写1清零)。 - 处理正常传输事件:
- TG完成:将处理完的数据从RX缓冲区移走,或将下一批待发送数据填充到TX缓冲区。然后清除TG完成中断标志(
TGxINTFLG寄存器对应位)。 - TG挂起:检查挂起原因(通常是等待对方设备),在条件满足后(如对方缓冲区已清空),恢复被挂起的TG。
- TG完成:将处理完的数据从RX缓冲区移走,或将下一批待发送数据填充到TX缓冲区。然后清除TG完成中断标志(
- 清除中断标志:这是最关键的一步。必须按照手册要求,先处理事件,再清除标志。错误的清除顺序可能导致丢失中断或陷入死循环。对于向量化中断,清除
TGINTVECT寄存器中的向量值通常也会清除相应的中断标志。 - 中断嵌套与性能:由于有两级中断,要小心处理中断嵌套。高优先级错误ISR应尽可能短小快,避免长时间阻塞低优先级的数据处理ISR。如果低优先级ISR处理任务繁重,可以考虑在其中设置标志位,退出ISR后在主循环中处理,以减少中断关闭时间。
踩坑实录:中断标志的“顽固性”有一次调试,我的TG完成中断只触发了一次就不再触发。排查了很久,最后发现是在ISR中,我先清除了
TGINTFLG寄存器中的完成标志,然后再去读取数据。然而,在数据读取操作期间,DMA可能又完成了下一次传输(如果配置了连续模式),瞬间再次置起了完成标志。而当我退出ISR时,硬件可能已经清除了中断请求,但这个新置起的标志位留在了寄存器里,由于中断请求已应答,导致无法再次进入ISR,造成了“假死”。解决方案:确保你的“清除标志”操作是ISR中离开前的最后一个动作。或者,在清除标志前,再次检查相关状态,确保没有待处理的新事件。
4. 从零开始:MibSPI多缓冲模式配置实战
理解了原理,我们来看如何一步步配置MibSPI,实现一个基于DMA和中断的可靠数据收发例程。这里以TI C2000系列芯片为例,但思路通用。
4.1 初始化步骤详解
步骤1:模块时钟与引脚初始化首先使能SPI模块的时钟,并配置相关引脚为SPI功能(而非通用GPIO)。这通常涉及外设时钟控制寄存器和对引脚复用控制器的配置。
// 假设使用SPI-A EALLOW; // 解除寄存器保护 ClkCfgRegs.PCLKCR0.bit.SPIAENCLK = 1; // 使能SPI-A时钟 GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1; // GPIO16 配置为 SPISIMOA GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1; // GPIO17 配置为 SPISOMIA GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1; // GPIO18 配置为 SPICLKA GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1; // GPIO19 配置为 SPISTEA (片选) EDIS; // 恢复寄存器保护步骤2:配置SPI基本参数设置SPI为主机模式、时钟极性相位、波特率、数据位宽等。这些配置通常在SPICCR,SPICTL,SPIBRR等寄存器中。
SpiaRegs.SPICCR.all = 0x0047; // 复位后,设置时钟极性为0,8位数据位 SpiaRegs.SPICTL.all = 0x0006; // 使能主机模式,使能发送,关闭SPI中断(后续用多缓冲中断) SpiaRegs.SPIBRR = 59; // 设置波特率,假设LSPCLK = 30MHz,目标波特率 = 30M / (59+1) = 500kHz SpiaRegs.SPICCR.all |= 0x0080; // 释放SPI复位,开始工作步骤3:使能并配置多缓冲模式这是关键切换。将SPI从兼容模式切换到多缓冲模式。
SpiaRegs.SPIGCR1.bit.MASTER = 1; // 主机模式 SpiaRegs.SPIGCR1.bit.CLKMOD = 1; // 使用内部时钟源 SpiaRegs.SPIGCR1.bit.POWERDOWN = 0; // 退出低功耗模式 // 切换到多缓冲模式,并初始化多缓冲RAM SpiaRegs.MIBSPIE.bit.PAR_ECC_SEL = 0; // 禁用RAM奇偶校验(根据需求) SpiaRegs.MIBSPIE.bit.RAMINIT = 1; // 启动多缓冲RAM初始化 while(SpiaRegs.MIBSPIE.bit.RAMINIT == 1) { // 等待RAM初始化完成 }步骤4:定义并初始化传输组与缓冲区这是最核心的配置。我们需要在内存中定义好TG控制结构体和缓冲区,然后将其内容写入到MibSPI对应的映射寄存器区域。
- 定义TG控制字段:每个TG控制字段是一个32位的数据结构,包含片选号(
CSNR)、数据格式选择(DFSEL)、字符长度(CHARLEN)、时钟极性相位(POLARITY,PHASE)、是否保持片选(CSHOLD)、是否启用DMA(TX_DMA_EN,RX_DMA_EN)等。你需要根据通信从设备的要求仔细设置。 - 关联缓冲区:为每个TG指定其使用的TX缓冲区和RX缓冲区在RAM中的索引(
BUFID)。 - 填充数据:将待发送的数据预先写入对应的TX缓冲区。
- 写入寄存器:通过CPU将上述配置和数据写入MibSPI的
TGxREG、TX RAM和RX RAM映射区域。这些区域通常被映射到特定的内存地址,你可以像操作数组一样操作它们。
步骤5:配置DMA通道假设我们使用DMA通道1来处理TG1的发送和接收。
- 配置DMA源/目标地址:
- 发送(TX):源地址 = 系统内存中的发送数组地址,目标地址 = MibSPI TX RAM中对应缓冲区的地址。
- 接收(RX):源地址 = MibSPI RX RAM中对应缓冲区的地址,目标地址 = 系统内存中的接收数组地址。
- 配置传输量:
DMAxCOUNT设置为要传输的数据字数量。 - 配置控制模式:设置突发大小、地址递增模式(通常源和目标地址都递增)。
- 映射DMA请求:在MibSPI中,通过
TXDMA_MAP1和RXDMA_MAP1寄存器,将TG1的发送完成和接收完成事件,映射到具体的DMA请求线(例如DMA_REQ(5)和DMA_REQ(6))。 - 在DMA控制器中配置:在DMA控制器配置中,将通道1的触发源设置为对应的DMA请求线(例如5和6)。
步骤6:配置并启用中断
- 分配中断优先级:如前所述,将错误中断设为高优先级,TG完成中断设为低优先级。
- 使能中断:在MibSPI中,使能你关心的中断(如
TG1INTENA.bit.TG1FIN = 1使能TG1完成中断)。同时,在DMA控制器中使能传输完成中断(如果需要)。 - 在CPU中断控制器中:使能对应的SPI中断线(如
SPIA_INT)和DMA中断,并设置好中断服务程序(ISR)的入口地址。
步骤7:启动传输一切就绪后,通过设置TG的控制寄存器中的启动位,或者通过特定的命令寄存器,启动TG序列。
SpiaRegs.TGCTRL[1].bit.EN = 1; // 使能TG1 // 或者使用全局启动命令 SpiaRegs.SETINT.bit.TG1_START = 1; // 启动TG1传输一旦启动,DMA会自动将数据从系统内存搬至TX缓冲区,MibSPI开始发送。发送完成后,接收的数据会被DMA自动搬至系统内存。整个过程无需CPU参与,直到传输完成或出错触发中断。
4.2 关键寄存器配置速查表
下表总结了配置MibSPI DMA和中断时最关键的几组寄存器及其作用:
| 寄存器类别 | 寄存器名称(示例) | 核心功能 | 配置要点 |
|---|---|---|---|
| 模式控制 | SPIGCR1 | 全局控制,如主从模式、时钟源、低功耗、多缓冲使能。 | 确保MASTER,CLKMOD,POWERDOWN位正确设置。RAMINIT位用于初始化多缓冲RAM。 |
| DMA映射 | TXDMA_MAPx(x=0-7)RXDMA_MAPx(x=0-7) | 将指定DMA通道的发送/接收请求映射到16条DMA请求线中的某一条。 | 确保映射关系与DMA控制器中的通道触发源配置一致。避免多个通道映射到同一请求线造成冲突。 |
| DMA使能 | TXDMA_ENAxRXDMA_ENAx(位于缓冲区控制字段) | 为多缓冲RAM中的特定缓冲区启用DMA发送或接收功能。 | 需要在对应缓冲区的控制字段中设置。这是激活DMA搬运的开关。 |
| 中断使能与级别 | SPIINT0(兼容模式)TGINTENA(多缓冲模式)SPILVL,TGINTLVL | 使能各类中断,并设置它们属于中断级别0还是1。 | 多缓冲模式下主要使用TGINTENA。合理分配错误中断(高优先级)和完成中断(低优先级)。 |
| 中断标志与向量 | SPIFLGTGINTFLGTGINTVECT0/1 | 标识中断发生的原因(错误类型、哪个TG完成)。 | ISR中首先读取这些寄存器判断中断源。TGINTVECT用于快速定位是哪个TG触发中断。 |
| 传输组控制 | TGCTRL[n](n=TG编号) | 控制每个TG的启停、挂起、链接等状态。 | EN位启动TG。SUSPEND位可手动挂起TG。NEXT_TG字段用于实现TG链式传输。 |
| 缓冲区控制字段 | 位于多缓冲RAM的特定区域 | 定义每个缓冲区的具体行为:数据格式、片选、时钟、DMA使能、CSHOLD等。 | 这是配置的核心,需要根据从设备协议逐字配置。CSHOLD位对于连续传输至关重要。 |
5. 高级应用场景与疑难问题排查
掌握了基础配置,我们来看几个高级应用和常见问题。
5.1 链式传输与乒乓缓冲
这是MibSPI发挥威力的高级用法。通过配置TG的NEXT_TG字段,可以让一个TG传输完成后,自动启动下一个TG,形成传输链。结合乒乓(Ping-Pong)缓冲技术,可以实现无缝连续数据流。
实现思路:
- 定义两个TG(TG1和TG2),每个TG关联一对TX/RX缓冲区(Buffer1和Buffer2)。
- 配置TG1的
NEXT_TG指向TG2,TG2的NEXT_TG指向TG1,形成一个环。 - 启动TG1。
- 当TG1传输完成并触发中断时,在ISR中处理Buffer1的数据,同时为下一次传输填充Buffer1的新数据。此时,TG2已经在自动传输Buffer2的数据了。
- 当TG2完成中断触发时,处理Buffer2的数据并填充之,此时TG1又开始了新一轮传输。
这样,数据处理和SPI传输在时间上完全重叠,实现了带宽的100%利用,非常适合高速ADC数据流采集或实时音频流传输。
5.2 常见问题排查手册
以下是我在调试MibSPI时遇到的一些典型问题及解决方法:
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| DMA不启动,数据无法发送 | 1. DMA通道未正确使能或触发源映射错误。 2. MibSPI中对应缓冲区的 TXDMA_ENA位未设置。3. TG未启动或处于挂起状态。 4. DMA源/目标地址配置错误(如地址未对齐)。 | 1. 检查DMA控制器的通道使能位和触发源选择寄存器,确认与TXDMA_MAPx设置一致。2. 使用调试器查看对应缓冲区控制字段的 TXDMA_ENA是否为1。3. 检查 TGCTRL[x].bit.EN位是否为1,SUSPEND位是否为0。4. 检查DMA配置中的地址,确保是有效的物理地址,并且数据宽度匹配。 |
| 能发送,但接收不到数据,或数据全为0 | 1. 接收DMA未配置或映射错误。 2. RXDMA_ENA位未设置。3. SPI时钟极性相位(CPOL/CPHA)与从设备不匹配。 4. 从设备片选( SPISCS)或使能(SPIENA)信号有问题。5. 接收缓冲区 RXEMPTY标志初始状态不对(应为1表示空)。 | 1. 对照发送DMA检查接收DMA的配置和映射。 2. 检查接收缓冲区控制字段的 RXDMA_ENA位。3.这是最常见原因!用逻辑分析仪抓取SPICLK、MOSI、MISO波形,对照从设备数据手册检查时钟边沿和数据采样点是否正确。 4. 测量片选和使能引脚波形,确认时序符合从设备要求(参考 C2TDELAY,T2CDELAY等延时配置)。5. 在多缓冲RAM初始化后或每次CPU取走数据后,确保将对应RX缓冲区的 RXEMPTY标志置1。 |
| 中断不触发或只触发一次 | 1. 中断未使能(TGINTENA, CPU中断控制器)。2. 中断标志未正确清除。 3. 中断向量寄存器( TGINTVECT)读取后未自动清除或清除方式不对。4. 中断嵌套或优先级配置导致屏蔽。 | 1. 逐级检查:MibSPI模块中断使能位 -> SPI全局中断使能 -> CPU内核中断使能及向量表配置。 2.严格按照手册顺序操作:在ISR中,先读取并保存必要状态,再进行业务处理,最后清除中断标志。清除标志时,确认是对正确的位写1。 3. 查阅芯片勘误表,有些型号的芯片在中断向量处理上有特殊要求。 4. 检查中断优先级,确保高级别中断没有长时间关闭全局中断。 |
| 数据传输出现错位或字节/字顺序错误 | 1. 数据格式配置错误,如CHARLEN(字符长度)设置不对。2. 移位方向( SHIFTDIR)设置错误(MSB/LSB first)。3. CPU/DMA访问多缓冲RAM的数据对齐方式错误。 4. 发送数据未按协议要求进行右对齐填充。 | 1. 确认主从设备约定的数据位宽,并正确设置CHARLEN。2. 检查 SPIFMTx寄存器中的SHIFTDIR位,确保与从设备一致。3. 确保CPU或DMA访问缓冲区时,地址和数据类型(8位/16位/32位)与 CHARLEN匹配。对于非16位数据,要注意内存中的存放格式。4. 牢记手册强调:发送数据必须右对齐写入。对于12位数据,应写入到寄存器的低12位,高4位补0。 |
使用CSHOLD时通信异常 | 1.CSHOLD位理解错误。在主机端,它控制片选在两个连续传输间是否保持有效;在从机端,它控制是否需要在片选无效后才更新缓冲区。2. 多个从设备共用 SPIENA线时,错误配置为推挽模式。 | 1. 仔细阅读手册关于CSHOLD在主机和从机模式下的不同含义。主机模式下,设置CSHOLD=1可以让片选在一次传输后保持低电平,紧接着进行下一次传输,中间无需重新置高再置低,适合要求片选持续有效的从设备。2.重要原则:当多个从设备共用一条 SPIENA(硬件握手)线时,所有从设备的ENABLE_HIGHZ位必须设置为1(高阻模式),否则会发生总线冲突。只有单从设备系统才能使用推挽模式。 |
调试MibSPI,逻辑分析仪或示波器是必不可少的工具。首先要确保物理层的波形(时钟、数据、片选)完全正确,然后再去排查软件配置(DMA、中断、缓冲区)。很多时候,问题就出在最基础的时钟相位或者一个标志位的理解偏差上。
MibSPI模块的DMA和中断机制,初看寄存器繁多,逻辑复杂,但一旦理顺其“多缓冲RAM为中心,TG为事务单元,DMA为搬运工,中断为通知员”的设计脉络,就会发现它其实是一个结构清晰、功能强大的自动化数据引擎。它将开发者从繁琐的字节搬运中解放出来,让CPU能够专注于更有价值的应用逻辑。在需要高效、稳定、大数据量SPI通信的嵌入式项目中,花时间深入理解和用好MibSPI,绝对是值得的投资。希望这篇结合手册与实战的解析,能帮你扫清障碍,更快地驾驭这个强大的外设。