基于DSP28335的CAN通信(附代码)

这篇具有很好参考价值的文章主要介绍了基于DSP28335的CAN通信(附代码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

问题描述

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

配置步骤

初始化

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

配置引脚和邮箱

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

中断配置

中断的配置算是有些复杂的,下面结合官方数据手册中的中断结构图进行说明。
基于DSP28335的CAN通信(附代码)
以接收中断为例进行说明。当接收到消息后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总线的波特率,那么应该怎么算呢,官方数据手册是这样给的:
基于DSP28335的CAN通信(附代码)
基于DSP28335的CAN通信(附代码)文章来源地址https://www.toymoban.com/news/detail-503321.html

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位,即中断标志位
}

到了这里,关于基于DSP28335的CAN通信(附代码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • DSP28335学习笔记-产生PWM波 ——从应用角度出发

    关于DSP28335的书籍有很多,但都是从乏味的寄存器开始入手。对于新手可能不是很友好,因此关于DSP的学习记录我打算从应用入手去学习寄存器的用法和配置。 此次实验用J4模块引脚的XPWM1和XPWM2分别产生ePWM1A和ePWM1B,对应芯片GPIO0和GPIO1引脚。 黄色线为EPWM1A,紫色线为EPWM1B。

    2024年02月06日
    浏览(27)
  • DSP28335使用SPI从AD2S1210(旋变芯片)读取位置

    精准的转子位置对于电机精确控制来说至关重要,利用旋转变压器获取转子位置角度是一种常见方案。因此在电控程序中只需要通过主控芯片(以 DSP28335 为例)与旋变解码芯片(以 AD2S1210 为例)进行通信(以 SPI通信 为例)。 在实际操作中,通过SPI从旋变芯片读取绝对位置时,读取

    2024年02月13日
    浏览(28)
  • 【无人机通信】基于机器学习求解4G网络无人机基站布局优化问题附Matlab代码

     ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,代码获取、论文复现及科研仿真合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab完整代码及仿真定制内容点击👇 智能优化算法       神经网络预测       雷达通信       无

    2024年04月15日
    浏览(45)
  • Autoware.universe部署06:使用DBC文件进行UDP的CAN通信代码编写

    根据CAN协议编写DBC文件,通过DBC文件编写ROS2包进行UDP通信,获取底盘速度转发至Autoware.Universe以及订阅Autoware.Universe控制命令,下发至CAN控制底盘运动(本文适用于CAN盒通过网线连接进行UDP通信),本系列其他文章: Autoware.universe部署01:Ubuntu20.04安装Autoware.universe并与Awsim联调

    2024年04月24日
    浏览(47)
  • STM32 CAN通信自定义数据包多帧连发乱序问题

    can标准帧中每一帧只能传输8字节,而应用中传输一包的内容往往超过8字节,因此需要把一个包拆成多个帧发送,接收端才把收到的多帧重新组装成一个完整的包 在一问一答的两块板间通信,多帧连发是能够按照顺序发送的。但是,在一个主板和多个从板之间轮询一问一答的

    2024年01月17日
    浏览(26)
  • 【QT5:CAN卡通信的上位机-代码练习-收发数据+布局+引用外部库+基础样例(1)】

    有句话叫做,出来还混,早晚是要还得,当时为快点使用完成can的qt上位机,偶然在网上找到一个样例,正好能运行,就直接拿着那个样例进行改了,后来上位机遇到点精准时间问题,一时间不知道如何调,正好也借着这个机会,学习一下样例代码,纯手打一遍。 实验环境还

    2024年02月01日
    浏览(24)
  • 基于硬件隔离增强risc-v调试安全1_问题描述

    安全之安全(security²)博客目录导读 2023 RISC-V中国峰会 安全相关议题汇总 说明:本文参考RISC-V 2023中国峰会如下议题,版权归原作者所有。   /

    2024年02月10日
    浏览(29)
  • 「PAT乙级真题解析」Basic Level 1097 矩阵行平移 (问题分析+完整步骤+伪代码描述+提交通过代码)

    乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范。从小白开始逐步掌握用编程解决问题。 PAT (Basic Level) Practice 1097 矩阵行平移 题设给定了明确的步骤, 要求按照给定方式进行\\\"平移\\\"操作, 然后计算各行元素的和并输出。 \\\"计算各行元素之和\\\"以及

    2023年04月10日
    浏览(80)
  • STM32在进行CAN总线多节点通信时,同时发数据会一直收不到某设备数据的问题及解决

    最近在开发Canopen项目中,进行一主多从设备通信时,主站发送同步帧,两个从站往往只有帧ID优先级高的设备可以让主站接收到数据,而另一个从设备的数据往往接收不到。但当我关闭其中一个can从设备,另一个就可以和主站设备通信正常。经过排查发现,是由于Can的冲突解

    2024年02月03日
    浏览(43)
  • 基于FPGA的CAN通讯verilog代码设计

    FPAGA本篇文章参考github网站的开源项目can-FPGA-master编写改进 在调试过程中,发现该项目无法在quartus pro13.0的环境下运行通过,代码存在错误,并且对于EP4系列的芯片来说有太多的IO口,无法在烧录,所以笔者对此进行了改进。  can_top模块 can_tx传输数据模块 can_rx接收数据模块

    2024年02月08日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包