遇到的问题
问题的发现
最近在开发DSP和STM32之间通信的一个项目,发现当STM32突然掉电后,即使重新上电,他们之间的通信也还是不能重连。
问题排查
之后进行排查:首先使用USB转TTL模块直接连接电脑和STM32,查看串口调试助手发现可以进行通信。之后使用相同的方法连接TMS320F28379D和电脑,查看串口调试助手,发现通信失败。此时可以确定,问题出在TMS320F28379D上。这时候通过将问题复现,前后查看寄存器,发现DSP串口的寄存器变化如下:
正常通信
出错状态
在这里大概就已经能确定问题了,DSP在串口通信突然中断时,会置位RX ERROR。根据以往经验,这时候只需要在通信错误后,将相关寄存器置0即可。
相关知识
串行通信接口(SCI)模块的功能和操作。 SCI是一种双线异步串行端口,通常称为UART。 SCI模块支持CPU和使用标准非归零(NRZ)格式的其他异步外设之间的数字通信。 SCI接收器和发送器每个都有一个16级深FIFO,用于减少服务开销,每个都有自己独立的使能和中断位。 两者都可以独立操作以进行半双工通信,或同时进行全双工通信。为了指定数据完整性,SCI检查接收到的数据是否存在中断检测,奇偶校验,溢出和帧错误。 比特率可通过16位波特选择寄存器编程为不同的速度。
由RXRDY和BRKDT位产生的中断由RX / BK INT ENA位(SCICTL2,位1)控制。 RX ERROR位产生的中断由RX ERR INT ENA位(SCICTL1,位6)控制。RXERR可以通过BRKDT,FE,OE,PE标志设置。 在FIFO模式下,BRKDT中断仅通过RXERR标志。
解决方法
解决流程
1.使能SCI接收错误中断
2.当发生SCI接收错误时,进入SCI接收中断,判断标志位 RX ERROR 是否置1(如果是SCI接收错误导致进入中断, RX ERROR自然为1)
3.当 RX ERROR 置1,执行一次完整的SW RESET,退出中断
具体程序
使能接收错误中断: SCI_enableInterrupt(SCIC_BASE, SCI_INT_RXFF | SCI_INT_RXERR );
void initSCICFIFO()
{
SCI_setConfig(SCIC_BASE, DEVICE_LSPCLK_FREQ, 115200, (SCI_CONFIG_WLEN_8 |SCI_CONFIG_STOP_ONE |SCI_CONFIG_PAR_NONE));
SCI_enableModule(SCIC_BASE);
SCI_disableLoopback(SCIC_BASE);
SCI_resetChannels(SCIC_BASE);
SCI_enableFIFO(SCIC_BASE);
SCI_enableInterrupt(SCIC_BASE, SCI_INT_RXFF | SCI_INT_RXERR );
SCI_disableInterrupt(SCIC_BASE, SCI_INT_TXFF);
SCI_setFIFOInterruptLevel(SCIC_BASE, SCI_FIFO_TX1, SCI_FIFO_RX1);
SCI_performSoftwareReset(SCIC_BASE);
SCI_resetTxFIFO(SCIC_BASE);
SCI_resetRxFIFO(SCIC_BASE);
#ifdef AUTOBAUD
SCI_lockAutobaud(SCIA_BASE);
#endif
}
在中断处理函数中判断是否为错误中断触发的,如果是,就置位。
__interrupt void scicRXFIFOISR(void)
{
receivedDataC=SCI_readCharNonBlocking(SCIC_BASE);
rxStatus_C = SCI_getRxStatus(SCIC_BASE);
if((rxStatus_C & SCI_RXSTATUS_ERROR) != 0)
{
SCI_clearInterruptStatus(SCIC_BASE, SCI_INT_RXERR);
}
SCI_clearOverflowStatus(SCIC_BASE);
SCI_clearInterruptStatus(SCIC_BASE, SCI_INT_RXFF);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);
loopCounter[1]++;
}
文章评论(0条评论)
登录后参与讨论