項目上通過RS485 SCI串口在DSP 28335和PLC之間通訊, PLC發送指令給DSP,觸發DSP的SCI接收中斷,進而在接收中斷里執行SCI發送函數,返回給PLC對應數據,未使用FIFO。
之前程序一直正常運行,最近在調試的過程中遇到了奇怪的現象,SCI中斷會在成功進入中斷一次或者若干次后(幾十、幾百、幾千不等)再也進不去中斷,而同時程序並沒有跑飛,CAN的收發中斷和定時器Timer0中斷都在正常運行,主循環也在正常運行。查看SCI寄存器發現,在PLC發送數據的末尾,會莫名多出來一字節數據 “0x00”。當“0x00”出現之后,就再也無法進入SCI接收中斷了,同時可以觀察到SCI寄存器SCIRXST的第3位(OE)溢出錯誤標志 ,第4位(FE)幀錯誤標志和第7位(RX ERROR,數值為第2、3、4位寄存器或運算結果)SCI接收器錯誤標志為1。正常情況下三個寄存器都應該為0。
據此判斷是SCI出現接收錯誤,導致進不去SCI接收中斷。查閱了一些資料,發現要想解決發生錯誤導致錯誤標志位置位的問題,需要執行一次完整的SW RESET((SCICTL1)的第5位)。
RX ERROR SCI receiver error flag. The RX ERROR flag indicates that one of the error flags in the receiver status register is set. RX ERROR is a logical OR of the break detect, framing error, overrun, and parity error enable flags (bits 5−2: BRKDT, FE, OE, and PE). A 1 on this bit will cause an interrupt if the RX ERR INT ENA bit (SCICTL1.6) is set.This bit can be used for fast error-condition checking during the interrupt service routine. This error flag cannot be cleared directly; it is cleared by an active SW RESET or by a system reset. 1 Error flag(s) set 0 No error flags set FE SCI framing-error flag. The SCI sets this bit when an expected stop bit is not found. Only the first stop bit is checked. The missing stop bit indicates that synchronization with the start bit has been lost and that the character is incorrectly framed. The FE bit is reset by a clearing of the SW RESET bit or by a system reset. 1 Framing error detected 0 No framing error detected OE SCI overrun-error flag. The SCI sets this bit when a character is transferred into registers SCIRXEMU and SCIRXBUF before the previous character is fully read by the CPU or DMAC. The previous character is overwritten and lost. The OE flag bit is reset by an active SW RESET or by a system reset. 1 Overrun error detected 0 No overrun error detected
那么解決方案就是:
1.使能SCI接收錯誤中斷
2.當發生SCI接收錯誤時,進入SCI接收中斷,判斷標志位 RX ERROR 是否置1(如果是SCI接收錯誤導致進入中斷, RX ERROR自然為1)
3.當 RX ERROR 置1,執行一次完整的SW RESET,退出中斷
通過這簡單3步,程序就可以繼續進入SCI接收中斷了,SCI通訊恢復正常。至於為何會出現錯誤,由於通訊程序並沒有改動,正常跑了大約一周突然連續出現錯誤,只能暫時理解成是環境電磁干擾導致的錯誤吧。。。
下面附上修改后的代碼供有需要的同學取用
1 void Scib_echoback_init() // SCI初始化 2 { 3 // Note: Clocks were turned on to the SCIA peripheral 4 // in the InitSysCtrl() function 5 6 ScibRegs.SCICCR.all =0x0007; // 1 stop bit, No loopback 7 // No parity,8 char bits, 8 // async mode, idle-line protocol 9 ScibRegs.SCICTL1.all =0x0003; // enable TX, RX, internal ScibLK, 10 // Disable RX ERR, SLEEP, TXWAKE 11 12 ScibRegs.SCICTL1.bit.RXERRINTENA=1; //使能錯誤接收中斷 13 14 ScibRegs.SCICTL2.all =0x0003; 15 ScibRegs.SCICTL2.bit.TXINTENA = 1; 16 ScibRegs.SCICTL2.bit.RXBKINTENA =1; 17 18 #if (CPU_FRQ_150MHZ) 19 ScibRegs.SCIHBAUD =0x0000; 20 // 19200 baud @LSPCLK = 37.5MHz. 21 ScibRegs.SCILBAUD =0x00F3; 22 #endif 23 #if (CPU_FRQ_100MHZ) 24 ScibRegs.SCIHBAUD =0x0001; // 9600 baud @LSPCLK = 20MHz. 25 ScibRegs.SCILBAUD =0x0044; 26 #endif 27 ScibRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset 28 }
1 interrupt void SCIRXINTB_ISR(void) // SCI-B中斷 2 { 3 4 if(ScibRegs.SCIRXST.bit.RXERROR == 1) //SW RESET 5 { 6 ScibRegs.SCICTL1.bit.SWRESET = 0; 7 DELAY_US(1000); 8 ScibRegs.SCICTL1.bit.SWRESET = 1; 9 } 10 11 12 // 正常SCI中斷函數 13 // ... 14 // ... 15 // ... 16 17 PieCtrlRegs.PIEACK.bit.ACK9 = 1; 18 EINT; 19 }
