目录
A. 配置SCI基础参数与引脚
B. 配置FIFO与中断触发水位线
C. 移植生成的代码
D. 串口FIFO开发的重点:
A. 配置SCI基础参数与引脚
在工业控制(如全桥升压、逆变器)中,上位机通讯和调试是必不可少的。进入 SysConfig 的 SCI 模块:
基础通讯帧格式:设为最常用的
115200波特率,8位数据位,None无校验,1位停止位 (8-N-1)。PinMux (引脚复用):根据硬件设计分配引脚。例如将
RX分配给GPIO29,TX分配给GPIO28。Use Interrupts:勾选此项以启用 SCI 中断。
B. 配置FIFO与中断触发水位线
在 50kHz 或更高频的控制环路中,如果每收到 1 个字节就进一次中断,CPU 资源会被严重榨干。强烈建议开启 FIFO。
在 SCI 配置面板下方找到FIFO Configuration并勾选启用。
Receive FIFO interrupt Level (接收中断水位):假设你的通讯协议一帧是 8 个字节,将其下拉设置为
8/16 FULL。这意味着硬件会自动暂存前 7 个字节,直到第 8 个字节存入时,才触发一次中断通知 CPU 集中处理。Transmit FIFO interrupt Level (发送中断水位):通常设置为
0/16 EMPTY或2/16 EMPTY,意为当发送缓冲区快空时再通知 CPU 填入新数据(很多项目中发送侧直接采用轮询阻塞发送,不开中断以节省资源)。
C. 移植生成的代码
配置完成后,SysConfig 会在后台自动生成初始化代码。将board.c和board.h中的相关部分移植到你的工程中即可。
board.c 核心移植代码:
#include "board.h" void Board_init() { EALLOW; PinMux_init(); SCI_init(); INTERRUPT_init(); EDIS; } // SCI 初始化逻辑 void SCI_init(){ // 清除所有挂起的中断标志位 SCI_clearInterruptStatus(mySCI0_BASE, SCI_INT_RXFF | SCI_INT_TXFF | SCI_INT_FE | SCI_INT_OE | SCI_INT_PE | SCI_INT_RXERR); SCI_clearOverflowStatus(mySCI0_BASE); SCI_resetTxFIFO(mySCI0_BASE); SCI_resetRxFIFO(mySCI0_BASE); // 核心配置:115200, 8-N-1 SCI_setConfig(mySCI0_BASE, DEVICE_LSPCLK_FREQ, mySCI0_BAUDRATE, (SCI_CONFIG_WLEN_8|SCI_CONFIG_STOP_ONE|SCI_CONFIG_PAR_NONE)); SCI_disableLoopback(mySCI0_BASE); SCI_performSoftwareReset(mySCI0_BASE); // 启用 FIFO 并设置中断级别 SCI_enableFIFO(mySCI0_BASE); SCI_setFIFOInterruptLevel(mySCI0_BASE, SCI_FIFO_TX0, SCI_FIFO_RX8); // 触发水位:TX空,RX满8字节 // 启用中断 SCI_enableInterrupt(mySCI0_BASE, SCI_INT_RXFF); SCI_enableModule(mySCI0_BASE); } // 中断向量注册 void INTERRUPT_init(){ Interrupt_register(INT_mySCI0_RX, &mySCI0_RX_ISR); Interrupt_enable(INT_mySCI0_RX); }对应的业务代码处理模板 (需在你的 main.c 或 ISR 文件中实现)
__interrupt void mySCI0_RX_ISR(void) { uint16_t i; uint16_t rxData[8]; // 当触发此中断时,FIFO中必定已有8个字节 for(i = 0; i < 8; i++) { rxData[i] = SCI_readCharBlockingFIFO(mySCI0_BASE); } // --- 在此处执行你的通讯协议解析逻辑 --- // 清除 FIFO 接收中断标志位,准备下一次接收 SCI_clearInterruptStatus(mySCI0_BASE, SCI_INT_RXFF); Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9); }D. 串口FIFO开发的重点:
从纯软件单字节接收(如传统 STM32 做法)转到 C2000 的硬件 FIFO 架构时,极易踩坑。以下是几个致命问题与解答汇总:
1. FIFO 中断和普通的串口单字节接收中断是一个概念吗?会互相干扰吗?
答:它们在物理底层是同一个中断向量,是替换关系,绝对不会互相干扰。一旦在 SysConfig 中使能了 FIFO,普通的单字节接收中断就会失效。取而代之的是 FIFO 深度比较器接管中断触发权,只有字节数达到设定的 Level(如 8 字节)才会触发中断。
2. 如果我的一帧数据是 15 个字节,但 FIFO 中断阈值设置的是 8,剩下的 7 个字节会怎样?
答:会发生经典的尾部残留 (Stranded Bytes)现象。前 8 个字节会正常触发中断被 CPU 读走,但剩下的 7 个字节会“死”在 FIFO 仓库里。因为没有达到 8 的触发水位线,中断不会再次触发。直到上位机发送下一帧的第 1 个字节凑够 8 个,中断才会爆发,导致数据跨帧拼接,解析彻底崩溃。
3. 如果总线受到干扰,丢失了一个字节或者多出了一个噪声字节,FIFO 怎么工作?
答:硬件 FIFO 是个“没有感情的计数器”,只认数量不认内容。
多出噪声字节:原本需要 8 个有效字节,现在 7 个有效 + 1 个噪声就触发了中断,导致中断提前发生。
丢失有效字节:FIFO 停留在 7,死活不触发,必须等下一帧开头凑数,导致中断滞后发生。 这两种情况都会造成数据在 FIFO 中的物理错位 (Misalignment)。
4. 终极解法:如何彻底驾驭 FIFO 防止错位和残留?答:工业代码中通常采用以下策略:
完美匹配法:如果帧长固定(如 15 字节),直接将 RX Level 设为
15/16 FULL。超时定时器法(推荐):模拟 STM32 的 IDLE 中断。开一个 CPU 定时器,串口引脚有动静就重置定时器。一旦总线安静导致定时器超时,就在定时器中断里强行把 FIFO 里残留的零星字节全部读走。
帧头扫描 + 软件复位(抗噪必杀技):每次进中断读取数据后立刻寻找帧头(如
0xAA 0x55)。一旦发现帧头错位(说明丢包或多包),绝对不要企图拼凑数据,直接操作寄存器暴力复位 FIFO:SCI_resetRxFIFO(mySCI0_BASE); // 硬件清空并重新使能 FIFO强制清空垃圾数据,让接收器状态直接对齐到上位机的下一帧。