linux 中在命令行中使用 SocketCAN(以 PCAN

2020-06-08  本文已影响0人  刘亚彬92

1 什么是 SocketCAN

根据 维基百科 的介绍,SocketCAN 是一个开源的 CAN 驱动以及网络堆栈。在 linux 中,传统的 CAN 驱动是基于字符设备(character device)模型的。一个典型的设备驱动实现,只允许一个进程访问一个设备,其他进程的访问会被阻塞。而且不同设备之间的驱动往往略有不同,这也给移植带来了不便。而 SocketCAN 使用了网络设备模型,允许多个应用同时访问同一个 CAN 设备,而一个应用也可以同时访问多个 CAN 总线。

Linux 内核中在 2.6.25 版本中加入了 CAN 的补丁,同时也添加了一些 CAN 设备的驱动。这里所用到的 PCAN 驱动基本上主流的 linux 发布版也都支持。

2 什么是 PCAN

PCAN 是一个 CAN 转 USB 的设备,由德国 PEAK-System 公司生产。一般一端用来连接 CAN 总线另一端用来连接 USB 主机(工控机、ECU、PC等)。这个东西还是比较贵的,差不多要 2k 多 RMB。有人可能就有疑问了,不就是一个 CAN 转 USB 吗?某宝上随便一搜也就是2百多块。为啥这个这么贵?下面我就简单的总结一下 PCAN 的优势:

[1] CAN FD 协议:全称为 Controller Area Network Flexible Data-Rate. 是对原有 CAN 协议的一种扩展。在 2011 年开发并于 2012 年由博世(Bosch)公司发布。和传统 CAN 协议不同,主要体现在了灵活数据(Flexible Data)。主控单元可以动态的切换不同的数据频率(允许高达传统 CAN 传输速率5倍的速度传输),而且每一帧的数据负载大小由最多8字节提升到64字节。

[2] 这一点很容易被其他的 USB-CAN 设备厂商忽略。我在某宝上买过2百多块的 USB-CAN 设备。当时我问老板支不支持事件触发,老板说:“不支持,而且目前国内所有的厂商都不支持。”(这篇文章写于2020年6月5日)。也就是说,使用这些设备你只能使用查询的方式读取数据,这就基本不可能保证实时性。专门使用一个线程开启事件循环来查询接收缓冲区也会浪费大量的 CPU 资源。因此这些设备配套的软件基本无法打到工业级标准,即使他们的硬件达到了标准。

需要注意的是如果你使用的 PCAN 已经安装了对应的字符设备驱动(chardev),那么是无法使用 SocketCAN 的,如果需要使用 SocketCAN(即网络驱动 aka netdev),需要你根据 PCAN 用户手册重新安装网络驱动。如果你的电脑上没有安装任何关于 PCAN 的驱动,那么默认是可以使用下面的 SocketCAN 的。

3 如何在 Linux 命令行中使用 SocketCAN

终于进入正题了。这部分内容主要来自于 How To Use SocketCAN With The Command-Line In Linux。我的环境如下:

3.1 SocketCAN 提供了哪些 CAN 接口类型?

3.2 列出 SocketCAN 接口

在连接好设备之后,我们首先可能想做的就是查看本地都有哪些 CAN 接口(设备是否被正确识别):

$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:97:9a:46 brd ff:ff:ff:ff:ff:ff
3: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
    link/can

这里的最后一个接口 can0 就是 SocketCAN 接口。此时你可能还希望打印本地支持 SocketCAN 的 CAN 设备信息:

$ ip addr ls dev can0
3: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN group default qlen 10
    link/can
$ ip addr ls dev can1  # 尝试不存在的设备
Device "can1" does not exist.

另一种显示 CAN 接口信息的方法是使用 ifconfig <canx>:

$ ifconfig can0
can0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          NOARP  MTU:16  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:10
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

3.3 配置并且使能 SocketCAN 接口

对于实际存在的 CAN 设备(连上设备时自动创建的 can0),可以使用如下的方法设定波特率(这里为 1M):

sudo ip link set can0 type can bitrate 1000000

如果你使用的是虚拟 CAN 接口,会略有不同:

$ sudo modprobe vcan
$ sudo ip link add dev vcan0 type vcan

使能 SocketCAN 接口使用如下的命令:

$ sudo ip link set up can0

如果出现 RTNETLINK answers: Operation not supported 错误,去先尝试执行 sudo modprobe can 或者 sudo modprobe vcan

3.4 使用 SocketCAN 发送或者接受数据

首先需要安装 can-utils:

$ sudo apt install can-utils

如果你的设备连接到了其他的 CAN 设备,你可以使用如下的命令来发送数据到该设备:

$ cansend can0 123#1122334455667788

其中 123 为 id 表示 0x123,数据为 [ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 ]。注意值总是被认为是16进制。

如果希望显示所有接收到的消息,可以使用如下命令:

$ candump can0

相关文章:

How To Use SocketCAN With C++ In Linux

上一篇下一篇

猜你喜欢

热点阅读