<br />网络拓扑结构为5个20Kbps的主CAN节点,通过5个LPC2119+PCA82AC250(网关)将波特率降低至12kbps、5Kbps已适应远距离传输,网关采用透明传输,使用<br />缓冲区存储转发,<br />20K→5K使用一个大缓冲区,可存储800帧报文,<br />5K→20K使用一个小缓冲区,可存储80帧报文,<br />5个网关通过5K的CAN总线联网,手拉手式连接,短线,5个主节点可能同时向<br />网关发送事件信息,每个主节点约有12个事件约60帧的报文向CAN总线发送,很可能是同时发送的,即肯定为发送总线竞争;<br />经多次测试发现,低速口多次发生“仲裁丢失中断”,导致各节点不同收到所有<br />网络上的事件信息,如果只有一个节点发送事件信息,250个事件约1000帧也不<br />会出现丢帧现象;<br />疑问:即使出现竞争,CAN协议2.0不是规定要自动重发的吗?应该可以保证数据都能发送到总线上?以下是相关代码:<br /><br />/**********中断发送程序***********/<br />void __irq can_isr(void)<br />{<br /> uint32 dev = 0;<br /> uCANICR k;<br /> for (dev=0; dev<CAN_MAX_NUM; dev++) {<br /> k = CANICR(dev); <br /> if (k.Bits.RI_BIT != 0){<br /> //rcvdata_fromcanbus(dev);<br /> if (CAN1 == dev) {<br /> struct Low2High *ptr=&LowSpeed2Highbuf;<br /> if (ptr->full == 0) {<br /> ptr->buf[ptr->start] = RxBUF(dev);<br /> if (++ptr->start >= SIZEOF_LOW_HIGH)<br /> ptr->start = 0;<br /> if (ptr->start == ptr->end)<br /> ptr->full = _FULL_;<br /> }else ON_RCAN_LED();<br /> RelCanRecBuf(dev);<br /> <br /> }else if (CAN2 == dev){<br /> struct High2Low *ptr=&HighSpeed2Lowbuf;<br /> if (ptr->full == 0) {<br /> ptr->buf[ptr->start] = RxBUF(dev);<br /> if (++ptr->start >= SIZEOF_HIGH_LOW)<br /> ptr->start = 0;<br /> if (ptr->start == ptr->end)<br /> ptr->full = _FULL_;<br /> }else ON_RCAN_LED();<br /> RelCanRecBuf(dev);<br /> }<br /> }<br /> /*<br /> if ((k.Bits.TI1_BIT != 0)<br /> || (k.Bits.TI2_BIT != 0)<br /> || (k.Bits.TI3_BIT != 0)) {<br /> }<br /> */<br /><br /> if (k.Bits.ALCBIT_BIT != 0) {<br /> flag[dev] |= 1<<2;<br /> }<br /> if (k.Bits.BEI_BIT != 0) {<br /> CanBufOffLinePrg(dev);<br /> }<br /> if (k.Bits.DOI_BIT != 0) {<br /> flag[dev] |= 1<<4;<br /> <br /> ClrCanDataOver(dev);<br /> }<br /> }<br /> VICVectAddr = 0x00;<br />}<br /><br />/*高速口数据转发至低速口*/<br />void SendHigh2LowData2Bus(void)<br />{<br /><br /> struct High2Low *ptr=&HighSpeed2Lowbuf;<br /><br /> if ((ptr->start != ptr->end) || ptr->full == _FULL_ ) {<br /> if (CANGSR(CAN1).Bits.TBS_BIT != 0){<br /> if (BegainSend2CANBus(CAN1, &ptr->buf[ptr->end]) != 1){<br /> TCAN_LEDGlint();<br /> if (++ptr->end >= SIZEOF_HIGH_LOW) {<br /> ptr->end = 0;<br /> }<br /> ptr->full = 0;<br /> }<br /> }<br /> }<br />}<br />/*低速口转发至高速口*/<br />void SendLow2HighData2Bus(void)<br />{<br /> struct Low2High *ptr=&LowSpeed2Highbuf;<br /><br /> if ((ptr->start != ptr->end) || ptr->full == _FULL_) {<br /> if (ptr->full ==_FULL_) print("low to high is fullx0dx0a");<br /> if (CANGSR(CAN2).Bits.TBS_BIT != 0){<br /> if (BegainSend2CANBus(CAN2, &ptr->buf[ptr->end]) != 1){<br /> TCAN_LEDGlint();<br /> if (++ptr->end >= SIZEOF_LOW_HIGH) {<br /> ptr->end = 0;<br /> }<br /> ptr->full = 0;<br /> }<br /> }<br /> }<br />}<br /><br /><br />/*<br />********************************************************************************<br />**函数名称:BegainSend2CANBus<br />**函数功能:启动发送<br />**入口参数:cannum:CAN控制器通道号ptr:发送缓冲区指针<br />**出口参数:1: erro 0:right<br />**函数说明:选择发送缓冲区<br />**<br />********************************************************************************<br />*/<br />uint32 BegainSend2CANBus(uint32 cannum, struct ObjectMessage *ptr)<br />{<br /> uint32 status = 0;<br /> uCANCMR Temp;<br /><br /> <br /> Temp.Word = 0; <br /> if (0 != CANSR(cannum).Bits.TBS1_BIT) { <br /> if (0 == CANSR(cannum).Bits.TS1_BIT) {<br /> CANTFI1(cannum) = ptr->RFS_TFI;<br /> CANTID1(cannum) = ptr->ID;<br /> CANTDA1(cannum) = ptr->CANRDA;<br /> CANTDB1(cannum) = ptr->CANRDB;<br /> Temp.Bits.STB1_BIT = 1;<br /> }else{<br /> status = 1;<br /> }<br /> } else if (0 != CANSR(cannum).Bits.TBS2_BIT){<br /> if (0== CANSR(cannum).Bits.TS2_BIT) {<br /> CANTFI1(cannum) = ptr->RFS_TFI;<br /> CANTID1(cannum) = ptr->ID;<br /> CANTDA1(cannum) = ptr->CANRDA;<br /> CANTDB1(cannum) = ptr->CANRDB;<br /> Temp.Bits.STB2_BIT = 1;<br /> }else{<br /> status = 1;<br /> }<br /> }else if (0 != CANSR(cannum).Bits.TBS3_BIT){ <br /> if (0 == CANSR(cannum).Bits.TS3_BIT) {<br /> CANTFI1(cannum) = ptr->RFS_TFI;<br /> CANTID1(cannum) = ptr->ID;<br /> CANTDA1(cannum) = ptr->CANRDA;<br /> CANTDB1(cannum) = ptr->CANRDB;<br /> Temp.Bits.STB3_BIT = 1; <br /> }else{<br /> status = 1;<br /> }<br /> }else{<br /> status = 1;<br /> }<br /> if (status == 0){<br /> if(CANMOD(cannum).Bits.SM_BIT != 0) {<br /> CanQuitSM(cannum);<br /> } <br /> Temp.Bits.TR_BIT = 1;<br /> CANCMR(cannum).Word = Temp.Word;<br /> }<br /> return status;<br />}<br /><br />/*主函数,只处理转发机制,*/<br />int main(void)<br />{ <br /> TargetInit();<br /><br /> while (1) {<br /> SendHigh2LowData2Bus();<br /> SendLow2HighData2Bus();<br /> feeddog();<br /> }<br /> return 1;<br />}<br />/*************************************/<br />在打印数据过程中发现有数据错位的现象发送<br />/*打印函数*/<br />void printfMessage(struct ObjectMessage *Msg)<br />{<br /> unsigned int i=0;<br /> unsigned char DLC=0;<br /> unsigned char buf[8];<br /> memset(buf, 0, 8);<br /> DLC = Msg->RFS_TFI.Bits.DLC_BIT;<br /> //print("TFI=%#X ", Msg->RFS_TFI);<br /> print("ID=%#X: x0dx0a", Msg->ID);<br /> switch (DLC){<br /> case 8:<br /> buf[7] = Msg->CANRDB.Bits.Data4_BIT;<br /> case 7:<br /> buf[6] = Msg->CANRDB.Bits.Data3_BIT;<br /> case 6:<br /> buf[5] = Msg->CANRDB.Bits.Data2_BIT;<br /> case 5:<br /> buf[4] = Msg->CANRDB.Bits.Data1_BIT;<br /> case 4:<br /> buf[3] = Msg->CANRDA.Bits.Data4_BIT;<br /> case 3:<br /> buf[2] = Msg->CANRDA.Bits.Data3_BIT;<br /> case 2:<br /> buf[1] = Msg->CANRDA.Bits.Data2_BIT;<br /> case 1:<br /> buf[0] = Msg->CANRDA.Bits.Data1_BIT;<br /> break;<br /> default:<br /> print("DLC=%dx0dx0ax0dx0a", DLC);<br /> return;<br /> }<br /> for(i=0;i<DLC;i++){<br /> print("f%d=%#x,", i, buf);<br /> }<br /> print("x0dx0ax0dx0a");<br />}<br /><br />void SendLow2HighData2Bus(void)<br />{<br /> struct Low2High *ptr=&LowSpeed2Highbuf;<br /><br /> if (ptr->TxBusy) return;<br /> if ((ptr->start != ptr->end) || ptr->full == _FULL_) {<br /> //if (CANGSR(CAN2).Bits.TBS_BIT != 0){<br /> if (BegainSend2CANBus(CAN2, &ptr->buf[ptr->end]) != 1){<br /> //TCAN_LEDGlint();<br /> ptr->TxBusy = 1;//开始向高速CAN口发送报文<br /> //在此打印由5K总线收到并发送给20K的数据帧<br /> printfMessage(&ptr->buf[ptr->end]);<br /> <br /> if (++ptr->end >= SIZEOF_LOW_HIGH) {<br /> ptr->end = 0;<br /> }<br /> ptr->full = 0;<br /> }else {<br /> print("2:busyx0dx0a");<br /> }<br /> //}<br /> }<br />}<br /><br />/************************************************/<br />/*打印结果如下(出错即丢帧时)*/<br /><br />//事件1,2帧<br />ID=0X1C880100: <br />f0=0x5,f1=0x1,f2=0x9,f3=0xed,f4=0x2a,f5=0xb9,f6=0x49,f7=0x1,<br /><br />ID=0XC840100: <br />f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,<br /><br />//事件2,2帧<br />ID=0X1C888200: <br />f0=0x5,f1=0x82,f2=0x9,f3=0xec,f4=0x2a,f5=0xb9,f6=0x49,f7=0x1,<br /><br />ID=0XC848200: <br />f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,<br /><br />//事件3,2帧<br />ID=0X1C888300: <br />f0=0xb,f1=0x83,f2=0x9,f3=0xec,f4=0x2a,f5=0xb9,f6=0x49,f7=0x1,<br /><br />ID=0XC848300: <br />f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,<br /><br />//事件4,2帧<br />ID=0X1C888100: <br />f0=0xb,f1=0x81,f2=0x9,f3=0xed,f4=0x2a,f5=0xb9,f6=0x49,f7=0x1,<br /><br />ID=0XC848100: <br />f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,<br /><br />//事件5,2帧<br />ID=0X1C880100: <br />f0=0xb,f1=0x1,f2=0x9,f3=0xee,f4=0x2a,f5=0xb9,f6=0x49,f7=0x1,<br /><br />ID=0XC840100: <br />f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,<br /><br />//事件6,2帧<br />ID=0X1C888200: <br />f0=0xb,f1=0x82,f2=0x9,f3=0xed,f4=0x2a,f5=0xb9,f6=0x49,f7=0x1,<br /><br />ID=0XC848200: <br />f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,<br /><br />//事件7,2帧<br />//本帧出错,f0~f7的内容应与其它事件信息一样即<br />//f0应为0xb,貌似f0数据丢失,而后续的向前移动了一个字节,导致节点<br />//无法正确识别数据帧格式,导致事件丢失<br />ID=0X44: <br />f0=0x81,f1=0x9,f2=0xed,f3=0x2a,f4=0xb9,<br /><br />ID=0XC848100: <br />f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,<br /><br />//事件8,2帧<br />//同上,本节点正好丢失的2个事件,就是7,8<br />ID=0XC4: <br />f0=0x83,f1=0x9,f2=0xed,f3=0x2a,f4=0xb9,<br /><br />ID=0XC848300: <br />f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,<br /><br />//不知道为什么帧内数据为出错<br />还有次打印出 DLC=11;不解中,收帧函数有bug???<br /><br />以上为程序基本流程,<br />现在在多个节点同时发送数据时,就会出现大量丢帧现在<br />各位看客有没有好的建议和解决方案!!!<br />谢谢<br /> |
|