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.

TMS320F28335: 有关eCAN的发送和接收中断问题

Part Number: TMS320F28335

大佬们,我想问一下,做CAN通信,我用0号邮箱做发送邮箱,16号邮箱作为接收邮箱。但我在十六号邮箱中写了个中断。就是使用CAN调试软件,运行程序,可以看到CAN调试软件中0号邮箱发送的数据。但是我在CAN调试软件上给16号邮箱发送数据程序就进入不到中断了。但是16号邮箱里面的数据变化了。而且从CAN调试软件上0号邮箱发送了一帧01,23,45,67,89,ab,cd,ef。这一帧不知道是怎么产生的。但是我如果在主函数将发送的那部分程序注释掉,在那个接收中断打断点,从CAN调试软件上发送数据是可以直接进入到中断里面的。

  • 你好,你这个是什么软件?是TI官方的软件吗?可以提供下链接吗?

    不是很理解你所说的请况。可以分享下你的程序吗?

  • 主程序:
    #include "eCAN.h"
    
    //定义全局变量
    Uint32 MessageSendCount = 0;
    Uint32 MessageReceiveCount = 0;
    Uint32 Rec_l;
    Uint32 Rec_h;
    Uint16 i = 0,j = 0,k = 0;
    Uchar senddata[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
    
    __interrupt void ECAN0INTB_iSR(void);
    
    void main(void)
    {
        InitSysCtrl();
        DINT;
        IER = 0x0000;
        IFR = 0x0000;
        InitPieCtrl();
        InitPieVectTable();
    
        EALLOW;  // 写保护
        PieVectTable.ECAN0INTB = &ECAN0INTB_iSR;    //设置ECAN0INTB中断服务程序的入口地址为ECAN0INTB_iSR
        EDIS;    // 禁用写保护
    
        InitECan();
        //使能PIE中断
        PieCtrlRegs.PIEIER9.bit.INTx7 = 1;
    
        //使能CPU中断
        IER |= M_INT9;
        EINT;                         //开全局中断
        ERTM;                         //开实时中断
    
        for(;;)
        {
            //只使用接收的话,52行-65行注释掉即可
    //        for(;k<20;)
    //        {
                ECanbRegs.CANTRS.all = 0x00000001;     //1设置TRSn,发送该邮箱中的消息
                while(ECanbRegs.CANTA.all == 0){}      //等待TA被置位,邮箱消息发送成功则置位
                ECanbRegs.CANTA.all = 0x00000001;      //如果邮箱n的消息发送成功,则设置该寄存器的第n位
                MessageSendCount++;                    //设断点,观察
                ECanbMboxes.MBOX0.MDL.all = senddata[i];
                ECanbMboxes.MBOX0.MDH.all = senddata[i + 1];
                i = i + 2;
                if(i > 7)
                i = 0;
    //            k++;
    //        }
        }
    }
    
    __interrupt void ECAN0INTB_iSR(void)            //eCAN_B
    {
        if(ECanbRegs.CANRMP.all != 0)               //判断是否有数据
        {
            while(ECanbRegs.CANRMP.all != 0x00010000);
            ECanbRegs.CANRMP.all = 0x00010000;      //复位RMP标志,同时也复位中断标志
            Rec_l = ECanbMboxes.MBOX16.MDL.all;     //接收到的数据在接收邮箱Mbox16
            Rec_h = ECanbMboxes.MBOX16.MDH.all;
            PieCtrlRegs.PIEACK.bit.ACK9 = 1;
            EINT;
        }
    }
    
    
    
    ecan.c
    
    void InitECan(void)
    {
        struct ECAN_REGS ECanbShadow;
        EALLOW;
    
        //配置GPIO引脚工作在eCAN功能
        GpioCtrlRegs.GPAPUD.bit.GPIO16 = 1;     //禁止上拉GPIO16(CANTXB)
        GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0;     //使能上拉GPIO17(CANRXB)
        GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 3;
        GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 2;    //配置GPIO16为CANTXB
        GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 2;    //配置GPIO17为CANRXB
        //配置eCAN的RX&TX分别为eCAN的接收和发送引脚
    
        ECanbShadow.CANTIOC.all = ECanbRegs.CANTIOC.all;
        ECanbShadow.CANTIOC.bit.TXFUNC = 1;
        ECanbRegs.CANTIOC.all = ECanbShadow.CANTIOC.all;
        ECanbShadow.CANRIOC.all = ECanbRegs.CANRIOC.all;
        ECanbShadow.CANRIOC.bit.RXFUNC = 1;
        ECanbRegs.CANRIOC.all = ECanbShadow.CANRIOC.all;
        ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
        ECanbShadow.CANMC.bit.STM = 0;          //工作在正常模式
        ECanbShadow.CANMC.bit.SCB = 1;
        ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
    
        //初始化所有主设备控制区域为0,MCF所有的位都初始化为0
        ECanbMboxes.MBOX0.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX1.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX2.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX3.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX4.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX5.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX6.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX7.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX8.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX9.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX10.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX11.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX12.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX13.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX14.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX15.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX16.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX17.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX18.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX19.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX20.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX21.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX22.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX23.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX24.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX25.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX26.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX27.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX28.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX29.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX30.MSGCTRL.all = 0x00000000;
        ECanbMboxes.MBOX31.MSGCTRL.all = 0x00000000;
        ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;
        ECanbShadow.CANTA.all = 0xFFFFFFFF;
        ECanbRegs.CANTA.all = ECanbShadow.CANTA.all;
        ECanbShadow.CANRMP.all = ECanbRegs.CANRMP.all;
        ECanbShadow.CANRMP.all = 0xFFFFFFFF;
        ECanbRegs.CANRMP.all = ECanbShadow.CANRMP.all;
        ECanbShadow.CANGIF0.all = ECanbRegs.CANGIF0.all;
        ECanbShadow.CANGIF0.all = 0xFFFFFFFF;
        ECanbRegs.CANGIF0.all = ECanbShadow.CANGIF0.all;
        ECanbShadow.CANGIF1.all = ECanbRegs.CANGIF1.all;
        ECanbShadow.CANGIF1.all = 0xFFFFFFFF;
        ECanbRegs.CANGIF1.all = ECanbShadow.CANGIF1.all;
        /*为eCAN配置位时间参数*/
        ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
        ECanbShadow.CANMC.bit.CCR = 1;             //设置CCR=1
        ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
    
    //    ECanbShadow.CANES.all = ECanbRegs.CANES.all;      //////////////////////
    
        do
        {ECanbShadow.CANES.all = ECanbRegs.CANES.all;
        }while(ECanbShadow.CANES.bit.CCE != 1);    //等待CCE位被清除
        ECanbShadow.CANBTC.all = ECanbRegs.CANBTC.all;
        ECanbShadow.CANBTC.bit.BRPREG = 9;         //数据传输速率
        //150/10 = 15
        ECanbShadow.CANBTC.bit.TSEG2REG = 2;
        ECanbShadow.CANBTC.bit.TSEG1REG = 10;
        ECanbRegs.CANBTC.all = ECanbShadow.CANBTC.all;
        ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
        ECanbShadow.CANMC.bit.CCR = 0;             //设置CCR=0
        ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
        do
        {ECanbShadow.CANES.all = ECanbRegs.CANES.all;
        }while(ECanbShadow.CANES.bit.CCE != 0);    //等待CCE位被置位
        ECanbShadow.CANME.all = ECanbRegs.CANME.all;
        ECanbShadow.CANME.all = 0;
        ECanbRegs.CANME.all = ECanbShadow.CANME.all;
    
        //接收邮箱的ID
        ECanbMboxes.MBOX0.MSGID.all = 0x80C80000;  //扩展帧         /////////////
        ECanbMboxes.MBOX16.MSGID.all = 0x80C20000;  //扩展帧
    
        //邮箱0为TX,16为RX
        ECanbShadow.CANMD.all = ECanbRegs.CANMD.all;
        ECanbShadow.CANMD.bit.MD0 = 0;              //邮箱0,发送    /////////////
        ECanbShadow.CANMD.bit.MD16 = 1;             //邮箱16,接收
        ECanbRegs.CANMD.all = ECanbShadow.CANMD.all;
    
        //数据长度为8个byte
        ECanbMboxes.MBOX0.MSGCTRL.bit.DLC = 8;      ////////////
        ECanbMboxes.MBOX16.MSGCTRL.bit.DLC = 8;
    
        //设置发送优先级 2009.3.15 Add
        ECanbMboxes.MBOX0.MSGCTRL.bit.TPL = 0;      ////////////
        ECanbMboxes.MBOX16.MSGCTRL.bit.TPL = 0;
    
        //没有远方应答帧被请求
        ECanbMboxes.MBOX0.MSGCTRL.bit.RTR = 0;      //////////////看手册弄懂
        ECanbMboxes.MBOX16.MSGCTRL.bit.RTR = 0;
    
        //向邮箱RAM区写数据
        ECanbMboxes.MBOX0.MDL.all = 0x00000000;                //0x01234567;     //////////////看手册弄懂
        ECanbMboxes.MBOX0.MDH.all = 0x00000000;                //0x89ABCDEF;
        //邮箱使能Mailbox0
        ECanbShadow.CANME.all = ECanbRegs.CANME.all;
        ECanbShadow.CANME.bit.ME0 = 1;              //////////////
        ECanbShadow.CANME.bit.ME16 = 1;
        ECanbRegs.CANME.all = ECanbShadow.CANME.all;
        ECanbRegs.CANMIM.all = 0xFFFFFFFF;          //邮箱中断使能(只需要测试发送的时候,注释掉该句即可)
    
        //邮箱中断将产生在ECAN0INT
        ECanbRegs.CANMIL.all = 0;
        ECanbRegs.CANGIF0.all = 0xFFFFFFFF;
    
        //ECAN0INT中断请求线被使能
        ECanbRegs.CANGIM.bit.I0EN = 1;
        EDIS;
    
    }

  • 这个软件叫CANTest。我现在就是0号邮箱会正常发送我的数组。但是我给DSP发送CAN数据,进入不到接收中断。但是我如果在主函数把那个0号邮箱发送的那几句注释掉,我给DSP发送CAN数据,就能进入到中断,数值也是正确的,我不知道是为啥。

  • 我查看下相关资料后回复您。

  • 我咨询下资深工程师后回复您。

  • 请查看下该文件中的例程:

    www.ti.com/.../spra876b.pdf

  • 你好,大佬。我发现ECAN在做发送数据的时候,不单单要配置一个发送邮箱。还需要配置一个接收邮箱。我的这个代码是通过一个只有发送功能的代码改的。0号邮箱发送,16号邮箱接收。在编写接收代码的时候,我依旧用的这两个邮箱。是不是应该在配置一组发送和接收邮箱。这样的话应该就不会起冲突。我想问题是不是出在了这里?

  • 我发现ECAN在做发送数据的时候,不单单要配置一个发送邮箱。还需要配置一个接收邮箱

    在正常应用程序中情况并非如此。我认为您正在自检模式下使用 CAN 模块。

    是不是应该在配置一组发送和接收邮箱。

    如果需要接收邮箱来接收发送的数据,则需要手动配置。

    我想问题是不是出在了这里?

    不,没有问题。在自检模式下,如果要产生接收中断,需要将接收邮箱配置为与发送邮箱相同的MSGID。一旦执行此操作,当接收到消息时,将生成中断。

  • 大佬,我发现了个问题,我如果在中断加上if(ECanbRegs.CANRMP.all != 0)这条语句。我的16号邮箱能接收到我用CANTest发送的报文,ID:00C20000发送的。在调试窗口也能看到16号邮箱里面数据变化是正确的。但是为啥设置断点,程序跳不到断点那里?下面是我的调试图。我如果将中断的这条语句if(ECanbRegs.CANRMP.all != 0)删掉,我向00C20000发送报文是可以调到中断的那个断点处的。但是我的0号邮箱ID:00C80000就无法发送报文。不知道原因是什么,希望大佬能给解惑。

  • 好的,已向工程师跟进。