• ARDUINO+MCP2515实现CAN通讯接收


    我的学习过程有几个关键点;
    1、MCP2515 CAN总线模块与ARDUINO UNO R3的接线方式;
    2、程序set_mask_filter_recv的参数设置,mcp_can_dfs.h库文件设置;
    3、MCP2515 CAN总线模块与mcp_can.cpp库文件的关联;

    第一点看下面图片:

    <ignore_js_op>
    <ignore_js_op>

    首先在ARDUINO UNO R3找到SCK,MIOS,MOIS,INT0,5V,GND,连接到MCP2515 CAN总线模块的对应接口;
    CANH,CANL接到can总线上;
    CS管脚接到arduino的9号管脚,单独拿出来讲,是因为此管脚位置可以在程序里面设置,设置如下;
    const int SPI_CS_PIN = 9;
    INT管脚接到arduino的2号管脚,单独拿出来讲,是因为此管脚位置可以在程序里面设置,设置如下;
    attachInterrupt(0,MCP2515_ISR, FALLING);  //0代表INT01代表INT1,看ARDUINO UNO R3管脚定义。

    延伸一下,关于不同版本的ARDUINO的INT管脚位置,

    参考如下链接
    Arduino——外部中断的使用

    接线图如下

    第二点,上代码和库文件

    GITHUB里面搜索Seeed-Studio/CAN_BUS_Shield得到
    GITHUB里面的MCP_CAN库文件
    https://github.com/Seeed-Studio/CAN_BUS_Shield

    程序set_mask_filter_recv代码(我做了些修改)如下


    1. #include <SPI.h>
    2. #include "mcp_can.h"

    3. // the cs pin of the version after v1.1 is default to D9
    4. // v0.9b and v1.0 is default D10
    5. const int SPI_CS_PIN = 9;

    6. MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin


    7. unsigned char flagRecv = 0;
    8. unsigned char len = 0;
    9. unsigned char buf[8];
    10. char str[20];

    11. void setup()
    12. {
    13.     Serial.begin(115200);

    14.     while (CAN_OK != CAN.begin(CAN_1000KBPS))              // init can bus : baudrate = 500k
    15.     {
    16.         Serial.println("CAN BUS Shield init fail");
    17.         Serial.println(" Init CAN BUS Shield again");
    18.         delay(100);
    19.     }
    20.     Serial.println("CAN BUS Shield init ok!");

    21.     attachInterrupt(0,MCP2515_ISR, FALLING); // start interrupt


    22.     /*
    23.      * set mask, 0x代表16进制,0b代表2进制,屏蔽器的0xf代表0b1111
    24.      */
    25.      //       屏蔽器序号   是否接受扩展桢 0 不接受 1:接受        32位屏蔽器 f 位置必须匹配 0 不关心
    26.     CAN.init_Mask(0,                  1,                                        0xffff00ff);   
    27.     CAN.init_Mask(1,                  1,                                        0xffff00ff);  
    28.     Serial.println("MASK IS OK");

    29.     /*
    30.      * set filter,以上MASK函数0xffff00ff中,can总线内 帧 ID中f位置必须符合Filt设置的数值,才会将帧的DATA存入缓存器
    31.      */
    32.     //       过滤器序号   是否接受扩展桢 0 不接受 1:接受            32位过滤器:屏蔽器为1的位必须匹配 0 不关心
    33.     CAN.init_Filt(0,                  1,                                              0x14fa0003);                          // mcp2515 0号过滤器
    34.     CAN.init_Filt(1,                  1,                                              0x14fa0004);                          // mcp2515 1号过滤器
    35.     CAN.init_Filt(2,                  1,                                              0x14fa0005);                          // mcp2515 2号过滤器
    36.     CAN.init_Filt(3,                  1,                                              0x14fa0010);                          // mcp2515 3号过滤器
    37.     CAN.init_Filt(4,                  1,                                              0x14fa0050);                          // mcp2515 4号过滤器
    38.     CAN.init_Filt(5,                  1,                                              0x14fa0051);                          // mcp2515 5号过滤器
    39.     Serial.println("FILT OK");
    40. }

    41. void MCP2515_ISR()
    42. {   
    43.     flagRecv = 1;
    44. }

    45. void loop()
    46. {   
    47.     if(flagRecv)                   // check if get data
    48.     {
    49.         flagRecv = 0;                // clear flag
    50.         CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf
    51.         Serial.println("READ MESSAGE OK");

    52. CAN.printMessage();
    53.      }
    54. }

    55. /*********************************************************************************************************
    56.   END FILE
    复制代码



    此程序是屏蔽接收can信息,所以需要打开mcp_can_dfs.h找到下面两行代码置0

    <ignore_js_op>


    整个程序的思路就是如下:

    1、调用<SPI.h>, "mcp_can.h"两个库文件,至于怎么添加库文件自己找教程;
    2、设置CS管脚为9号IO管脚
    3、预设flagRecv=0,len=0,buf=[8], str[20],意思是flagRecv,len默认状态为0,,buf为8组8个字节的数据组,str不知道是什么,有知道的高手请告知,个人臆断欢迎指正。
    4、SETUP()函数,设置串口通讯码率为115200,can通讯波特率为1000KBPS(这里做一个记号)
    5、设置中断函数attachInterrupt(0,MCP2515_ISR, FALLING),意思是:中断INT接2号IO管脚,自定义中断函数名为MCP2515_ISR,使用下降沿触发中断。
    6、 CAN.init_Mask(0,  1, 0xffff00ff)设置0号屏蔽器,可以接收扩展桢,帧的ID符合0xffff00ff这个格式, 32位屏蔽器 f 位置必须匹配 0 不关心,f相当于开关来启动下面的过滤器。
    7、 CAN.init_Filt(0,1,0x14fa0003)设置0号过滤器,可以接收扩展桢,ID符合0x14fa0003的扩展桢都可进入缓存器。
    8、设置中断函数 MCP2515_ISR的状态标志,flagRecv=1。
    9、循环函数loop(),每当一个下降沿信号进来,flagRecv置0,CAN.readMsgBuf(&len, buf)读取缓存器内的信息,CAN.printMessage()can打印出信息。

    以上是一个菜鸟的理解,欢迎大神门指正。
    =========分割线=====================分割线===================分割线====================

    关于怎么理解程序中各个函数的意思和使用方法——————没什么特别的方法,自己分别打开【mcp_can.cpp】【mcp_can.h】【mcp_can_dfs.h】【MCP2515中文详解.pdf】,一个个不懂的翻译和搜索学习。

    例如:CAN.init_Mask()   CAN.readMsgBuf()   CAN.printMessage()   这几个函数在哪里定义的,内容是怎样的都可以在上面的文件找到。

    =========分割线=====================分割线===================分割线====================

    上面有一个记号的地方需要重点说明的

    如果你的can总线波特率是500KBPS

    CAN.begin(CAN_1000KBPS)   can通讯波特率设置为1000KBPS

    差了1倍,原因是mcp_can.cpp的代码是以16MHz晶振的CAN总线模块编写的,而我们使用的MCP2515 CAN总线模块的晶振是8M的。所以代码里面要把CAN.begin()设高一倍。
    <ignore_js_op>
    看上面的模块照片,晶振上打字是8.000M。
    =========分割线=====================分割线===================分割线====================

    代码写好了需要自己搭建测试台架,一个can发送装置提供CAN信号。
    下面的照片是我在串口接收到的信息,显示了ID和DATA


    <ignore_js_op>



  • 相关阅读:
    uva 10129 play on words——yhx
    uva 10305 ordering tasks(超级烂题)——yhx
    uva 816 abbott's revenge ——yhx
    php 格式化数字 位数不足前面加0补足
    NetBeans-xdebug的安装
    php 文件file常用的操作
    pg 匹配中文字符
    隐藏 php apache 的版本号
    php redis扩展
    php 二维数组的排序
  • 原文地址:https://www.cnblogs.com/anandexuechengzhangzhilu/p/10711964.html
Copyright © 2020-2023  润新知