打印
[ZLG-ARM]

LPC2119 CAN 多节点竞争 丢包严重

[复制链接]
3005|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
有意思|  楼主 | 2009-3-10 14:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
网络拓扑结构为5个20Kbps的主CAN节点,通过5个LPC2119+PCA82AC250(网关)将波特率降低至12kbps、5Kbps已适应远距离传输,网关采用透明传输,使用
缓冲区存储转发,
20K→5K使用一个大缓冲区,可存储800帧报文,
5K→20K使用一个小缓冲区,可存储80帧报文,
5个网关通过5K的CAN总线联网,手拉手式连接,短线,5个主节点可能同时向
网关发送事件信息,每个主节点约有12个事件约60帧的报文向CAN总线发送,很可能是同时发送的,即肯定为发送总线竞争;
经多次测试发现,低速口多次发生“仲裁丢失中断”,导致各节点不同收到所有
网络上的事件信息,如果只有一个节点发送事件信息,250个事件约1000帧也不
会出现丢帧现象;
疑问:即使出现竞争,CAN协议2.0不是规定要自动重发的吗?应该可以保证数据都能发送到总线上?以下是相关代码:

/**********中断发送程序***********/
void __irq can_isr(void)
{
    uint32 dev = 0;
    uCANICR k;
    for (dev=0; dev<CAN_MAX_NUM; dev++) {
        k = CANICR(dev);   
        if (k.Bits.RI_BIT != 0){
            //rcvdata_fromcanbus(dev);
            if (CAN1 == dev) {
                struct Low2High *ptr=&LowSpeed2Highbuf;
                if (ptr->full == 0) {
                    ptr->buf[ptr->start] = RxBUF(dev);
                    if (++ptr->start >= SIZEOF_LOW_HIGH)
                        ptr->start = 0;
                    if (ptr->start == ptr->end)
                        ptr->full = _FULL_;
                }else ON_RCAN_LED();
                RelCanRecBuf(dev);
        
            }else if (CAN2 == dev){
                struct High2Low *ptr=&HighSpeed2Lowbuf;
                if (ptr->full == 0) {
                    ptr->buf[ptr->start] = RxBUF(dev);
                    if (++ptr->start >= SIZEOF_HIGH_LOW)
                        ptr->start = 0;
                    if (ptr->start == ptr->end)
                        ptr->full = _FULL_;
                }else ON_RCAN_LED();
                RelCanRecBuf(dev);
            }
        }
        /*
        if ((k.Bits.TI1_BIT != 0)
            || (k.Bits.TI2_BIT != 0)
            || (k.Bits.TI3_BIT != 0)) {
        }
        */

        if (k.Bits.ALCBIT_BIT != 0) {
            flag[dev] |= 1<<2;
        }
        if (k.Bits.BEI_BIT != 0) {
            CanBufOffLinePrg(dev);
        }
        if (k.Bits.DOI_BIT != 0) {
            flag[dev] |= 1<<4;
            
            ClrCanDataOver(dev);
        }
    }
    VICVectAddr = 0x00;
}

/*高速口数据转发至低速口*/
void SendHigh2LowData2Bus(void)
{

    struct High2Low *ptr=&HighSpeed2Lowbuf;

    if ((ptr->start != ptr->end) || ptr->full == _FULL_ ) {
        if (CANGSR(CAN1).Bits.TBS_BIT != 0){
            if (BegainSend2CANBus(CAN1, &ptr->buf[ptr->end]) != 1){
                TCAN_LEDGlint();
                if (++ptr->end >= SIZEOF_HIGH_LOW) {
                    ptr->end = 0;
                }
                ptr->full = 0;
            }
        }
    }
}
/*低速口转发至高速口*/
void SendLow2HighData2Bus(void)
{
    struct Low2High *ptr=&LowSpeed2Highbuf;

    if ((ptr->start != ptr->end) || ptr->full == _FULL_) {
        if (ptr->full ==_FULL_) print("low to high is fullx0dx0a");
        if (CANGSR(CAN2).Bits.TBS_BIT != 0){
            if (BegainSend2CANBus(CAN2, &ptr->buf[ptr->end]) != 1){
                TCAN_LEDGlint();
                if (++ptr->end >= SIZEOF_LOW_HIGH) {
                    ptr->end = 0;
                }
                ptr->full = 0;
            }
        }
    }
}


/*
********************************************************************************
**函数名称:BegainSend2CANBus
**函数功能:启动发送
**入口参数:cannum:CAN控制器通道号ptr:发送缓冲区指针
**出口参数:1: erro      0:right
**函数说明:选择发送缓冲区
**
********************************************************************************
*/
uint32 BegainSend2CANBus(uint32 cannum, struct ObjectMessage *ptr)
{
    uint32 status = 0;
    uCANCMR Temp;

        
    Temp.Word = 0;        
    if (0 != CANSR(cannum).Bits.TBS1_BIT) {    
        if (0 == CANSR(cannum).Bits.TS1_BIT) {
            CANTFI1(cannum) = ptr->RFS_TFI;
            CANTID1(cannum) = ptr->ID;
            CANTDA1(cannum) = ptr->CANRDA;
            CANTDB1(cannum) = ptr->CANRDB;
            Temp.Bits.STB1_BIT = 1;
        }else{
            status = 1;
        }
    } else if (0 != CANSR(cannum).Bits.TBS2_BIT){
        if (0== CANSR(cannum).Bits.TS2_BIT) {
            CANTFI1(cannum) = ptr->RFS_TFI;
            CANTID1(cannum) = ptr->ID;
            CANTDA1(cannum) = ptr->CANRDA;
            CANTDB1(cannum) = ptr->CANRDB;
            Temp.Bits.STB2_BIT = 1;
        }else{
            status = 1;
        }
    }else if (0 != CANSR(cannum).Bits.TBS3_BIT){    
        if (0 == CANSR(cannum).Bits.TS3_BIT) {
            CANTFI1(cannum) = ptr->RFS_TFI;
            CANTID1(cannum) = ptr->ID;
            CANTDA1(cannum) = ptr->CANRDA;
            CANTDB1(cannum) = ptr->CANRDB;
            Temp.Bits.STB3_BIT = 1;    
        }else{
            status = 1;
        }
    }else{
        status = 1;
    }
    if (status == 0){
        if(CANMOD(cannum).Bits.SM_BIT != 0) {
            CanQuitSM(cannum);
        }    
        Temp.Bits.TR_BIT = 1;
        CANCMR(cannum).Word = Temp.Word;
    }
    return status;
}

/*主函数,只处理转发机制,*/
int main(void)
{  
    TargetInit();

    while (1) {
        SendHigh2LowData2Bus();
        SendLow2HighData2Bus();
        feeddog();
    }
    return 1;
}
/*************************************/
以上为程序基本流程,
现在在多个节点同时发送数据时,就会出现大量丢帧现在
各位看客有没有好的建议和解决方案!!!
谢谢

相关帖子

沙发
有意思|  楼主 | 2009-3-12 09:09 | 只看该作者

帧数据错位,郁闷中

在打印数据过程中发现有数据错位的现象发送
/*打印函数*/
void printfMessage(struct ObjectMessage *Msg)
{
    unsigned int i=0;
    unsigned char DLC=0;
    unsigned char buf[8];
    memset(buf, 0, 8);
    DLC = Msg->RFS_TFI.Bits.DLC_BIT;
    //print("TFI=%#X ", Msg->RFS_TFI);
    print("ID=%#X: x0dx0a", Msg->ID);
    switch (DLC){
        case 8:
            buf[7] = Msg->CANRDB.Bits.Data4_BIT;
        case 7:
            buf[6] = Msg->CANRDB.Bits.Data3_BIT;
        case 6:
            buf[5] = Msg->CANRDB.Bits.Data2_BIT;
        case 5:
            buf[4] = Msg->CANRDB.Bits.Data1_BIT;
        case 4:
            buf[3] = Msg->CANRDA.Bits.Data4_BIT;
        case 3:
            buf[2] = Msg->CANRDA.Bits.Data3_BIT;
        case 2:
            buf[1] = Msg->CANRDA.Bits.Data2_BIT;
        case 1:
            buf[0] = Msg->CANRDA.Bits.Data1_BIT;
            break;
        default:
            print("DLC=%dx0dx0ax0dx0a", DLC);
            return;
    }
    for(i=0;i<DLC;i++){
        print("f%d=%#x,", i, buf);
    }
    print("x0dx0ax0dx0a");
}

void SendLow2HighData2Bus(void)
{
    struct Low2High *ptr=&LowSpeed2Highbuf;

    if (ptr->TxBusy) return;
    if ((ptr->start != ptr->end) || ptr->full == _FULL_) {
        //if (CANGSR(CAN2).Bits.TBS_BIT != 0){
            if (BegainSend2CANBus(CAN2, &ptr->buf[ptr->end]) != 1){
                //TCAN_LEDGlint();
                ptr->TxBusy = 1;//开始向高速CAN口发送报文
                //在此打印由5K总线收到并发送给20K的数据帧
                printfMessage(&ptr->buf[ptr->end]);
                
                if (++ptr->end >= SIZEOF_LOW_HIGH) {
                    ptr->end = 0;
                }
                ptr->full = 0;
            }else {
                print("2:busyx0dx0a");
            }
        //}
    }
}

/************************************************/
/*打印结果如下(出错即丢帧时)*/

//事件1,2帧
ID=0X1C880100: 
f0=0x5,f1=0x1,f2=0x9,f3=0xed,f4=0x2a,f5=0xb9,f6=0x49,f7=0x1,

ID=0XC840100: 
f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,

//事件2,2帧
ID=0X1C888200: 
f0=0x5,f1=0x82,f2=0x9,f3=0xec,f4=0x2a,f5=0xb9,f6=0x49,f7=0x1,

ID=0XC848200: 
f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,

//事件3,2帧
ID=0X1C888300: 
f0=0xb,f1=0x83,f2=0x9,f3=0xec,f4=0x2a,f5=0xb9,f6=0x49,f7=0x1,

ID=0XC848300: 
f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,

//事件4,2帧
ID=0X1C888100: 
f0=0xb,f1=0x81,f2=0x9,f3=0xed,f4=0x2a,f5=0xb9,f6=0x49,f7=0x1,

ID=0XC848100: 
f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,

//事件5,2帧
ID=0X1C880100: 
f0=0xb,f1=0x1,f2=0x9,f3=0xee,f4=0x2a,f5=0xb9,f6=0x49,f7=0x1,

ID=0XC840100: 
f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,

//事件6,2帧
ID=0X1C888200: 
f0=0xb,f1=0x82,f2=0x9,f3=0xed,f4=0x2a,f5=0xb9,f6=0x49,f7=0x1,

ID=0XC848200: 
f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,

//事件7,2帧
//本帧出错,f0~f7的内容应与其它事件信息一样即
//f0应为0xb,貌似f0数据丢失,而后续的向前移动了一个字节,导致节点
//无法正确识别数据帧格式,导致事件丢失
ID=0X44: 
f0=0x81,f1=0x9,f2=0xed,f3=0x2a,f4=0xb9,

ID=0XC848100: 
f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,

//事件8,2帧
//同上,本节点正好丢失的2个事件,就是7,8
ID=0XC4: 
f0=0x83,f1=0x9,f2=0xed,f3=0x2a,f4=0xb9,

ID=0XC848300: 
f0=0,f1=0,f2=0x1,f3=0,f4=0,f5=0,f6=0,f7=0,

//不知道为什么帧内数据为出错
还有次打印出 DLC=11;不解中,收帧函数有bug???

使用特权

评论回复
板凳
ijk| | 2009-3-12 14:41 | 只看该作者

有意思

  有意思,问题也有意思。可以看看是否因为通信电缆太长,另外用示波器来看波形。

使用特权

评论回复
地板
有意思|  楼主 | 2009-3-12 15:07 | 只看该作者

不可能线缆太长

都是短线,半米都不到,首末加终端
不是每次都错,大概7-8次会错一次

使用特权

评论回复
5
ijk| | 2009-3-13 14:52 | 只看该作者

示波器

 示波器看,情况如何?

使用特权

评论回复
6
胡刚| | 2009-4-6 16:33 | 只看该作者

又一个把代码扔上来的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

79

主题

331

帖子

0

粉丝