• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

DSP28335的CAN通信()

武飞扬头像
我要跑半马!
帮助1

问题描述

在学DSP28335的时候由于寄存器数量多且配置复杂,网上各路大神给出的代码基本上都不太能跑的通(可能是我移植的时候有些寄存器没配置好),所以在看了好几遍官方数据手册并且自己动手写了一遍代码之后,将一些容易错的地方记录了下来,文末也附上了一份代码,希望能对大家有所帮助,也欢迎各位一起谈论。

配置步骤

初始化

初始化主要是配置BRPREG和BT,这里需要注意的是CCR和CCE这两个位的读和写,具体流程图参考官方数据手册中给出的初始化流程,这里我也截图放在下面了。
学新通

配置引脚和邮箱

这一步就是根据需求配置发送接收引脚和输入输出邮箱,比较简单。

中断配置

中断的配置算是有些复杂的,下面结合官方数据手册中的中断结构图进行说明。
学新通
以接收中断为例进行说明。当接收到消息后RMP会被硬件置位,此时想要把成功接收的信息传达给中断线需要经过三个开关。第一个开关是CANMIM[x],这个位是中断使能位,如果被置位就说明RMP被置位后就会引起中断;第二个开关是CANMIL[x],这个位用来选择将前一个开关带来的接收成功的消息送到中断线0还是中断线1,因为CAN模块有两根中断线,所以要这第二个开关进行一个选择,与此同时对应中断标志位GMIF会被置位;最后一个开关是CANGIM,是用来选择是否将中断线接到CPU上去(这个说法不准确,但是可以先这样理解)。总之仔细看看这张图大概就能知道中断应该怎么配了。
同时在接收中断函数中,中断标志位的清除是通过向CANRMP对应位写1实现的,而无法通过GIFx.GMFx位实现。

注意事项

移植代码时输入输出引脚的改变

TI官方例程中将GPIO16、GPIO17分别配置成了ECanb的发送和接收引脚,进行代码移植时要注意自己开发板CAN模块的引脚是否与例程一致,不一致则要进行修改。

波特率选择

不同CAN通信设备的带宽是不一样的,要根据实际需求配置CAN总线的波特率,并且必须保证各个结点的波特率一致。

Bit Rate计算

上面说到了要根据实际需求配置CAN总线的波特率,那么应该怎么算呢,官方数据手册是这样给的:
学新通
学新通

CAN模块代码

CAN初始化

void ECAN_Init(void)
{
    struct ECAN_REGS ECanbShadow;

    //配置引脚
    EALLOW;
    GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 2;
    GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 2;
    GpioCtrlRegs.GPAPUD.bit.GPIO16  = 0;
    GpioCtrlRegs.GPAPUD.bit.GPIO17  = 0;
    GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 3;
    EDIS;

    //配置引脚用于CAN
    EALLOW;
    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;
    EDIS;

    ECanbRegs.CANME.all = 0;

    //接收邮箱
    ECanbMboxes.MBOX0.MSGID.all  = 0x9555AAA0;
    ECanbMboxes.MBOX1.MSGID.all  = 0x9555AAA1;
    ECanbMboxes.MBOX2.MSGID.all  = 0x9555AAA2;
    ECanbMboxes.MBOX3.MSGID.all  = 0x9555AAA3;
    ECanbMboxes.MBOX4.MSGID.all  = 0x9555AAA4;
    ECanbMboxes.MBOX5.MSGID.all  = 0x9555AAA5;

    //发送邮箱
    ECanbMboxes.MBOX16.MSGID.all = 0x9555AAB0;
    ECanbMboxes.MBOX17.MSGID.all = 0x9555AAB1;
    ECanbMboxes.MBOX18.MSGID.all = 0x9555AAB2;
    ECanbMboxes.MBOX19.MSGID.all = 0x9555AAB3;

    EALLOW;
    ECanbShadow.CANMD.all = ECanbRegs.CANMD.all;
    ECanbShadow.CANMD.bit.MD0  = 1;  //Rx
    ECanbShadow.CANMD.bit.MD1  = 1;  //Rx
    ECanbShadow.CANMD.bit.MD2  = 1;  //Rx
    ECanbShadow.CANMD.bit.MD3  = 1;  //Rx
    ECanbShadow.CANMD.bit.MD4  = 1;  //Rx
    ECanbShadow.CANMD.bit.MD5  = 1;  //Rx

    ECanbShadow.CANMD.bit.MD16 = 0;  //Tx
    ECanbShadow.CANMD.bit.MD17 = 0;  //Tx
    ECanbShadow.CANMD.bit.MD18 = 0;  //Tx
    ECanbShadow.CANMD.bit.MD19 = 0;  //Tx
    ECanbRegs.CANMD.all = ECanbShadow.CANMD.all;

    ECanbShadow.CANME.all = ECanbRegs.CANME.all;
    ECanbShadow.CANME.bit.ME0  = 1;
    ECanbShadow.CANME.bit.ME1  = 1;
    ECanbShadow.CANME.bit.ME2  = 1;
    ECanbShadow.CANME.bit.ME3  = 1;
    ECanbShadow.CANME.bit.ME4  = 1;
    ECanbShadow.CANME.bit.ME5  = 1;
    ECanbShadow.CANME.bit.ME16 = 1;
    ECanbShadow.CANME.bit.ME17 = 1;
    ECanbShadow.CANME.bit.ME18 = 1;
    ECanbShadow.CANME.bit.ME19 = 1;
    ECanbRegs.CANME.all = ECanbShadow.CANME.all;
    EDIS;

    ECanbMboxes.MBOX0.MSGCTRL.bit.DLC  = 8;
    ECanbMboxes.MBOX1.MSGCTRL.bit.DLC  = 8;
    ECanbMboxes.MBOX2.MSGCTRL.bit.DLC  = 8;
    ECanbMboxes.MBOX3.MSGCTRL.bit.DLC  = 8;
    ECanbMboxes.MBOX4.MSGCTRL.bit.DLC  = 8;
    ECanbMboxes.MBOX5.MSGCTRL.bit.DLC  = 8;
    ECanbMboxes.MBOX16.MSGCTRL.bit.DLC = 8;
    ECanbMboxes.MBOX17.MSGCTRL.bit.DLC = 8;
    ECanbMboxes.MBOX18.MSGCTRL.bit.DLC = 8;
    ECanbMboxes.MBOX19.MSGCTRL.bit.DLC = 8;

    ECanbMboxes.MBOX16.MSGCTRL.bit.RTR  = 0;
    ECanbMboxes.MBOX17.MSGCTRL.bit.RTR  = 0;
    ECanbMboxes.MBOX18.MSGCTRL.bit.RTR  = 0;
    ECanbMboxes.MBOX19.MSGCTRL.bit.RTR  = 0;


    EALLOW;
    ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
    ECanbShadow.CANMC.bit.CCR = 1;
    ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
    EDIS;
    do
    {
        ECanbShadow.CANES.all = ECanbRegs.CANES.all;
    }while(ECanbShadow.CANES.bit.CCE != 1 );

    EALLOW;
    ECanbShadow.CANBTC.all = ECanbRegs.CANBTC.all;
    ECanbShadow.CANBTC.bit.BRPREG = 9;
    ECanbShadow.CANBTC.bit.TSEG2REG = 2 ;
    ECanbShadow.CANBTC.bit.TSEG1REG = 10;  // Bit time = 15
    ECanbShadow.CANBTC.bit.SAM = 1;
    ECanbRegs.CANBTC.all = ECanbShadow.CANBTC.all;

    ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
    ECanbShadow.CANMC.bit.CCR = 0;
    ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
    EDIS;
    do
    {
      ECanbShadow.CANES.all = ECanbRegs.CANES.all;
    } while(ECanbShadow.CANES.bit.CCE != 0 );

    ECanbRegs.CANTA.all = 0xFFFFFFFF;  //清除所有TA位

    EALLOW;
    ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
    ECanbShadow.CANMC.bit.STM = 0;    
    ECanbShadow.CANMC.bit.SCB = 1;    // eCAN mode (reqd to access 32 mailboxes)
    ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;
    EDIS;

    EALLOW;
    ECanbRegs.CANGIM.all = 0;
    ECanbRegs.CANMIM.all = 0x003F;  //使能上面的接收邮箱(0-5号邮箱)中断
    ECanbRegs.CANMIL.all = 0;

    ECanbShadow.CANGIM.all = ECanbRegs.CANGIM.all;
    ECanbShadow.CANGIM.bit.I0EN = 1;  //选择中断线0
    ECanbRegs.CANGIM.all = ECanbShadow.CANGIM.all;

    PieCtrlRegs.PIECTRL.bit.ENPIE=1;
    PieCtrlRegs.PIEIER9.bit.INTx7=1;  //9.7
    PieVectTable.ECAN0INTB = &ISRECanRx;
    IER|=M_INT9;
    EINT;
    EDIS;
}
学新通

CAN接受中断

interrupt void ISRECanbRx(void)
{

    PieCtrlRegs.PIEACK.bit.ACK9 = 1;

    struct ECAN_REGS ECanbShadow;
    Uint16 group;
    Uint32 high;  //用于存储接收邮箱的内容
    Uint32 low;   //用于存储接收邮箱的内容
    volatile struct MBOX* Mailbox;
    group = (ECanbRegs.CANGIF0.all)&0x3F;   //判断是哪个接收邮箱触发的中断
    Mailbox = &ECanbMboxes.MBOX0   group;   //取触发中断邮箱的地址
    switch(group)  //我这里是把0-5号邮箱配置成了接收邮箱,所以下面case的取值是0-5
    {
    case 0:
        low     = Mailbox->MDL.all    //低32位
        high    = Mailbox->MDH.all    //高32位
        break;
    case 1:
        //跟上面是一样的,把邮箱里的数取出来
        break;
    case 2:

        break;
    case 3:

        break;
    case 4:

        break;
    case 5:

        break;
    default:
        break;
    }
    ECanbRegs.CANRMP.all = 0x0000003F;   //清除GIF0.GMIF位,即中断标志位
}
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggggck
系列文章
更多 icon
同类精品
更多 icon
继续加载