新闻详情

新闻详情

首页 / 资讯中心 / 详情

C28x DSP SCI增强功能:FIFO与自动波特率检测实战解析

发布时间:2026/7/21 8:03:30
C28x DSP SCI增强功能:FIFO与自动波特率检测实战解析
1. 项目概述与核心价值在嵌入式系统开发尤其是工业控制、电机驱动和电力电子领域德州仪器TI的C28x系列DSP因其强大的实时处理能力和丰富的外设而备受青睐。串行通信接口SCI作为其与上位机、其他控制器或传感器进行异步数据交换的“咽喉要道”其性能直接影响到整个系统的响应速度和可靠性。如果你正在使用C28x进行开发可能已经体验过传统SCI模式下频繁的中断服务程序ISR对CPU时间的“掠夺”——每收发一个字节就触发一次中断在高速或大数据量通信时CPU几乎被“绑死”在通信任务上无暇顾及其他关键的控制算法。这正是C28x SCI模块的增强功能大显身手的地方。它并非简单的UART而是集成了两大“神器”FIFO操作和自动波特率检测。FIFO就像在CPU和串口硬件之间修建了一个小型仓库缓冲区。发送时你可以一次性把十几个字节的数据“搬”进仓库然后让硬件自己慢慢发货期间CPU可以去处理其他任务只在仓库快空时收到一次提醒中断。接收亦然数据先堆在仓库里攒到一定数量再通知CPU来批量取走。这直接将中断频率降低了十几倍解放了宝贵的CPU资源。而自动波特率检测则像是一个智能的通信“翻译官”在上电或连接初期它能自动侦测对方设备的通信速率波特率并完成自我配置省去了手动计算和设置波特率寄存器的麻烦尤其适合需要与多种不同设备适配或进行Bootloader升级的场景。本文将从一个资深嵌入式工程师的视角彻底拆解C28x SCI的这两项增强功能。我不会仅仅复述数据手册的寄存器描述而是结合我多年在电机控制和逆变器开发中实际使用SCI-FIFO和自动波特率的经验深入讲解其工作原理、配置步骤、避坑指南以及性能优化技巧。无论你是刚接触C28x的新手还是希望优化现有通信架构的老手这篇文章都将提供从原理到实战的完整参考。2. 核心增强功能深度解析2.1 FIFO机制从“来一件发一件”到“批处理”要理解FIFO带来的变革我们得先看看传统SCI非FIFO模式是怎么工作的。想象一下一个没有缓冲区的快递站每来一个包裹一个字节的数据快递员CPU就必须立刻停下手中的活亲自把这个包裹贴上标签写入SCITXBUF然后看着它被送走移位发出。接收端也一样每收到一个包裹快递员就得立刻跑去门口签收从SCIRXBUF读取。这种“来一件处理一件”的模式在数据流密集时会让快递员疲于奔命效率低下。C28x的SCI FIFO功能本质上就是给这个快递站配上了16个格口的智能货架16级深度FIFO。其核心改进体现在以下几点1. 数据流重构与中断合并在FIFO模式下数据流路径发生了变化。发送时数据不再直接写入单一的发送缓冲器SCITXBUF就等待发送。实际上SCITXBUF变成了一个“中转站”。当你写入数据时数据首先被存入发送FIFOTX FIFO队列。发送移位寄存器TXSHF会直接从TX FIFO的头部取出数据进行串行化发送而非从SCITXBUF获取。这意味着你可以连续写入最多16个字节到FIFO中硬件会自动按序发送。中断不再基于单个字节的发送完成TXRDY而是基于FIFO的“库存水位”。你可以设置一个触发水平例如当FIFO中剩余数据少于4个时产生中断这样CPU只需在FIFO快空时一次性补充多个数据极大减少了中断上下文切换的开销。2. 可编程延迟传输FFTXDLY这是一个非常实用但常被忽略的特性由SCIFFCT寄存器的低8位FFTXDLY7-0控制。它定义了FIFO中每个字字节传输到发送移位寄存器之间的延迟单位是波特率时钟周期数0-256。这有什么用呢它模拟了硬件流控中的“忙”状态。对于一些老旧的、处理速度慢的UART设备如果C28x以最高速率连续发送数据对方可能因为缓冲区溢出而丢失数据。通过设置一个合适的FFTXDLY值你可以在每个字节之间人为插入一段空闲时间相当于对数据流进行“节流”确保接收端能跟上。例如在9600波特率下一个字节传输约需1ms。如果你设置FFTXDLY为10个波特时钟那么在每个字节之间就会增加大约0.1ms的间隔从而降低平均数据速率。3. 状态指针与灵活复位SCIFFTX和SCIFFRX寄存器中的TXFFST/RXFFST位段位12-8实时指示着发送和接收FIFO中当前有效数据的数量。这为软件流控和动态调整中断策略提供了可能。例如你可以在发送函数中检查TXFFST如果FIFO未满就直接写入如果满了则等待或采用其他策略。此外通过TXFIFORESET和RXFIFORESET位可以独立复位发送或接收FIFO的指针清空FIFO而不会影响整个SCI模块的其他设置这比使用全局的SCIRST或SWRESET更加精细和安全。2.2 自动波特率检测硬件级的“自适应”握手自动波特率检测Auto-Baud Detection功能旨在解决嵌入式系统特别是基于SCI的Bootloader中一个经典难题如何在不预先知道主机波特率的情况下建立通信传统方法需要尝试多种波特率或依赖固定的低速默认值既不可靠又繁琐。C28x的硬件自动波特率检测逻辑巧妙地利用了字符‘A’0x41或‘a’0x61的位模式。为什么是‘A’因为其ASCII码的二进制形式0100 0001具有对称性和清晰的上升沿/下降沿便于硬件计时测量。其工作流程可以概括为“使能、等待、锁定、应用”四个阶段。硬件工作原理当使能自动波特率检测CDC1后硬件开始监控SCIRXD引脚。一旦检测到起始位内部的波特率测量电路就会启动一个高精度计数器用于测量从起始位下降沿到第一个数据位LSB采样点之间的时间间隔或者更常见的是测量整个字符‘A’包括起始位、8个数据位、停止位的完整位时间。字符‘A’的位序列起始位-1-0-0-0-0-0-1-0-停止位提供了多个边沿用于校准。硬件通过测量这些边沿之间的时间反向推算出准确的波特率时钟周期数并自动更新波特率寄存器SCIHBAUD和SCILBAUD的值。关键寄存器协同整个过程由SCIFFCT寄存器中的三个关键位控制CDC (位13) 校准检测控制位。置1使能自动波特率检测逻辑。ABD (位15) 自动波特率检测完成标志位。硬件检测成功后自动置1。ABDCLR (位14) ABD标志清除位。软件写1可清除ABD标志。其核心交互逻辑是软件先设置CDC1并清除ABD通过写ABDCLR1然后等待。当硬件成功锁定波特率后会置位ABD并产生一个发送FIFO中断TXINT——注意这里是TXINT而不是接收中断。这是一个非常重要的设计细节意味着自动波特率检测流程的完成通知是通过发送中断线来完成的。在中断服务程序中软件必须读取ABD状态确认成功后清除ABD标志ABDCLR1并立即将CDC位清零以退出自动波特率检测模式防止后续正常数据被误判为波特率检测字符。3. 实战配置与编程指南理解了原理我们进入实战环节。下面我将以TI的C2000 DriverLib库函数结合寄存器操作的方式展示如何配置和使用这些功能。假设我们使用SCI-A目标波特率为115200LSPCLK低速外设时钟为50MHz。3.1 FIFO模式配置与数据收发首先我们需要完成SCI模块的基础初始化包括引脚复用、基本通信参数设置等这部分与标准SCI相同在此不赘述。重点在于FIFO相关的增强配置。步骤1计算并设置波特率根据公式BRR LSPCLK / (SCI Asynchronous Baud * 8) - 1代入BRR 50,000,000 / (115200 * 8) - 1 ≈ 53.25取整后BRR 53。将其分解为高8位和低8位写入SCIHBAUD和SCILBAUD。// 使用DriverLib配置波特率 SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 115200, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE));步骤2使能FIFO模式并进行关键配置这是核心步骤需要配置SCIFFTX、SCIFFRX和SCIFFCT三个增强功能寄存器。#include “driverlib.h” void SCI_FIFO_Init(void) { // 1. 首先确保SCI处于复位状态以安全配置FIFO。SCIRST位写0会复位FIFO和部分标志位。 // 注意SCIRST在SCIFFTX[15]写0复位写1使能。DriverLib可能没有直接函数需操作寄存器。 HWREG(SCIA_BASE SCI_O_FFTX) ~SCI_FFTX_SCIRST; // 2. 使能FIFO增强功能 (SCIFFENA) HWREG(SCIA_BASE SCI_O_FFTX) | SCI_FFTX_SCIFFENA; // 3. 配置发送FIFO // - 复位发送FIFO指针 (TXFIFORESET先低后高) HWREG(SCIA_BASE SCI_O_FFTX) ~SCI_FFTX_TXFIFORESET; DELAY_US(10); // 短暂延时确保复位完成 HWREG(SCIA_BASE SCI_O_FFTX) | SCI_FFTX_TXFIFORESET; // - 设置发送FIFO中断触发水平。例如当FIFO中数据少于4个时触发中断。 // TXFFIL位域在寄存器低5位默认值为0。我们设置为16-412不对。 // 注意TXFFIL是触发水平值。当TXFFST当前FIFO数据量 TXFFIL时触发中断。 // 我们希望FIFO快空比如剩下4个或更少时触发那么TXFFIL应设为4。 // 但寄存器描述是“小于或等于”所以设为3表示当数据量3时触发。 uint32_t temp HWREG(SCIA_BASE SCI_O_FFTX); temp ~SCI_FFTX_TXFFIL_M; // 清除原有水平设置 temp | (3 SCI_FFTX_TXFFIL_S); // 设置TXFFIL 3 HWREG(SCIA_BASE SCI_O_FFTX) temp; // - 使能发送FIFO中断 (TXFFIENA) HWREG(SCIA_BASE SCI_O_FFTX) | SCI_FFTX_TXFFIENA; // 4. 配置接收FIFO // - 复位接收FIFO指针 HWREG(SCIA_BASE SCI_O_FFRX) ~SCI_FFRX_RXFIFORESET; DELAY_US(10); HWREG(SCIA_BASE SCI_O_FFRX) | SCI_FFRX_RXFIFORESET; // - 设置接收FIFO中断触发水平。例如当FIFO中数据达到8个时触发中断。 // RXFFIL位域默认值为0x1F(31)即几乎满才触发。我们改为8。 // 注意RXFFIL是触发水平值。当RXFFST当前FIFO数据量 RXFFIL时触发中断。 temp HWREG(SCIA_BASE SCI_O_FFRX); temp ~SCI_FFRX_RXFFIL_M; temp | (8 SCI_FFRX_RXFFIL_S); // 设置RXFFIL 8 HWREG(SCIA_BASE SCI_O_FFRX) temp; // - 使能接收FIFO中断 (RXFFIENA) HWREG(SCIA_BASE SCI_O_FFRX) | SCI_FFRX_RXFFIENA; // 5. 可选配置发送延迟FFTXDLY。例如在每个字节间插入16个波特时钟的延迟。 // 这可以用于与低速设备通信。如果不需要保持为0即可。 HWREG(SCIA_BASE SCI_O_FFCT) 16; // 设置FFTXDLY 16 // 6. 最后重新使能SCI FIFO模块 (SCIRST置1) HWREG(SCIA_BASE SCI_O_FFTX) | SCI_FFTX_SCIRST; // 7. 使能SCI模块的接收器和发送器标准SCI配置 SCI_enableModule(SCIA_BASE); SCI_enableTx(SCIA_BASE); SCI_enableRx(SCIA_BASE); // 8. 使能PIE级和CPU级中断此处以发送中断为例 Interrupt_register(INT_SCIA_TX, SCIA_TX_ISR); Interrupt_enable(INT_SCIA_TX); SCI_enableInterrupt(SCIA_BASE, SCI_INT_TXFF); // 使能TX FIFO中断 }步骤3编写中断服务程序ISR与数据搬运配置好中断后关键在于高效、安全的ISR设计。// 发送FIFO中断服务程序 __interrupt void SCIA_TX_ISR(void) { uint32_t status SCI_getInterruptStatus(SCIA_BASE); // 检查是否是TX FIFO中断TXFFINT标志 if(status SCI_INT_TXFF) { // 1. 读取当前FIFO状态看还有多少数据待发送 uint16_t tx_fifo_st (HWREG(SCIA_BASE SCI_O_FFTX) SCI_FFTX_TXFFST_M) SCI_FFTX_TXFFST_S; // 2. 计算需要填充的数据量FIFO深度(16) - 当前数据量 - 触发水平(3) // 更稳健的做法是判断如果当前数据量小于某个阈值就进行填充。 if(tx_fifo_st 3) { // 如果数据量小于等于触发水平 // 假设我们有一个全局的发送数据队列 txQueue while((!isTxQueueEmpty()) (tx_fifo_st 16)) { uint16_t data popFromTxQueue(); // 从应用层队列取数据 SCI_writeCharNonBlocking(SCIA_BASE, data); // 非阻塞写入FIFO tx_fifo_st; } } // 3. 清除TX FIFO中断标志。注意必须写1到TXFFINTCLR位来清除TXFFINT标志。 HWREG(SCIA_BASE SCI_O_FFTX) | SCI_FFTX_TXFFINTCLR; } // 清除PIE组应答位 Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9); } // 接收FIFO中断服务程序类似 __interrupt void SCIA_RX_ISR(void) { uint32_t status SCI_getInterruptStatus(SCIA_BASE); if(status SCI_INT_RXFF) { // 接收FIFO中断 // 1. 读取当前接收FIFO状态看有多少数据可读 uint16_t rx_fifo_st (HWREG(SCIA_BASE SCI_O_FFRX) SCI_FFRX_RXFFST_M) SCI_FFRX_RXFFST_S; // 2. 批量读取数据 for(int i 0; i rx_fifo_st; i) { uint16_t data SCI_readCharNonBlocking(SCIA_BASE); // 非阻塞读取 // 注意SCI_readCharNonBlocking会返回16位数据低8位是数据高位可能包含错误标志 if(data SCI_FE) { /* 处理帧错误 */ } if(data SCI_OE) { /* 处理溢出错误 */ } if(data SCI_PE) { /* 处理奇偶校验错误 */ } uint8_t pure_data data 0x00FF; pushToRxQueue(pure_data); // 存入应用层队列 } // 3. 清除RX FIFO中断标志 HWREG(SCIA_BASE SCI_O_FFRX) | SCI_FFRX_RXFFINTCLR; } // 检查接收错误中断RXERR if(status SCI_INT_RXERR) { // 处理接收错误帧错误、溢出等 uint16_t error_status SCI_getRxStatus(SCIA_BASE); // ... 错误处理逻辑 // 错误标志通常需要通过软件复位SWRESET或读取SCIRXBUF来清除具体看错误类型 } Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9); }关键提示中断标志清除机制FIFO中断标志TXFFINT和RXFFINT的清除方式比较特殊。它们不是通过读取数据自动清除的也不是通过写0清除的。你必须向对应的“清除位”TXFFINTCLR或RXFFINTCLR写入1才能将其清除。这是一个常见的出错点如果忘记清除或清除方式不对会导致中断只触发一次或不断重入。3.2 自动波特率检测流程实现自动波特率检测通常用于系统初始化阶段例如在Bootloader中。下面是一个典型的实现流程。步骤1初始化SCI并进入自动波特率检测模式bool SCI_AutoBaud_Detect(uint32_t sciBase) { // 1. 确保SCI和FIFO处于复位/初始状态 HWREG(sciBase SCI_O_FFTX) 0; // 写0会清除SCIRST和SCIFFENA复位FIFO // 进行基本的SCI引脚和模块使能配置此处省略... SCI_disableModule(sciBase); // 先禁用模块 // 2. 配置SCI为8位数据位1位停止位无校验这是自动波特率检测的典型配置 SCI_setConfig(sciBase, DEVICE_LSPCLK_FREQ, 9600, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE)); // 注意初始波特率可以设为一个较低的值如9600但这不是必须的因为后面会被覆盖。 // 3. 使能FIFO自动波特率检测需要在FIFO使能下工作根据手册SCIRST需为1且逻辑关联TXINT HWREG(sciBase SCI_O_FFTX) | SCI_FFTX_SCIFFENA; HWREG(sciBase SCI_O_FFTX) | SCI_FFTX_SCIRST; // 使能SCI FIFO模块 // 4. 配置自动波特率检测控制寄存器SCIFFCT // a. 清除之前的ABD标志写1到ABDCLR HWREG(sciBase SCI_O_FFCT) | SCI_FFCT_ABDCLR; // b. 使能自动波特率检测置位CDC HWREG(sciBase SCI_O_FFCT) | SCI_FFCT_CDC; // 5. 使能SCI接收器开始监听 SCI_enableModule(sciBase); SCI_enableRx(sciBase); // 注意此时不要使能发送器我们只接收主机发来的‘A’或‘a’ // 6. 使能TX FIFO中断因为自动波特率检测完成是通过TXINT通知的 SCI_enableInterrupt(sciBase, SCI_INT_TXFF); // 配置PIE和CPU中断略 // 7. 等待中断发生或采用轮询方式检测ABD位 // 轮询方式示例带超时 uint32_t timeout 1000000; // 超时计数 while((timeout-- 0) ((HWREG(sciBase SCI_O_FFCT) SCI_FFCT_ABD) 0)) { // 空循环等待 } if(timeout 0) { // 超时自动波特率检测失败 HWREG(sciBase SCI_O_FFCT) ~SCI_FFCT_CDC; // 禁用CDC return false; } // 8. 检测成功ABD位被硬件置1 // 清除ABD标志 HWREG(sciBase SCI_O_FFCT) | SCI_FFCT_ABDCLR; // 非常重要禁用自动波特率检测逻辑清除CDC位 HWREG(sciBase SCI_O_FFCT) ~SCI_FFCT_CDC; // 9. 清空接收缓冲区读取掉主机发送的‘A’或‘a’ // 由于FIFO可能已使能需要读取SCIRXBUF直到RXFFST为0 while(SCI_getRxFifoStatus(sciBase) ! SCI_FIFO_RX0) { uint16_t dummy SCI_readCharBlockingFIFO(sciBase); // 或使用非阻塞读取 } // 10. 此时波特率寄存器已被硬件自动更新。 // 你可以选择读取新的波特率值进行验证或者直接开始正常通信。 // 验证示例计算实际波特率 uint16_t brr SCI_getBaudRate(sciBase); // 此函数DriverLib可能不直接提供需从寄存器计算 // uint32_t calculatedBaud DEVICE_LSPCLK_FREQ / ((brr 1) * 8); // DEBUG_PRINT(“Auto-baud detected. BRR%d, Baud≈%d\n”, brr, calculatedBaud); // 11. 重新配置SCI中断如果需要使能发送器开始正常通信。 SCI_enableTx(sciBase); // 重新配置FIFO中断触发水平等见3.1节 return true; }重要注意事项自动波特率检测的局限性数据手册明确指出在高波特率通常超过100k baud下由于信号边沿斜率Slew Rate受收发器和连接器性能影响自动波特率检测可能不可靠。因此TI推荐在Bootloader中使用较低的波特率如9600完成初始的波特率锁定和握手。一旦主机和DSP的应用程序建立联系主机可以通过命令通知DSP切换到更高的、预定的波特率进行后续高速通信。这是一种更稳健的“两步走”策略。4. 高级应用技巧与避坑指南掌握了基本配置后如何让SCI增强功能在复杂系统中稳定、高效地运行下面分享一些从实际项目中总结的经验和常见问题的解决方法。4.1 FIFO深度与中断触发水平的权衡艺术设置TXFFIL和RXFFIL不是随便填个数就行它需要在CPU中断开销和通信实时性/缓冲区利用率之间取得平衡。发送FIFO (TXFFIL)设置过低如0或1中断非常频繁几乎退化到非FIFO模式失去了批处理优势。设置过高如14或15中断次数少但可能导致FIFO完全清空后CPU未能及时补充数据造成发送总线出现不必要的空闲间隙降低了平均带宽利用率。对于连续流数据设置在水位一半左右如7或8是个不错的起点。对于突发性数据可以设低一些确保尽快通知CPU准备下一批数据。接收FIFO (RXFFIL)设置过低如1或2数据刚来一两个字节就触发中断CPU响应及时但中断频繁。设置过高如默认的31但FIFO深度只有16所以实际最大为15或16几乎等到FIFO满了才中断。这虽然中断次数最少但意味着数据在FIFO中停留时间最长增加了接收端处理的延迟。对于要求快速响应的控制指令这种延迟是不可接受的。策略建议对于命令-响应型协议如Modbus接收FIFO中断水平可以设得较低例如2或4以便及时处理短帧命令。对于纯粹的数据流传输如数据日志可以设得较高例如12或14以最大化每次中断的数据吞吐量。一个进阶技巧动态调整触发水平。在通信初期或处理关键指令时使用低触发水平保证低延迟在进入稳定大数据流传输后切换到高触发水平以降低CPU负载。这可以通过在ISR或主循环中根据通信状态修改RXFFIL/TXFFIL寄存器来实现。4.2 错误处理与FIFO溢出管理在FIFO模式下错误处理需要格外小心。接收错误帧错误FE、奇偶错误PE、溢出错误OE仍然会触发接收错误中断如果使能了RXERRINTENA但中断源是共同的RXINT。FIFO溢出 (RXFFOVF)这是FIFO模式下特有的严重错误。当接收FIFO已满16个数据但又有新数据到来时RXFFOVF标志位会被置1并且最早的数据会被覆盖丢失。关键点手册指出RXFFOVF标志和RXFFIL中断是“或”的关系。这意味着在溢出发生时即使RXFFST未达到RXFFIL水平也可能因为RXFFOVF置位而触发RXINT中断。更关键的是在清除中断标志时必须同时清除RXFFINT和RXFFOVF否则可能会阻止后续中断的产生。安全的清除操作如下// 在RX ISR中处理溢出 if(HWREG(SCIA_BASE SCI_O_FFRX) SCI_FFRX_RXFFOVF) { // 1. 处理溢出错误记录日志、复位通信等 handleOverflowError(); // 2. 必须同时清除RXFFINT和RXFFOVF标志 HWREG(SCIA_BASE SCI_O_FFRX) | SCI_FFRX_RXFFINTCLR; // 写1清除RXFFINT HWREG(SCIA_BASE SCI_O_FFRX) | SCI_FFRX_RXFFOVRCLR; // 写1清除RXFFOVF }FIFO中的错误标志在非FIFO模式错误标志FE, PE在SCIRXST寄存器中。在FIFO模式每个存储在FIFO中的数据字都附带了自己的错误标志位SCIFFFE和SCIFFPE它们位于从SCIRXBUF读取的16位数据的高位位15和位14。因此在FIFO模式下读取数据后必须检查这些位来判断该特定字节是否有错误。uint16_t rxData SCI_readCharNonBlocking(SCIA_BASE); uint8_t data rxData 0x00FF; // 提取数据字节 if(rxData SCI_FFFE) { // SCI_FE是帧错误标志但FIFO模式下要用SCIFFFE // 处理该字节的帧错误 } if(rxData SCI_FFPE) { // 处理该字节的奇偶错误 }4.3 自动波特率检测的实战陷阱与对策字符匹配问题自动波特率检测只识别字符‘A’ (0x41) 或 ‘a’ (0x61)。主机必须发送其中之一且必须是通信开始后的第一个字符。发送其他字符或先发送其他字节如同步头0x55会导致检测失败。确保你的主机端协议严格遵守此要求。CDC位未及时清除这是最常见的错误。在ABD置位、进入中断并清除ABD标志后必须立即将CDC位写0退出自动波特率检测模式。如果忘记清除SCI会持续尝试进行波特率检测干扰后续的正常数据通信导致数据接收全部错乱。高波特率下的不稳定性如前所述尽量避免在高于115200的波特率下依赖自动波特率检测。稳妥的方案是Bootloader使用自动波特率检测在低波特率如9600下建立连接然后通过一个已知的、简单的握手协议由主机命令DSP切换到应用程序设定的高波特率。中断冲突自动波特率检测成功时产生的是TXINT发送FIFO中断。如果你的应用程序同时使能了发送FIFO中断在自动波特率检测阶段TX FIFO中断服务程序可能会被错误调用。因此在自动波特率检测流程中最好先禁用其他的TX FIFO中断使能TXFFIENA或者在中斷服務程序中通过检查ABD标志位来区分是自动波特率完成中断还是正常的发送空中断。4.4 性能优化与系统集成建议DMA与FIFO的强强联合对于极高速度或极低CPU占用率要求的场景可以考虑将SCI FIFO与DMA直接存储器访问控制器结合使用。C28x的DMA可以配置为与SCI的TXFFIL和RXFFIL事件联动。例如当TX FIFO数据量低于某个水平时触发DMA自动从内存搬运一批数据到SCI的发送缓冲区当RX FIFO数据量高于某个水平时触发DMA自动将数据从FIFO搬移到内存。这样可以将CPU从数据搬运工作中完全解放出来仅需处理协议解析等高层逻辑。双缓冲区的应用层设计即使在FIFO模式下也建议在应用层实现一个软件环形缓冲区Ring Buffer。ISR只负责快速地将FIFO数据倒入环形缓冲区或从环形缓冲区取出数据填入FIFO。主循环或后台任务则从容地从环形缓冲区中处理数据。这种“硬件FIFO软件缓冲区”的双重缓冲设计能有效解耦高速硬件中断和相对低速的应用处理提高系统整体的鲁棒性和响应能力。功耗考量在低功耗应用中频繁的SCI中断会阻止CPU进入低功耗模式。通过合理设置FIFO中断触发水平让CPU在一次中断中处理更多数据然后可以进入更深的休眠状态从而降低平均功耗。例如将RXFFIL设置为14让CPU在FIFO几乎满时才被唤醒一次处理大量数据后再次休眠。
网站建设 高端定制 企业官网