DSP28335的CAN总线通讯

本文将演示DSP28335的CAN通讯,并用示波器验证CAN总线、CAN模块的RX、TX管脚的电压波形。话不多说,直接上代码

Uint32  TestMbox1 = 0;//用来接收mailbox里面的值
Uint32  TestMbox2 = 0;
Uint32  TestMbox3 = 0;
Uint32  TestMbox4 = 0;
Uint32  TestMbox5 = 0;
Uint32  TestMbox6 = 0;
Uint32  received1[20];
Uint32 received2[20];
Uint32  cnt=0;
Uint32 i1=0;
Uint32 j1=0;
interrupt void ECAN1Receiver(void)
{
if(ECanbRegs.CANRMP.bit.RMP25==1){
           Mailbox1 = &ECanbMboxes.MBOX0 + 25;  //CANB读数据
           TestMbox1 = Mailbox1->MDL.all; // = 0x (n is the MBX number)
           TestMbox2 = Mailbox1->MDH.all; // = 0x (a constant)
           received1[i1]=TestMbox1;
           received1[i1+1]=TestMbox2;
           i1=i1+2;
           TestMbox3 = Mailbox1->MSGID.all;// = 0x (n is the MBX number)

           ECanbRegs.CANRMP.bit.RMP25=1;
}
if(ECanbRegs.CANRMP.bit.RMP26==1){
           Mailbox2 = &ECanbMboxes.MBOX0 + 26;  //CANB读数据
           TestMbox4 = Mailbox2->MDL.all; // = 0x (n is the MBX number)
           TestMbox5 = Mailbox2->MDH.all; // = 0x (a constant)
           TestMbox6 = Mailbox2->MSGID.all;// = 0x (n is the MBX number)
           received2[j1]=TestMbox4;
           received2[j1+1]=TestMbox5;
                      j1=j1+2;
           ECanbRegs.CANRMP.bit.RMP26=1;
}


    PieCtrlRegs.PIEACK.bit.ACK9=1;

}
void main(){
struct ECAN_REGS ECanbShadow;//因为CAN的控制寄存器需要32位寻址,不能单独对位操作,所以定义一个中间的寄存器
 InitSysCtrl();
 InitECanbGpio();//这里使用Ecan模块的b模块,直接用例程的,代码就不贴了
 DINT;
 InitPieCtrl();
 IER = 0x0000;
 IFR = 0x0000;
 InitPieVectTable();
 
   EALLOW;
 ECanbRegs.CANGIM.bit.I0EN=1;//中断线0使能
 PieVectTable.ECAN0INTB=&ECAN1Receiver;//关联中断子函数,CAN模块的中断线有0和1,这里我使用了0中断线
   EDIS;
   
 InitECan();//这个是Ecan模块的初始化部分,这里直接抄例程的,代码就不贴出来了。波特率设置为500k baud/s
  
  Eallow;
   ECanbRegs.CANMIM.bit.MIM25=1;//邮箱中断使能
   ECanbRegs.CANMIM.bit.MIM26=1;//邮箱中断使能
   ECanbRegs.CANMIL.all=0;//邮箱中断级别,设置为0则对应在中断线0出产生中断
   ECanbRegs.CANGIF0.all=0xffffffff;//全局中断标志寄存器,写1清0
   PieCtrlRegs.PIEIER9.bit.INTx7=1;
    IER |=0x0100;
   IFR=0x0000;
   EDIS;
    EINT;
    ERTM;
     ECanbMboxes.MBOX24.MSGID.all = 0x95555555;//扩展帧,标识符29位
     ECanbMboxes.MBOX25.MSGID.all = 0x96666666;//扩展帧,标识符29位
     ECanbMboxes.MBOX26.MSGID.all = 0x97777777; //扩展帧,标识符29位
     ECanbShadow.CANMD.all = ECanbRegs.CANMD.all;
     ECanbShadow.CANMD.bit.MD24=0;//配置24作为发送
     ECanbShadow.CANMD.bit.MD25 = 1;//配置eCANB的25和26号作为接收邮箱
     ECanbShadow.CANMD.bit.MD26=1;
     ECanbRegs.CANMD.all = ECanbShadow.CANMD.all;
   
 //在配置标识符之前必须unable,然后在enable
   ECanbShadow.CANME.all = ECanbRegs.CANME.all;
   ECanbShadow.CANME.bit.ME24 = 1;
   ECanbShadow.CANME.bit.ME25 = 1;
   ECanbShadow.CANME.bit.ME26 = 1;
   ECanbRegs.CANME.all = ECanbShadow.CANME.all;//使能邮箱
   
  ECanbMboxes.MBOX24.MSGCTRL.bit.DLC = 8;//8字节的发送数据

   ECanbMboxes.MBOX24.MDL.all = 0xAABBCCDD;//发送的数据
   ECanbMboxes.MBOX24.MDH.all = 0xDDCCBBAA;
   for(i=0; i < 20; i++){       //连发20帧数据
       ECanbShadow.CANTRS.all = 0;
       ECanbShadow.CANTRS.bit.TRS24 = 1;             // TRS一旦被置位,则立即发送
       ECanbRegs.CANTRS.all = ECanbShadow.CANTRS.all;

       do
        {
           ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;

        } while(ECanbShadow.CANTA.bit.TA24 == 0 );   // Wait for TA5 bit to be set..//如果线没有连接,如果线连接错误
       ECanbShadow.CANTA.all = 0;
       ECanbShadow.CANTA.bit.TA24 = 1;               // Clear TA5
       ECanbRegs.CANTA.all = ECanbShadow.CANTA.all;
   }

}

以上就是发送和接收的程序。下面我将展示主DSP发送、子DSP接收时的情况
DSP28335的CAN总线通讯_第1张图片
对应的帧格式如上所示,具体可以参考这篇博文。CAN协议帧格式
这里采用扩展帧,对于发送部分用示波器测的CAN总线上的波形如下,黄色代表CAN总线电压,红色代表子模块DSP的接收RX管脚电压。这里看到RX管脚和CAN总线相反。是因为CAN总线显性逻辑"0"对应电压2V,而隐性逻辑"1"对应电压0V
DSP28335的CAN总线通讯_第2张图片
根据500k的波特率,上图128位刚好发送256us,再来看一下数据帧起始地方是否和协议相对应,如下图
DSP28335的CAN总线通讯_第3张图片
黄色代表RX1,红色代表RX2(两个DSP的CAN模块来接收)可见首先发送0,再发送1 0101 0101 01 (起始帧+前11位标识符)完全正确

再看数据区
DSP28335的CAN总线通讯_第4张图片
黄线代表CAN总线差分电压。数据从第40位开始。故对应78us。数据我定义发送AABBCCDD DDCCAABB 这8个字节。这里可以看出白色这条虚线左边对应DLC 刚好是1000(0111取反),右边是数据对应AAB(后面的就不一一列出来了)。

当然实际中的CAN不会这么简单。

1. 考虑多个邮箱同时发送,这是要对邮箱设置优先级
2. 同时向总线请求发送时,这时涉及竞争机制。即比较标识符的位
3. 当接收邮箱不断接收到值时,是否覆盖原来的值,这也是需要考虑的问题
4. 使能接收屏蔽,标识符匹配才能被正确的接收。如果只需要一部分匹配,那就要设置接受屏蔽寄存器
5. 另外,此次发了8 byte个数据,不过我发现如果前面发送i byte个数据,再发送j byte个数据,其中i>j,那么后面的数据只会替代掉属于它的那几个byte,有几个byte还是上一次发送i 个byte时候的数据。这个问题暂时还没有解决。还望大家指导下。
6. 最后一点也是最近调试的时候发现了,当CAN 总线上检测出现5个相同的电平位之后,会自动发送一个相反的电平位。这个要注意下

你可能感兴趣的:(DSP28335)