This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

关于2812CAN接收邮箱中断

问题说明:我在程序中,将3个邮箱配置为接收邮箱,将接收中断配置为ECAN0INT中断线,当某个邮箱接收到数据后,触发邮箱中断,然后根据CANRMP寄存器的标志位确定是哪个邮箱触发了中断,对该邮箱进行接收处理。奇怪的是,程序刚开始运行一直正常,但是运行到一个小时左右后,出现故障。通过反复的测试,总结出故障的现象为,当我向dsp中发送数据时,能够确定邮箱接收到了数据,并且触发了邮箱中断,但是该邮箱的CANRMP标志位并没有被置位,因此dsp程序中无法判别哪个邮箱触发了中断,而且发送邮箱能够正常发送数据。经过测试,确定错误计数寄存器CANTEC/CANREC均正常。                                                     

以上为我所遇到的问题,不知道哪位朋友能够解惑,说一说解决方法或者可能的原因,谢谢!

  • 贴一段你的程序看看.

    还有没有别的中断?

    3个数据的发送间隔是多少?

    CAN中断中还有其他的程序执行没有?

    对CANRMP的操作有没有使用影子寄存器.有可能错误清除CMP.

  • 1.还有一个定时器下溢中断

    2.我做测试实际只用了一个接收邮箱,数据的发送是通过上位机手动发送,间隔时间很长。

    rpm清楚不需要影子寄存器吧。

  • interrupt void Ecan0ISR(void)
    {

    Can_receivecounter++;
    DINT;

    if(ECanaRegs.CANRMP.all&0x00040000)
    {CANSXSRX18();
    receiveflag18=1;
    }

    if(ECanaRegs.CANRMP.all&0x00080000)
    {CANSXSRX19();
    receiveflag19=1;
    }

    if(ECanaRegs.CANRMP.all&0x20000000)
    {

    CANSXSRX29();
    receiveflag29=1;
    }

    PieCtrlRegs.PIEACK.bit.ACK9 = 1;
    EINT;

    }

    void CANSXSRX29(void)
    {
    ECanaRegs.CANRMP.all = (ECanaRegs.CANRMP.all|0x20000000);

    a=ECanaMboxes.MBOX29.MDL.byte.BYTE0;
    b=ECanaMboxes.MBOX29.MDL.byte.BYTE1;

    }

    上面是中断程序和接收邮箱程序

  • interrupt void Ecan0ISR(void)
    {
    Can_receivecounter++;
    DINT;

    if(ECanaRegs.CANRMP.all&0x00040000)
    {CANSXSRX18();
    receiveflag18=1;
    }

    if(ECanaRegs.CANRMP.all&0x00080000)
    {CANSXSRX19();
    receiveflag19=1;

    }

    if(ECanaRegs.CANRMP.all&0x20000000)
    {CANSXSRX29();
    receiveflag29=1;

    }

    PieCtrlRegs.PIEACK.bit.ACK9 = 1;
    EINT;
    }

    void CANSXSRX29(void)


    ECanaRegs.CANRMP.all = (ECanaRegs.CANRMP.all|0x20000000);
    a=ECanaMboxes.MBOX29.MDL.byte.BYTE0;
    b=ECanaMboxes.MBOX29.MDL.byte.BYTE1;

    }

    上面是中断程序和接收邮箱程序

  • 建议改为:

    interrupt void Ecan0ISR(void)
    {

    struct ECAN_REGS  ECanaShadow;//注意引用CAN的头文件


    Can_receivecounter++;
    //DINT;   //删除这个,其他的中断中也不要写这个.进中断之后会自动禁止,除非你想使能别人打断,这里可以写EINT.

    ECanaShadow.CANRMP.all = 0;

    ECanaShadow.CANRMP.all = ECanaRegs.CANRMP.all;

    //if(ECanaRegs.CANRMP.all&0x00040000)

    if((ECanaShadow.CANRMP.all & 0x00040000) ==0x00040000)
    {CANSXSRX18();
    receiveflag18=1;
    }


    //if(ECanaRegs.CANRMP.all&0x00080000)

    if((ECanaShadow.CANRMP.all & 0x00080000) ==0x00080000  )
    {CANSXSRX19();
    receiveflag19=1;

    }

    //if(ECanaRegs.CANRMP.all&0x20000000)

    if((ECanaShadow.CANRMP.all & 0x20000000) ==0x20000000)
    {CANSXSRX29();
    receiveflag29=1;

    }

    //PieCtrlRegs.PIEACK.bit.ACK9 = 1;

    PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
    //EINT;
    }

    void CANSXSRX29(void)

    ECanaRegs.CANRMP.all = 0x20000000;//其他邮箱按设计赋值,只清除对应的位

    //ECanaRegs.CANRMP.all = (ECanaRegs.CANRMP.all|0x20000000);//这样先读后写,如果收到两帧,则又可能清除其他的位.

    //ECanaRegs.CANRMP.all = RMP_TEMP;//也可以带参


    a=ECanaMboxes.MBOX29.MDL.byte.BYTE0;
    b=ECanaMboxes.MBOX29.MDL.byte.BYTE1;

    }

    你再试试.

  • 好的,非常感谢,我先试试。

  • 你好,我按照你说的试了一下,现象还是和原来一样。

    程序刚开始正常,运行一个小时后,通过观测Can_receivecounter++的值,这个值还能递增,说明程序能够进入邮箱中断;但是观测ECanaRegs.CANRMP.bit.RMP29的值,这个值一直保持为0,而且提取ECanaMboxes.MBOX29.MDL.byte.BYTE0和ECanaMboxes.MBOX29.MDL.byte.BYTE1的数据,也是变化的,说明邮箱29能够接收到数据,并且能够触发邮箱中断,但是CANRMP却没有被置位。

    不知道是什么原因?

  • 你的意思是运行一段时间后,程序中a,b的值不变化了吗?

    由于进入中断后,RMP29很快会被清0 .你是在什么地方打断点看的?

    你可以在运行一段时间后,在中断中打一个断点,发送一组数据看看, 看进入中断后,RMP的那一位置位了?

  • 对对,运行一个小时左右,a、b的值就不变了。RMP位一直保持为0,但是能确定接收邮箱29肯定接收到了数据,并且中断也进入了。

    我是用其他邮箱查询发送的,将邮箱29中的数据和RMP位赋给邮箱15,用邮箱15将他们发送给上位机观察的。我试验了好多次,基本都是在一个小时左右出现故障。

  • 那你可以在运行一段时间后,在中断中打一个断点,发送一组数据看看, 看进入中断后,RMP的那一位  置位了?

  • void Ecan_init()
    {
    /*-------------------------------------------------------------------------*/
    // configure CAN pins using GPIO regs here
    EALLOW;
    GpioMuxRegs.GPFMUX.bit.CANTXA_GPIOF6 = 1;
    GpioMuxRegs.GPFMUX.bit.CANRXA_GPIOF7 = 1;
    EDIS;
    /*-------------------------------------------------------------------------*/
    // Configure the eCAN RX and TX pins for eCAN transmissions
    EALLOW;
    ECanaRegs.CANTIOC.bit.TXFUNC = 1;
    ECanaRegs.CANRIOC.bit.RXFUNC = 1;
    EDIS;
    /*-------------------------------------------------------------------------*/
    // eCAN mode (reqd to access 32 mailboxes)
    EALLOW;
    ECanaRegs.CANMC.bit.SCB = 1; // eCAN mode
    EDIS;

    ECanaRegs.CANME.all = 0x00000000;
    /*-------------------------------------------------------------------------*/
    /* Clear all TAn bits */
    ECanaRegs.CANTA.all = 0xFFFFFFFF;
    /*-------------------------------------------------------------------------*/
    /* Clear all RMPn bits(write 1 to clear) */
    ECanaRegs.CANRMP.all = 0xFFFFFFFF;
    /*-------------------------------------------------------------------------*/
    /* Clear all interrupt flag bits */
    ECanaRegs.CANGIF0.all = 0xFFFFFFFF;
    ECanaRegs.CANGIF1.all = 0xFFFFFFFF;
    /*-------------------------------------------------------------------------*/
    /* disbale global interrupt and mailbox interrupt */
    EALLOW;
    ECanaRegs.CANGIM.all = 0x00000000;
    ECanaRegs.CANMIM.all = 0x00000000;
    EDIS;
    /*-------------------------------------------------------------------------*/
    /* Configure bit timing parameters */
    EALLOW;
    ECanaRegs.CANMC.bit.CCR = 1; // Set CCR = 1
    EDIS;
    while(ECanaRegs.CANES.bit.CCE != 1 ) {} // Wait for CCE bit to be set..
    /*-------------------------------------------------------------------------*/
    EALLOW;
    ECanaRegs.CANBTC.bit.BRPREG = 19; // 150MHz/20=7.5MHz
    ECanaRegs.CANBTC.bit.TSEG1REG = 10;
    ECanaRegs.CANBTC.bit.TSEG2REG = 2; //Bode rate:7.5M/(1+11+3)=500kb
    EDIS;
    /*-------------------------------------------------------------------------*/
    EALLOW;
    ECanaRegs.CANMC.bit.CCR = 0; // Set CCR = 0
    EDIS;
    while(ECanaRegs.CANES.bit.CCE != 0 ) {} // Wait for CCE bit to be cleared..
    /*-------------------------------------------------------------------------*/
    /* Disable all Mailboxes */
    ECanaRegs.CANME.all = 0x00000000; // Required before writing the MSGIDs
    /*-------------------------------------------------------------------------*/
    EALLOW;
    ECanaRegs.CANMC.bit.STM = 0; // Configure CAN for normal mode
    ECanaRegs.CANMC.bit.DBO = 1;
    ECanaRegs.CANMC.bit.ABO = 1;
    ECanaRegs.CANMC.bit.PDR = 0;
    ECanaRegs.CANMC.bit.WUBA = 0;
    EDIS;

    ECanaRegs.CANMC.bit.SRES = 0;
    ECanaRegs.CANMC.bit.CDR = 0;
    ECanaRegs.CANMC.bit.MBNR = 0;
    /*-------------------------------------------------------------------------*/
    EcanMboxConfig();
    /*-------------------------------------------------------------------------*/

    EALLOW; // Enable EALLOW

    ECanaRegs.CANMIL.all = ECanaRegs.CANMIL.all&0x00000000;//在中断0产生中断
    ECanaRegs.CANMIM.all = ECanaRegs.CANMIM.all|0x200C0000;
    ECanaRegs.CANGIM.all = ECanaRegs.CANGIM.all|0x00000001;
    EDIS; // Disable EALLOW


    }

    上面是邮箱的配置,麻烦帮忙看一下

  • 贴一下这个EcanMboxConfig();

    如果开始可以正常运行,后面邮箱数据可以更新, 我认为CAN这部分没有问题, 你整个程序是否还有其他的部分,你试试屏蔽其他的部分,但是测试CAN 看一下.

    你可以运行一段时间后,打一个断点看,不建议再用其他邮箱进行发送.多利用watch窗口看看.