1 什么是 SocketCAN
根據 維基百科 的介紹,SocketCAN 是一個開源的 CAN 驅動以及網絡堆棧。在 linux 中,傳統(tǒng)的 CAN 驅動是基于字符設備(character device)模型的。一個典型的設備驅動實現(xiàn),只允許一個進程訪問一個設備,其他進程的訪問會被阻塞。而且不同設備之間的驅動往往略有不同,這也給移植帶來了不便。而 SocketCAN 使用了網絡設備模型,允許多個應用同時訪問同一個 CAN 設備,而一個應用也可以同時訪問多個 CAN 總線。
Linux 內核中在 2.6.25 版本中加入了 CAN 的補丁,同時也添加了一些 CAN 設備的驅動。這里所用到的 PCAN 驅動基本上主流的 linux 發(fā)布版也都支持。
2 什么是 PCAN
PCAN 是一個 CAN 轉 USB 的設備,由德國 PEAK-System 公司生產。一般一端用來連接 CAN 總線另一端用來連接 USB 主機(工控機、ECU、PC等)。這個東西還是比較貴的,差不多要 2k 多 RMB。有人可能就有疑問了,不就是一個 CAN 轉 USB 嗎?某寶上隨便一搜也就是2百多塊。為啥這個這么貴?下面我就簡單的總結一下 PCAN 的優(yōu)勢:
- PCAN 廣泛運用到汽車領域,應該是車規(guī)級的產品(我沒有查到相關的資料,只是憑感覺推斷)。
- PCAN 支持 windows、linux 系統(tǒng)、以及 linux 實時擴展 Xenomai,RTAI (對應為“實時驅動模式”)。
- PCAN 支持 C++、Java、Python 3.x 等編程語言甚至可以直接將數(shù)據輸入到 matlab/simulink 車輛網絡工具箱。
- Qt 也自帶對該設備的支持(通過 Qt CAN Bus)。
- 支持 CAN 2.0 a/b 協(xié)議以及 CAN FD 協(xié)議[1]。
- 讀取數(shù)據支持事件觸發(fā)[2]。
- 各種各樣的軟件以及成熟的生態(tài)。尤其是在汽車通信領域。
- 等等。
[1] CAN FD 協(xié)議:全稱為 Controller Area Network Flexible Data-Rate. 是對原有 CAN 協(xié)議的一種擴展。在 2011 年開發(fā)并于 2012 年由博世(Bosch)公司發(fā)布。和傳統(tǒng) CAN 協(xié)議不同,主要體現(xiàn)在了靈活數(shù)據(Flexible Data)。主控單元可以動態(tài)的切換不同的數(shù)據頻率(允許高達傳統(tǒng) CAN 傳輸速率5倍的速度傳輸),而且每一幀的數(shù)據負載大小由最多8字節(jié)提升到64字節(jié)。
[2] 這一點很容易被其他的 USB-CAN 設備廠商忽略。我在某寶上買過2百多塊的 USB-CAN 設備。當時我問老板支不支持事件觸發(fā),老板說:“不支持,而且目前國內所有的廠商都不支持?!保ㄟ@篇文章寫于2020年6月5日)。也就是說,使用這些設備你只能使用查詢的方式讀取數(shù)據,這就基本不可能保證實時性。專門使用一個線程開啟事件循環(huán)來查詢接收緩沖區(qū)也會浪費大量的 CPU 資源。因此這些設備配套的軟件基本無法打到工業(yè)級標準,即使他們的硬件達到了標準。
需要注意的是如果你使用的 PCAN 已經安裝了對應的字符設備驅動(chardev),那么是無法使用 SocketCAN 的,如果需要使用 SocketCAN(即網絡驅動 aka netdev),需要你根據 PCAN 用戶手冊重新安裝網絡驅動。如果你的電腦上沒有安裝任何關于 PCAN 的驅動,那么默認是可以使用下面的 SocketCAN 的。
3 如何在 Linux 命令行中使用 SocketCAN
終于進入正題了。這部分內容主要來自于 How To Use SocketCAN With The Command-Line In Linux。我的環(huán)境如下:
- USB-CAN 設備為 PCAN。
- 系統(tǒng)為狀態(tài) VMware 中的 Ubuntu 16.04。
3.1 SocketCAN 提供了哪些 CAN 接口類型?
-
Native interfaces: 本地接口對應了真實的硬件(如 USB-CAN 適配器),這些接口命名為
canX,如can0,can1,... -
Virtual interfaces: 虛擬接口并沒有對應實際的硬件,它們被命名為
vcanX,如vcan0,vcan1,... -
SLCAN based interfaces: 基于 SLCAN 的接口提供了串行接口,它們被命名為
slcanX,如slcan0,slcan1,等等。
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 設備(連上設備時自動創(chuàng)建的 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
如果出現(xiàn)
RTNETLINK answers: Operation not supported錯誤,去先嘗試執(zhí)行sudo modprobe can或者sudo modprobe vcan。
3.4 使用 SocketCAN 發(fā)送或者接受數(shù)據
首先需要安裝 can-utils:
$ sudo apt install can-utils
如果你的設備連接到了其他的 CAN 設備,你可以使用如下的命令來發(fā)送數(shù)據到該設備:
$ cansend can0 123#1122334455667788
其中 123 為 id 表示 0x123,數(shù)據為 [ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 ]。注意值總是被認為是16進制。
如果希望顯示所有接收到的消息,可以使用如下命令:
$ candump can0
相關文章: