Linux上使用CAN通信的方法

一、CAN協(xié)議簡介

1.1 CAN發(fā)展歷程

CAN發(fā)展的重要歷史事件

1.2 標(biāo)準(zhǔn)CAN與拓展CAN區(qū)別

CAN 1.0 定義的 CAN 具有 11 位消息標(biāo)識,提供可能的 2048 個消息標(biāo)識符。2.0 版允許有效的 29 位消息 ID。為了使新的 CAN 設(shè)備與舊的實現(xiàn)兼容,CAN 2.0 規(guī)范分為兩部分,2.0A 和 2.0B。在 CAN 2.0A 中,消息格式與僅使用 11 位消息 ID 的舊版本 CAN 一致。 CAN 2.0B 中,允允許有效的 29 位消息 ID,然后可以在被動或主動模式下實現(xiàn) CAN 2.0B。CAN 版本 1.0 和 2.0A 被稱為“標(biāo)準(zhǔn) CAN”,因為它們都使用 11 位消息 ID。CAN 2.0 B 被稱為“擴(kuò)展 CAN”,因為它使用擴(kuò)展的 29 位消息 ID

1.3 參考

https://www.can-cia.org/can-knowledge/can/can-history/
https://en.wikipedia.org/wiki/CAN_bus#History
https://www.edaboard.com/threads/difference-between-can1-0-and-can-2-0.217912/

二、基于CAN的典型應(yīng)用協(xié)議

SAE J1939/ISO11783
CANOpen
CANaerospace
DeviceNet
NMEA 2000

三、Linux上使用CAN的幾種方式

3.1 Linux中CAN設(shè)備掛載的總線類型

Linux可以通過串口、USB、網(wǎng)口、PCIE等接口與CAN設(shè)備間接進(jìn)行通信。

CAN設(shè)備連接在不同的硬件接口時,意味著CAN設(shè)備被掛載在Linux中不同的總線上,如USB總線、PCI-E總線(直接通過PCI-E與linux通訊),因此Linux采用不同的通訊協(xié)議與CAN設(shè)備進(jìn)行通訊。

3.2 CAN轉(zhuǎn)串口

  • 設(shè)備形態(tài):
    CAN轉(zhuǎn)串口
  • 數(shù)據(jù)傳輸流程:

Linux->串口->單片機(jī)->CAN

  • 通訊協(xié)議:

利用linux自帶的串口庫,或ros的serial庫對串口進(jìn)行讀寫。

通過定義串口協(xié)議,如10個字節(jié),前兩個字節(jié)為CAN ID,后面8個字節(jié)為CAN Data。通過此對串口發(fā)送數(shù)據(jù),讓單片機(jī)對其進(jìn)行轉(zhuǎn)換為CAN數(shù)據(jù)。

協(xié)議參考:https://manual.zlg.cn/web/#/64/2607

3.3 CAN轉(zhuǎn)USB

  • 設(shè)備形態(tài):
    CAN轉(zhuǎn)USB

注意,不是所有的周立功CAN轉(zhuǎn)USB設(shè)備都支持Linux,見表:https://manual.zlg.cn/web/#/146

  • 數(shù)據(jù)傳輸流程:

Linux->USB->單片機(jī)->CAN

  • 通訊協(xié)議:

與CAN轉(zhuǎn)串口不一樣,利用的庫是libusb和libusbcan,對CAN轉(zhuǎn)USB數(shù)據(jù)直接進(jìn)行讀寫

libusb是linux驅(qū)動,可以操作USB接口對USB設(shè)備進(jìn)行讀寫操作。

libusbcan是CAN轉(zhuǎn)USB設(shè)備廠商給的驅(qū)動,其中定義了can數(shù)據(jù)幀的數(shù)據(jù)結(jié)構(gòu)體,填充相應(yīng)的CAN ID和CAN Data,最后通過USB進(jìn)行讀寫。

協(xié)議參考:https://manual.zlg.cn/web/#/55/2282

3.4 CAN轉(zhuǎn)網(wǎng)

  • 設(shè)備形態(tài):

    CAN轉(zhuǎn)網(wǎng)

  • 數(shù)據(jù)傳輸流程:

Linux->TCP(UDP)/IP->單片機(jī)->CAN

  • 通訊協(xié)議:

利用Linux的socket庫對網(wǎng)絡(luò)設(shè)備進(jìn)行讀寫操作。

Linux通過IP地址利用Socket與CAN設(shè)備通信,一個TCP/UDP幀包中包含若干個連續(xù)的CAN幀,每個CAN幀包含若干個字節(jié),包含CAN ID和CAN Data。

協(xié)議參考:https://manual.zlg.cn/web/#/67/2693

3.5 CAN轉(zhuǎn)PCI-E

  • 設(shè)備形態(tài):
    PCI-E轉(zhuǎn)CAN

注意周立公CAN轉(zhuǎn)PCI-E設(shè)備,型號PCI-5010-P不支持Linux:https://manual.zlg.cn/web/#/146

  • 數(shù)據(jù)傳輸流程:

Linux->SocketCAN->單片機(jī)->CAN

  • 通訊協(xié)議:

Linux提供了SocketCAN接口,使得CAN總線通信近似于和以太網(wǎng)的通信。網(wǎng)絡(luò)設(shè)備通過IP確定地址,CAN設(shè)備通過CAN ID確定地址,如can0,can1...

CAN ID可以通過ifconfig -a查看

Linux利用SocketCAN庫根據(jù)CAN的設(shè)備ID對其進(jìn)行讀寫操作,CAN的數(shù)據(jù)結(jié)構(gòu)在Socket CAN中被結(jié)構(gòu)體定義,填充相應(yīng)數(shù)據(jù)后發(fā)送即可。

協(xié)議參考:https://manual.zlg.cn/web/#/77/3180

3.6 USB轉(zhuǎn)CAN(CANable)

  • 設(shè)備形態(tài):
    USB轉(zhuǎn)CAN(SocketCAN)

開源地址:https://canable.io/

淘寶有售賣

  • 數(shù)據(jù)傳輸流程:

注意與上面周立功的CAN轉(zhuǎn)USB設(shè)備數(shù)據(jù)傳輸流程不同,利用的是SocketCAN,不是USB。

Linux->SocketCAN->單片機(jī)->CAN

  • 通訊協(xié)議:

Linux利用SocketCAN庫根據(jù)CAN的設(shè)備ID對其進(jìn)行讀寫操作,CAN的數(shù)據(jù)結(jié)構(gòu)在Socket CAN中被結(jié)構(gòu)體定義,填充相應(yīng)數(shù)據(jù)后發(fā)送即可。

SocketCAN簡介:https://en.wikipedia.org/wiki/SocketCAN
協(xié)議參考1:https://canable.io/getting-started.html#socketcan-linux
協(xié)議參考2:https://manual.zlg.cn/web/#/77/3180

四、ROS中的CAN通信

4.1 ROS提供三個層次的驅(qū)動庫

三個層次的驅(qū)動庫

socketcan_interface是較為底層的包,與Linux的socketcan打交道。

socketcan_bridgeros中最常用的包,通過將接收到的topic轉(zhuǎn)換為can數(shù)據(jù)發(fā)出去,或者把接收到的can數(shù)據(jù)轉(zhuǎn)換為ros的topic。

ros_canopen是基于canopen應(yīng)用協(xié)議的包,是上層協(xié)議。

4.2 socketcan_bridge包

該功能以三個節(jié)點的形式提供:socketcan_bridge_nodesocketcan_to_topic_nodetopic_to_socketcan_node。要從同一個 CAN 設(shè)備接收和發(fā)送幀,需要使用socketcan_bridge_node來防止每個發(fā)送的消息都回顯到接收主題。

4.2.1 socketcan_bridge_node

從 SocketCAN 設(shè)備接收幀并將這些幀發(fā)布到主題上,同時它偵聽 CAN 消息并將這些消息發(fā)送到 SocketCAN。發(fā)送到 CAN 設(shè)備的幀不會作為接收消息發(fā)布。

  • 訂閱的話題名稱:sent_messages(can_msgs/Frame),此處收到的消息將被發(fā)送到 SocketCAN 設(shè)備。

  • 發(fā)布的話題名稱:received_messages (can_msgs/Frame),在 SocketCAN 設(shè)備上接收到的幀在本主題中發(fā)布。

  • ROS節(jié)點參數(shù):~can_device (string, default: can0),SocketCAN 設(shè)備的名稱,默認(rèn)情況下這些設(shè)備被命名為can0及以上。

4.2.2 socketcan_to_topic_node

將在 SocketCAN 設(shè)備上接收到的幀發(fā)布到topic。

  • 發(fā)布的話題名稱:received_messages (can_msgs/Frame),在 SocketCAN 設(shè)備上接收到的幀在本主題中發(fā)布。

  • ROS節(jié)點參數(shù):~can_device (string, default: can0),SocketCAN 設(shè)備的名稱,默認(rèn)情況下這些設(shè)備被命名為can0及以上。

4.2.3 topic_to_socketcan_node

將收到的topic的 CAN 消息發(fā)送到 SocketCAN 設(shè)備。

  • 訂閱的話題名稱:sent_messages(can_msgs/Frame),此處收到的消息將被發(fā)送到 SocketCAN 設(shè)備。

  • ROS節(jié)點參數(shù):~can_device (string, default: can0),SocketCAN 設(shè)備的名稱,默認(rèn)情況下這些設(shè)備被命名為can0及以上。

4.3 基于ROS中轉(zhuǎn)節(jié)點松耦合的CAN通信

4.3.1 松耦合需求的原因

對于一些成熟的包,或者比較復(fù)雜的包,要想把其中的topic轉(zhuǎn)為CAN數(shù)據(jù)發(fā)出去,有兩種修改方式:

    1. 直接修改源碼中相應(yīng)topic的數(shù)據(jù)類型,或者在源碼中新發(fā)布一個can_msgs/Frame數(shù)據(jù)類型,名稱為sent_messages的topic
    1. 新建一個中轉(zhuǎn)節(jié)點,接收該復(fù)雜節(jié)點的topic(消息類型為該復(fù)雜節(jié)點的消息類型),將其轉(zhuǎn)換為一個can_msgs/Frame數(shù)據(jù)類型,名稱為sent_messages的topic,將反饋的can信息,通過指定的topic,反饋給該復(fù)雜節(jié)點。

第二種方式更為簡單和快速,但會增加通信中轉(zhuǎn)延時,ROS的節(jié)點通信是基于TCP/IP,對于本機(jī)節(jié)點通信而言,此延時大概在1ms以內(nèi)(百兆網(wǎng)卡以上)。

4.3.2 中轉(zhuǎn)節(jié)點

對于該中轉(zhuǎn)節(jié)點,需要訂閱兩個topic,發(fā)布兩個topic

  • 訂閱:
  1. 復(fù)雜節(jié)點發(fā)布的topic
  2. socketcan_bridge_node節(jié)點的topic:received_messages
  • 發(fā)布:
  1. 復(fù)雜節(jié)點訂閱的topic
  2. socketcan_bridge_node節(jié)點的topic:sent_messages

4.3.3 CAN數(shù)據(jù)幀

socketcan_bridge_node的話題的消息類型都為ROS內(nèi)置消息類型can_msgs/Frame

Header header
uint32 id
bool is_rtr
bool is_extended
bool is_error
uint8 dlc
uint8[8] data

需要填充的數(shù)據(jù)是

  • id:CAN ID
  • dlc:數(shù)據(jù)長度,一般為8
  • is_extended:是否是拓展幀,一般為0
  • uint8[8] data:can數(shù)據(jù)

4.3.4 使用

一般把該中轉(zhuǎn)節(jié)點與socketcan_bridge_node放在一個launch文件中。

如果socketcan_bridge_node節(jié)點的名稱沖突了,可以在launch文件中添加group,或者remap話題名稱。

五、總結(jié)

推薦CANable + socketcan_bridge包實現(xiàn)ROS中的CAN通信!

Github:https://github.com/wanghuohuo0716/ros_can_driver

ROS socketcan_bridge包使用參考:
https://blog.csdn.net/zyf_to_utopia/article/details/116209605
https://blog.csdn.net/m0_58322903/article/details/121630592
https://blog.csdn.net/wangrunhuan/article/details/117962857

SocketCAN介紹:
https://en.wikipedia.org/wiki/SocketCAN

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • DBUS是一種高級的進(jìn)程間通信機(jī)制。DBUS支持進(jìn)程間一對一和多對多的對等通信,在多對多的通訊時,需要后臺進(jìn)程的角...
    愛喝茶de公羊雁蘭閱讀 877評論 0 1
  • 安裝最新版cmake & cmake https://blog.csdn.net/u011291667/artic...
    Jimmy_Tong閱讀 1,512評論 0 0
  • 作者:良知猶存 轉(zhuǎn)載授權(quán)以及圍觀:歡迎添加微信公眾號:羽林君 前言 主題:串口是一種設(shè)備間常用的通訊接口,ross...
    良知猶存閱讀 1,552評論 0 1
  • 需要注意的點: ------ 1、單片機(jī)讀取編碼器脈沖時采用外部中斷方式的缺點,由于脈沖頻率較高,單片機(jī)頻繁進(jìn)入外...
    鄒y閱讀 483評論 0 1
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,422評論 4 61

友情鏈接更多精彩內(nèi)容