树莓派spi转can通信之C编程实现(二)

2023-10-28

一.相关库的安装

  1. wiringPi
    链接网址: http://wiringpi.com/
    一个函数库,在编程时节省底层汇编以操作pi的功能引脚,对pi的引脚也进行了再次编号。

  2. BCM2835 C Library
    链接网址: http://www.airspayce.com/mikem/bcm2835/
    C Library可以理解为使用C语言实现的底层驱动(GPIO、SPI和UART等)

linux操作系统将 CAN 设备作为网络设备进行管理, 而且Linux 提供了SocketCAN 接口,允许同太网的socket通信一般地进行CAN 总线通信。(参考-炒鸡感谢这位博主分享了《Linux Can编程详解》)

使用 SocketCAN 实现通信。(参考华清远见

二.编前测试
1.cansend:发送请求的命令。
命令格式:cansend {接口} {CAN-ID}#{数据}
(在CAN-ID和数据之间插入#)

2.用candump接受来自can总线的数据
接收格式:candump {接口},{CAN-ID}:{bitmask}
CAN-ID分别对应于不同的请求和响应。
bitmask指定要分配要获得的数据。(当它变成CAN-ID或bitmask自变量指定的CAN-ID时,我们就会获得比特运算所接收到的数据。)

3.开始接上BMS设备的can口后直接用candump接收没有反应,打开另一端口对BMS设备发送任意数据后出现:
在这里插入图片描述
多发了几次,结果出现了另一个问题:No buffer space available -----说缓冲区内存不足
在这里插入图片描述
而重启就可再发送了:
在这里插入图片描述
4.尝试解决buffer的问题,发现只能发11条。网上有人说是tx_queue_len的的问题:
先sudo ip link set can0 down
在这里插入图片描述
默认值为10,直接改成100试试
在这里插入图片描述
可以看到,之后果然cansend个几十条都没有报错。那就回到第一个问题,查看一下错误信息:
在这里插入图片描述

  1. “ERROR-PASSIVE”:CAN控制器的当前状态:

  2. “restart-ms 0”
    自动重启的延时时间。如果设为非零值, 在总线关闭的情况下,在设定的数量毫秒后CAN控制器被自动触发。这个功能默认是关闭的。

  3. tq 250 prop-seg 2 phase-seg1 3 phase-seg2 2 sjw 1
    CAN比特时序参数:以ns为单位显示时间份额(tq-time quanta)、传播段(prop-seg : propagation segment)、相位缓冲段1和2(phase-seg:phase buffer),以tq为单位显示同步跳转宽度(sjw:synchronisation jump width)。这些变量允许定义与硬件无关。

  4. “re-started bus-errors arbit-lost error-warn error-pass bus-off”
    分别是显示重启的次数、总线和仲裁丢失错误,错误主动(error-warning)、错误被动(error-passive)、和总线关闭的状态变化。接收的过载错误在 统计信息的"overrun"域下面列出。
    5.TX :将套接字缓冲区的CAN帧发送到CAN控制器;RX :从CAN控制器的CAN帧读取到套接字缓冲区。

5.再次尝试和解析:
在这里插入图片描述
打开另一终端,发送任意数据时:出现了bus-off:
在这里插入图片描述
CAN网络节点的三种状态:
  1)主动错误,能正常的进行总线通信,错误产生时,发送主动错误帧。
  2)被动错误,能够进行总线通信,错误产生时,发送被动错误帧。
  3)总线关闭,不能收发任何报文。
  
  对于bus-off也找到了比较好的回答:(参考what is CAN bus-off state ?博友的CAN BusOff相关知识点
(1)CAN控制器必须保留两个计数器,称为发送和接收错误计数器。它们从0开始,根据CAN标准指定的一组规则递增(在出现错误时)和递减(每当控制器执行成功的tx/rx时)。计数器的值影响控制器的错误处理模式(error-active和error-passive),并最终(当传输错误计数器超过255的值时)过渡到busoff状态。粗略地说,当控制器处于这种状态时,它就从总线断开。强制地,它停止传送和确认帧。它是否保持接收帧取决于实现。

(2)当一个CAN节点检测到错误时,它将发送错误帧,这将干扰总线通信,最终完全禁用其他节点的有效帧。为了防止这种情况,发送太多错误帧的节点将完全进入总线断开状态,在这种状态下,它不再参与流量。通常,总线断开是指向节点本身潜在问题的错误条件(错误配置…)。所有节点是因为(由于CAN的错误机制)总线上任何节点检测到的任何错误都会立即广播给(并由)所有其他节点计算,只有少数例外。

6.确实我的BMS充电均衡应该是烧坏了,会一直报错,可能是这个持续报错影响了其他节点的数据发送和接收,暂抛弃BMS,计划用Ardiuno加MCP2515来模拟BMS设备来测试发送和接收can口的数据(参考Github,Seeed-Studio大佬的分享还有这位网友的经验贴):
接线图如下:
在这里插入图片描述
代码也是参考网友czw74,分享得BUS_CAN文件里的例子“send”,按其要求改了波特率设定:
(如果你的can总线波特率是500KBPS,
CAN.begin(CAN_1000KBPS) can通讯波特率设置为1000KBPS
差了1倍,原因是mcp_can.cpp的代码是以16MHz晶振的CAN总线模块编写的,而我们使用的MCP2515 CAN总线模块的晶振是8M的。所以代码里面要把CAN.begin()设高一倍。)
然鹅树莓派的接收端还是出现以上相似的错误:

can0 20000004 [8] 00 04 00 00 00 00 00 00 ERRORFRAME controller-problem {rx-error-warning}
在这里插入图片描述
然后折腾了一整天无果,找到一个问题帖,下面的cluse网友默默说了一句:
MCP2515模块,右下角那两个pin,要短路。
实在没有办法的时候蛮试了一下,把Arduino端接的MCP2515_CAN模块哪J1(jumper for 120Ω Termination),两个pin角短接后,竟然成功接收数据了:
在这里插入图片描述
测试成功,这是是什么原理呢,找了一下原理图:

在这里插入图片描述这里有J1和J2 两个端口,然后我的canH/L 的线接在J2端口,此时是没有接上120Ω的电阻,而短接J1的两端口等于是在J2两端接上了一个120Ω的电阻,而接这个电阻干嘛用?
在这里也找到一位博主的解释(can总线为什么要有两个120的终端电阻):
既抗干扰:CAN总线两端必须连接终端电阻才可以正常工作,终端电阻应该与通讯电缆的阻抗相同,典型值为120欧姆.其作用是匹配总线阻抗,提高数据通信的抗干扰性及可靠行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

树莓派spi转can通信之C编程实现(二) 的相关文章

  • C++虚函数的作用和实现原理

    一 什么是虚函数 在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数 用法格式为 virtual 函数返回类型 函数名 参数表 函数体 实现多态性 通过指向派生类的基类指针或引用 访问派生类中同名覆盖成员函数 二

随机推荐