故障现象:
1、在通讯线上耦合±2kV、5kHz的快速瞬变脉冲群干扰或者使用串口通讯软件对仪表进行5~10ms灌包,可能会导致通讯中断不可恢复,设备并未死机重新初始化串口后通讯恢复。
2、同时若干台仪表手拉手连接在同一条总线上进行5~10ms灌包,亦会导致通讯中断不可恢复,设备并未死机重新初始化串口后通讯恢复。
问题分析
问题1:
程序在5ms定时中断中进行断帧,判断一帧结束后会关闭所有中断,置发送标志,代码如下所示:
//接收标志置位;MODBUS断帧条件3.5个字符内未收到数据
if((BYENDRXA == TRUE) && (BYRXACLK > RXINTERVAL[sSysCtlPara.uSCIARate&0x000f]))
{
LPC_UART1->IER =0; //关闭所有中断
BYENDRXA = FALSE; //清除接收标志
UART1Status |= 0x100; //断帧标志置位
}
在主循环中对接收报文进行解析,组织发送报文并打开发送中断,伪代码如下所示:
void Uartprocess (void)
{
if((UART1Status>>8) && (UART1Count != 0))//断帧标志置位,且接收计数不为0
{
UART1Count = 0; //清接收计数
UART1Status = 0; //清断帧标志
TX1LEN = ModBus();//接收报文解析
if(TX1LEN != 0)//需回复报文
{
UARTSend();//打开发送中断,报文发送完成后打开接收中断
}
else//无需回复报文或错误报文,打开接收中断继续接收报文
{
LPC_UART1->IER = IER_RBR | IER_RLS;
}
}
}
由于脉冲群干扰或者灌包很频繁,在执行程序时均有可能会有报文接收。5ms定时中断时断帧,关闭所有中断之前接收缓冲中接收到一帧,之后由于关闭了接收中断肯定会没有收到数据。按MODBUS标准在3.5个字符时间内无新数据接收再次断帧,关闭所有中断。在第二次断帧前处理数据并打开发送中断或者接收中断,会被第二次错误断帧把所有中断关闭。此时发送中断被关闭无法发送,不结束发送也不会再次打开接收中断,从而造成通讯中断不可恢复。
问题2:
在串口中断中接收数据满会把接收计数清0,而在红色注释处被高优先级的定时中断打断进行断帧处理,关闭了所有中断。此后应当进入报文解析打开发送或接收中断,但是接收计数被清0了而无法进行数据处理,从而造成通讯中断不可恢复。代码如下所示:
else if((IIRValue == IIR_RDA)||(IIRValue == IIR_CTI)) //接收到有效数据
{
RXNOW = 1;//接收标识,显示用
UART1Buffer[UART1Count] = LPC_UART1->RBR;//读取数据至接收缓冲
UART1Count++; //接收计数满,断帧将所有中断关闭。
BYRXACLK = 0; //断帧超时计数清零
BYENDRXA = TRUE; //接收标志置位
if(UART1Count == BUFSIZE) //接收计数满清0
{
BYENDRXA = FALSE;
UART1Count = 0;
}
}
问题3:
在发送完成后先置发送结束标志后关闭所有中断。在定时中断中检查该标志去打开接收中断继续等待新报文接收。若置位发送完成标志后恰好进入高优先级的定时中断打开的接收中断会被之后的关所有中断覆盖,从而造成通讯中断不可恢复。代码如下所示:
SendOver = SEND_OVER_START; //置发送完成标志
LPC_UART1->IER = 0; //关闭所有中断
解决措施:
1、主程序中串口处理函数进入后关闭接收标志,禁止断帧。
2、接收计数满后,修改清0为清为1。处理一帧错误报文。
3、先关闭所有中断,再置发送完成标志。
总结建议:
再处理通讯流程过程中, 需要做好通讯的状态管理,按照状态流程做好寄存器的配置,避免出错。