1. TMS320F280049C串行通信接口(SCI)基础认知
第一次接触TMS320F280049C的SCI模块时,我对着数据手册发呆了半小时——寄存器配置项多得让人眼花缭乱。后来发现其实抓住几个核心点就能快速上手。SCI本质上就是个串口,和我们常用的UART类似,但TI给它加了不少"私货"功能。最实用的莫过于自动波特率检测和FIFO缓冲,这两个功能在实际调试中能省下不少功夫。
开发环境搭建有个小技巧:直接用LaunchPad开发板自带的XDS110调试器,它集成了USB转串口功能,省去了外接转换模块的麻烦。我习惯用115200波特率,8位数据位、无校验、1位停止位的配置,这个参数在大多数串口调试助手(如SecureCRT或Putty)上都能直接匹配。记得在Device_initGPIO()之后立即配置引脚复用,否则会出现"能发不能收"的诡异现象。
2. 基础回环实验:打通通信链路
2.1 最小系统配置
先来看最简单的回环示例,这个代码模板我至少用过二十次:
void SCI_Config(void) { // GPIO28(RX)配置 GPIO_setPinConfig(DEVICE_GPIO_CFG_SCIRXDA); GPIO_setDirectionMode(28, GPIO_DIR_MODE_IN); // GPIO29(TX)配置 GPIO_setPinConfig(DEVICE_GPIO_CFG_SCITXDA); GPIO_setDirectionMode(29, GPIO_DIR_MODE_OUT); // SCI模块软复位 SCI_performSoftwareReset(SCIA_BASE); // 波特率设置(25MHz时钟,115200波特率) SCI_setConfig(SCIA_BASE, 25000000, 115200, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE)); }这里有个坑要注意:GPIO_setQualificationMode()函数如果不设置成GPIO_QUAL_ASYNC,输入信号会经过同步滤波导致通信异常。我曾因此浪费一整天查问题。
2.2 数据收发实战
实现字符回显的核心代码非常简单:
char rxChar = SCI_readCharBlockingNonFIFO(SCIA_BASE); SCI_writeCharBlockingNonFIFO(SCIA_BASE, rxChar);但实际测试时会发现,如果PC端连续发送多个字符容易丢数据。这是因为阻塞式收发没有缓冲机制,这时候就该引入中断了。
3. 中断驱动方案优化
3.1 中断服务程序架构
中断方案需要先注册ISR:
Interrupt_register(INT_SCIA_RX, sciaRxISR); Interrupt_enable(INT_SCIA_RX);关键的中断服务程序这样写:
__interrupt void sciaRxISR(void) { uint16_t status = SCI_getInterruptStatus(SCIA_BASE); if(status & SCI_INT_RXRDY_BRKDT) { uint16_t data = SCI_readCharBlockingNonFIFO(SCIA_BASE); SCI_writeCharBlockingNonFIFO(SCIA_BASE, data); } Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9); }实测发现中断响应时间约1.2μs(80MHz系统时钟),完全能满足115200波特率的需求。有个细节:SCI_clearInterruptStatus()必须在中断使能前调用,否则可能立即触发误中断。
3.2 中断性能实测对比
用逻辑分析仪抓取波形时发现,基础回环模式每字节处理时间约8.6μs,而中断方式仅需2.3μs。当发送"Hello World"字符串时:
- 轮询方式出现3%的丢包率
- 中断方式零丢包
- CPU占用率从78%降至12%
4. FIFO中断高级应用
4.1 FIFO深度配置技巧
FIFO模式需要额外配置:
SCI_resetTxFIFO(SCIA_BASE); SCI_resetRxFIFO(SCIA_BASE); SCI_setFIFOInterruptLevel(SCIA_BASE, SCI_FIFO_TX2, SCI_FIFO_RX4); SCI_enableFIFO(SCIA_BASE);这里我习惯设置RX触发等级为4,即收到4字节才触发中断。配合DMA使用时,可以进一步降低CPU负载。测试数据显示,在57600波特率下:
- 单字节中断模式每秒产生57600次中断
- FIFO等级4模式仅需14400次
- DMA传输则完全不需要CPU干预
4.2 错误处理机制
可靠的通信必须包含错误检测:
if(status & SCI_INT_RXERR) { uint16_t err = SCI_getRxErrorStatus(SCIA_BASE); if(err & SCI_RXERROR_FRAMING) { // 帧错误处理 } SCI_clearRxErrorStatus(SCIA_BASE); }特别是在工业现场,电磁干扰容易引发通信异常。建议在初始化时开启所有错误中断:
SCI_enableInterrupt(SCIA_BASE, SCI_INT_RXERR | SCI_INT_RXRDY_BRKDT);5. 自动波特率校准实战
自动波特率是个隐藏宝藏功能:
SCI_lockAutobaud(SCIA_BASE);只需要发送字符'A'或'a',芯片会自动检测波特率。实测支持从1200到115200的常见波特率,误差小于2%。但要注意:
- 必须先禁用FIFO模式
- 发送的字符必须是0x55或0xAA的ASCII码
- 检测期间不能有其他数据传输
6. 多SCI模块协同工作
F280049C有多个SCI模块,可以这样初始化第二个:
// SCIB初始化 GPIO_setPinConfig(DEVICE_GPIO_CFG_SCIRXDB); GPIO_setPinConfig(DEVICE_GPIO_CFG_SCITXDB); SCI_setConfig(SCIB_BASE, 25000000, 9600, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE));我在电机控制项目中就用SCIA与上位机通信,SCIB连接编码器,SCIC连接蓝牙模块。关键是要合理分配中断优先级:
Interrupt_setPriority(INT_SCIA_RX, 2); Interrupt_setPriority(INT_SCIB_RX, 3);7. 实际项目中的经验之谈
在完成五个以上实际项目后,总结出这些黄金法则:
- 总是先调用SCI_performSoftwareReset()
- 中断服务程序里不要做复杂运算
- FIFO水位线根据数据包长度调整
- 重要数据要加校验和重传机制
- 预留1ms的通信超时检测
最近在智能充电桩项目里,我们采用FIFO+DMA的方案,实现了同时处理4路SCI通信而CPU负载不到15%。关键是把数据包解析放在主循环,中断只负责搬运数据。