项目上通过普通SCI串口在两个DSP28335之间进行通讯,一主一从,主机向从机发送指令,触发从机SCI接收中断,在中断中执行数据包判断和存储,数据处理和回复在主循环进行,未使用FIFO,轮询方式进行发送。
1:主从同时开机,主从机通讯异常,主机发送正常,从机无法进行回复,串口单独调试从机依然无法回复,排查出从机在开机后有未知数据触发了接收中断,后续无法被触发。
2:主机先开,从机后开,通讯正常。
3. 从机先开,主机后开,通讯异常。
在13情况下,SCI中断会在成功进入中断一次后再也进不去中断,但程序并没有跑飞,主循环和AD控制中断仍在正常运行,也在正常运行。查看SCI寄存器发现,在主机开机但还没开始主动发送命令时从机接收端会莫名多出来若干字节数据。错误字节数据出现之后,就再也无法进入SCI接收中断,同时可以观察到SCI寄存器SCIRXST的第3位(OE)溢出错误标志 ,第4位(FE)帧错误标志和第7位(RX ERROR,数值为第2、3、4位寄存器或运算结果)SCI接收器错误标志为1。正常情况下三个寄存器都应该为0。
据此判断是SCI出现接收错误,导致进不去SCI接收中断。查阅相关资料,发现要想解决发生错误导致错误标志位置位的问题,需要执行一次完整的SW RESET((SCICTL1)的第5位)。
解决方案:
1.使能SCI接收错误中断
2.当发生SCI接收错误时,进入SCI接收中断,判断标志位 RX ERROR 是否置1(如果是SCI接收错误导致进入中断, RX ERROR自然为1)
3.当 RX ERROR 置1,执行一次完整的SW RESET,退出中断
错因分析:
通过以上3步,程序可以继续正常进入SCI接收中断,SCI通讯恢复正常。由于通讯程序并没有改动,考虑是开机时环境电磁干扰导致的错误。
附修改后的代码
void Init_Scia(void)
{
EALLOW;
SysCtrlRegs.PCLKCR0.bit.SCIAENCLK = 1; // SCI-A
EDIS;
SciaRegs.SCICCR.all =0x0007; // 1 stop bit, No loopback
// No parity, 8 char bits,
// async mode, idle-line protocol
SciaRegs.SCICTL1.all =0x0003; // enable TX,RX, internal SCICLK,
// Disable RX ERR, SLEEP, TXWAKE
SciaRegs.SCICTL2.all =0x0003;
SciaRegs.SCICTL2.bit.TXINTENA =0;
SciaRegs.SCICTL2.bit.RXBKINTENA =1;
SciaRegs.SCICTL1.bit.RXERRINTENA=1; //使能错误接收中断
SciaRegs.SCIHBAUD =0x0000;
SciaRegs.SCILBAUD =SCI_PRD;
SciaRegs.SCICCR.bit.LOOPBKENA =0; // disable loop back
SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
}
interrupt void SCIRXINTB_ISR(void) // SCI-B中断
{
if(ScibRegs.SCIRXST.bit.RXERROR == 1) //SW RESET
{
ScibRegs.SCICTL1.bit.SWRESET = 0;
DELAY_US(1000);
ScibRegs.SCICTL1.bit.SWRESET = 1;
}
// 正常SCI中断函数
// ...
// ...
// ...
PieCtrlRegs.PIEACK.bit.ACK9 = 1;
EINT;
}