目录
[A. 配置SCI基础参数与引脚](#A. 配置SCI基础参数与引脚)
[B. 配置FIFO与中断触发水位线](#B. 配置FIFO与中断触发水位线)
[C. 移植生成的代码](#C. 移植生成的代码)
[D. 串口FIFO开发的重点:](#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强制清空垃圾数据,让接收器状态直接对齐到上位机的下一帧。