极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 108373|回复: 15

经验分享——ARDUINO+MCP2515实现CAN通讯接收

[复制链接]
发表于 2017-11-17 15:56:37 | 显示全部楼层 |阅读模式
本帖最后由 czw74 于 2017-11-17 17:04 编辑

很开心~经过1个月的时间,自己摸索还有坛友-275891381(网名:依叶知秋)是指导帮助。终于搞懂了can接收的程序——set_mask_filter_recv。
从程序的名称可以知道,这个程序是通过设置屏蔽器和过滤器来实现can接收的。

技术含量低老鸟勿喷,写下分享贴子,意在让更多在摸索学习的新手有多一份参考文章。好了废话不多说,下面开始学习过程。

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

第一点看下面图片:




首先在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代表INT0,1代表INT1,看ARDUINO UNO R3管脚定义。
延伸一下,关于不同版本的ARDUINO的INT管脚位置,可以参考如下链接
Arduino教程——外部中断的使用
http://www.arduino.cn/thread-2421-1-1.html
接线图如下


第二点,上代码和库文件
首先库文件是坛友-275891381(网名:依叶知秋)提供的,再次谢谢依叶知秋的分享精神,不过大家也可以在里面搜索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




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

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的代码是以16M晶振的CAN总线模块编写的,而我们使用的MCP2515 CAN总线模块的晶振是8M的。所以代码里面要把CAN.begin()设高一倍。

看上面的模块照片,晶振上打字是8.000M。

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

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


好了,文章写到这里,不足之处欢迎指正,谢谢大家!




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

 楼主| 发表于 2017-11-17 15:56:38 | 显示全部楼层
沙发自己坐!
回复 支持 反对

使用道具 举报

发表于 2017-11-17 18:32:01 | 显示全部楼层
请问下楼主 那张UNO PINOUT 的图片是怎么做的
回复 支持 反对

使用道具 举报

发表于 2017-11-17 18:39:30 | 显示全部楼层
Name_006 发表于 2017-11-17 18:32
请问下楼主 那张UNO PINOUT 的图片是怎么做的

http://www.geek-workshop.com/thread-11826-1-1.html
回复 支持 反对

使用道具 举报

发表于 2017-11-20 08:42:40 | 显示全部楼层
正好用到CAN,学习了。
回复 支持 反对

使用道具 举报

发表于 2017-11-26 11:46:31 | 显示全部楼层
Name_006 发表于 2017-11-17 18:32
请问下楼主 那张UNO PINOUT 的图片是怎么做的

很明显,是用作图软件做的。。。 目测画风应该是CAD制作 然后PS处理。。。
回复 支持 反对

使用道具 举报

发表于 2018-3-7 14:23:59 | 显示全部楼层
mcp_can_dfs.h该文件内没有你说的那两行代码
回复 支持 反对

使用道具 举报

发表于 2018-3-7 14:29:44 | 显示全部楼层
两端都是提示初始化成功,但通信不上
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-5-26 09:04:32 | 显示全部楼层
本帖最后由 czw74 于 2018-5-26 09:08 编辑
fly60000 发表于 2018-3-7 14:23
mcp_can_dfs.h该文件内没有你说的那两行代码


我刚刚打开附件了,确认是有的,你用记事本打开搜索一下。

你确定是用的MCP2515_CAN模块,剩下的就是我再帖子后面提到的晶振的倍率差问题了。你按我的帖子设置。
论坛上的少,可以加我QQ119917261.
回复 支持 反对

使用道具 举报

发表于 2019-2-19 22:26:52 | 显示全部楼层
你好 如果想设置波特率为1M该怎么办呢 ,可不可以自己把模块上的8M晶振换成16M呀
回复 支持 反对

使用道具 举报

发表于 2019-4-17 12:49:41 | 显示全部楼层
有点蒙啊 小白一个
回复 支持 反对

使用道具 举报

发表于 2019-8-31 16:48:32 | 显示全部楼层
楼主,我用的你的例程为啥波特率500识别不到呀
回复 支持 反对

使用道具 举报

发表于 2019-8-31 17:55:01 | 显示全部楼层
data显示不出来  ,dlc是0,是啥问题呢?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2020-12-22 16:53:53 | 显示全部楼层
你好   我用了您的代码,编译一直出错,还没找到原因
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-28 22:45 , Processed in 0.057998 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表