打印
[CAN-bus/DeviceNet]

LPC2119 CAN 多节点竞争 报文内容出错 移位

[复制链接]
2399|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
有意思|  楼主 | 2009-3-12 10:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

网络拓扑结构为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;
}
/*************************************/
在打印数据过程中发现有数据错位的现象发送
/*打印函数*/
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???

以上为程序基本流程,
现在在多个节点同时发送数据时,就会出现大量丢帧现在
各位看客有没有好的建议和解决方案!!!
谢谢

相关帖子

沙发
georgekin203| | 2009-3-12 11:36 | 只看该作者

heihei

各节点发送频率太高导致数据区倒数第二位丢失,或者位定时标志丢失
建议各节点尽量不要同时发送,差开一个时间最好,2119好像是有这个问题,sja1000及其他内嵌can的mcu都没这个现象

使用特权

评论回复
板凳
有意思|  楼主 | 2009-3-12 14:03 | 只看该作者

不会吧

芯片本身如果有这个问题
NXP早就应该知道,出修订版本了吧
我一直认为是自己程序哪里处理出错,但是一直没找到问题啊,郁闷
发送频率基本上是调节不了了
LPC2119类似一个中继降速模块,高速节点的发送频率已经定型,控制不了
降速模块收到高速节点发送的报文后,立即存储到high→low缓冲区
主main中判断读写指针不等后就立即启动发送
作为中继节点,觉得不应该控制发送速率,怕当有大量数据时,缓冲区满会溢出
郁闷ing

使用特权

评论回复
地板
有意思|  楼主 | 2009-3-13 11:02 | 只看该作者

报文收错了

void sendbyte(uint32 Device,uint8 ch)
{
    if (Device == UART0)
        U0THR = ch;
    else    if (Device == UART1)
        U1THR = ch;
}
在中断中打印同样出现出差情况
sendbyte(UART0,CANRDA(dev).Bits.Data1_BIT);
ptr->buf[ptr->start] = RxBUF(dev);
同样Data1_BIT的数据会变成Data2_BIT的数据,郁闷ing

使用特权

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

本版积分规则

79

主题

331

帖子

0

粉丝