CAN網路學習總結
什麼是CAN 控制器區域網(CAN-Controller Area Network)是 BOSCH公司為現代汽車應用領先推出的一種多主機區域性網,由於其卓越效能現已廣泛應用於工業自動化、多種控制裝置、交通工具、醫療儀器以及建築、環境控制等眾多部門。 CAN bus - Wikipedia https://en.wikipedia.org/wiki/CAN_bus
組網方式 匯流排型組網。類似一根葫蘆藤上長了7個小葫蘆一樣。當然通過閘道器、轉換器等方式,可以組成樹形網路。 CAN的直接通訊距離最遠可達10km(速率5kbps以下),速率最高可達1mbps (此時通訊距離最長為40m)。 問題:資料流通有方向嗎? http://embed.21ic.com/hardware/can/201611/42974_2.html
特點 多主節點 網路上任一節點均可在任意時刻主動地向網路上其他節點發送資訊,而不分主從,通訊方式靈活。 可以隨時動態新增新節點到網路中。 同一時刻,只能有一個節點處於傳送狀態。傳送的報文要麼同時被其他節點收到,要麼同時不能收到。
節點無地址 不像乙太網,CAN網路中每個節點並沒有地址,傳送資訊的節點 無法控制資訊傳送給誰。資訊是以廣播的形式傳送,所有節點都同時收到資訊。但收不收是接收者的事情。
節點有ID識別符號 節點雖然沒有地址,但是有ID識別符號。在傳送資訊的時候,節點ID識別符號成為資訊內容的一部分被髮送出去。
網路報文格式 CAN網路中傳輸的報文只有幾種型別:資料幀,遠端請求幀,錯誤幀,過載幀。具體詳細見下文通訊協議。
網路中流通的報文由接收者定義是否要接收 報文內容中包括了傳送節點的ID識別符號,而網路中其他每個節點都能收到報文內容。所以接收者可以定義是否要接收報文。 接收者可以規定,只接受某ID識別符號傳送來的報文內容。其他節點不予以接收。 因此,CAN網路很容易制定出實現點對點、一點對多點及一點對全域性廣播等幾種方式傳送接收資料。
接收者通過向CAN晶片設定Filter來定義是否接收報文 當接收節點收到報文的時候,可以根據Filter來決定是否接收這一幀報文。 Filter包括MASK和欲接收節點的ID識別符號。 所謂MASK,是指接收節點在進行接收到的報文HEADER進行對比的時候,只需要關注Header中哪些位。如果MASK中某位設定為1,表示需要關注報文Header中的該位的值,如果MASK某位為0,則表示不用管接收到的報文中ID識別符號對應的位是什麼,都需要接收進主機。 首先將接收到的報文header中的ID識別符號與MASK做與操作之後,得到一個值。這個值是收到的報文MASK值。 然後將設定的欲接收節點的ID識別符號與MASK也做與操作之後,得到一個值。這個是預先設定的願意接收的節點MASK值。 如果上述兩值相同,則說明該報文需要接受,否則不需要接收。 參考: Canbus ID filter and mask - carprog - 部落格園 http://www.cnblogs.com/shangdawei/p/4716860.html 可以同時設定多個接收Filter。
RTR-傳送器通過傳送遠端請求幀來主動獲得資料報文 當報文中Header的ID識別符號欄位中的RTR位置1,表示當前幀是遠端請求幀。請求遠端節點ID為本幀中指定ID的節點發送遠端資料。 接收器接收到的報文中,通過RTR位也可以看出該報文是否是其他節點發送的Remote Request報文。 該場景比較普遍,比如我現在急需要遠端節點ID=123的節點彙報裝置當前的溫度。 我使用別人的資料,有兩種方式:別人定時或者不定時的主動發出來,也不管有人要不要這些資料;別人是個木瓜呆子,需要人推一下動一下,不推不動就悶聲睡覺,自然就沒有資料發出來。 所以當我需要節點的資料時,而那該死的節點遲遲不主動傳送,那麼只好本節點親自請求它傳送了。
EFF-擴充套件幀Flag 關於報文格式,有兩種格式,標準幀和擴充套件幀。區別在於幀頭中識別符號的長度,一個是11位,一個是29位。 11位的ID識別符號,表示的節點個數肯定小於29位ID識別符號,也就是說接入到網路中的節點數目不一樣。
CAN匯流排bitrate vs 任意兩節點間的最大距離
CAN網路的位速率取決於匯流排長度。控制器最快能達到1mbps,但對匯流排長度有限制。對於50m長的匯流排,最大bitrate是1mbps,而1500m的匯流排,bitrate約為0.05mbps。
bitrate Max Length 1mbps 40m 500kbps 130m 250kbps 270m 125kbps 530m 100kbps 620m 50kbps 1.3km 20kbps 3.3km 10kbps 6.7km 5kbps 10km 同一網路中,所有節點的速率必須相同,並且固定不變。
匯流排仲裁技術 當多個節點同時向匯流排傳送資訊時,優先順序低的會主動退出傳送,而優先順序高的節點可不受影響的繼續 傳送資料,從而大大節省了匯流排衝突仲裁時間,尤其在網路負載很重的情況下也不會出現網路癱瘓情況。 ID識別符號值越小,優先順序越高。標準格式報文優先順序高於擴充套件格式報文。資料報文高於遠端請求報文。 基於Linux SocketCAN的RAW socket應用注意 ID如何分配 首先確定是使用標準格式報文還是擴充套件格式報文。標準格式ID佔用11位。擴充套件格式ID佔用29位。 需要根據整個網路情況,統籌合理分配ID。
BitRate如何設定 應根據距離最遠的兩個節點間的距離反推出整個網路統一設定的bit rate。
can_frame 是應用程式與核心驅動互動的結構體。核心驅動與CAN硬體互動之後,BUS上傳輸的通訊協議由下文的通訊協議指定。
/* * 擴充套件格式識別符由 29 位組成。其格式包含兩個部分:11 位基本 ID、18 位擴充套件 ID。 * Controller Area Network Identifier structure * * bit 0-28 : CAN識別符 (11/29 bit) * bit 29 : 錯誤幀標誌 (0 = data frame, 1 = error frame) * bit 30 : 遠端傳送請求標誌 (1 = rtr frame) * bit 31 :幀格式標誌 (0 = standard 11 bit, 1 = extended 29 bit) */ typedef __u32 canid_t;
struct can_frame { canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ __u8 can_dlc; /* 資料長度: 0 .. 8 */ __u8 data[8] __attribute__((aligned(8))); }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 可傳送什麼資料 基於Linux Socket CAN的原始套接字,利用can_frame格式,一次最大發送8個位元組資料。當然,也可以使用ISOTP格式,一次可以傳送64位元組。 資料內容應用可以自行定義。
可收到什麼資料 根據CAN通訊協議,可以收到3種類型資料:資料幀,遠端請求幀,錯誤幀。資料幀,遠端請求幀包括標準格式和擴充套件格式,錯誤幀沒有區分。 所有收到的資料,都是struct can_frame結構體表示。 通過can_frame.can_id ,可以知道是什麼格式資料。
/* special address description flags for the CAN_ID */ #define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */ #define CAN_RTR_FLAG 0x40000000U /* remote transmission request */ #define CAN_ERR_FLAG 0x20000000U /* error message frame */ 1 2 3 4 對於資料幀,則由應用程式自行解析資料內容;對於RTR幀,資料幀沒有內容;對於錯誤幀,格式如下: can_frame.can_id 中0~28位表示錯誤類:
/* error class (mask) in can_id */ #define CAN_ERR_TX_TIMEOUT 0x00000001U /* TX timeout (by netdevice driver) */ #define CAN_ERR_LOSTARB 0x00000002U /* lost arbitration / data[0] */ #define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */ #define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2..3] */ #define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */ #define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */ #define CAN_ERR_BUSOFF 0x00000040U /* bus off */ #define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */ #define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */ 1 2 3 4 5 6 7 8 9 10 具體錯誤資訊由標頭檔案指示:include/uapi/linux/can/error.h,由can_frame.data承載。 http://androidxref.com/kernel_3.18/xref/include/uapi/linux/can/error.h#56
設定filter CAN_RAW_FILTER:設定接受資料幀和遠端請求幀。 CAN_RAW_ERR_FILTER:設定接受錯誤幀。 具體可參考核心文件。 翻譯:http://blog.csdn.net/yuanlulu/article/details/7220060 新設Filter覆蓋舊Filter。 核心沒有檢查可以設定的Filter個數,我曾經在2016年某個 核心patch看到最大512個Filter: LKML: Jiri Slaby: [PATCH 3.12 007/235] can: raw: raw_setsockopt: limit number of can_filter that can be set https://lkml.org/lkml/2017/1/27/412 通訊協議 這裡描述的通訊協議,是底層硬體的通訊協議,按位傳送。應用程式通過struct can_frame結構體與驅動互動。驅動將struct can_frame 轉換成硬體通訊協議。 硬體bus中的報文包括兩種格式幀格式:標準格式,有11位的傳送節點ID識別符號;擴充套件格式,有29位的傳送節點ID識別符號,其他部分相同。
幀型別 資料幀:將傳送器傳送的資料傳輸到接收器。 遠端請求幀:請求遠端具有同樣ID識別符號的節點發送資料幀。 “具有同樣ID識別符號”:這裡進行對比的雙方,一個是遠端節點自己的ID,一個是遠端請求幀中Header.ID。 錯誤幀:任何節點檢測到錯誤,就發生錯誤幀。 因為所有節點同時收到幀,會否同時多個節點檢測到錯誤?從而會發生多個錯誤幀? 過載幀:兩個相鄰的資料幀或者遠端請求幀之間,提供附加延時。 資料幀和遠端請求幀使用標準格式或者擴充套件格式。和前面的幀通過一個幀間間隔分開。 資料幀和遠端幀格式 資料幀包括7個欄位(Field):幀起始(Start Of Frame),仲裁欄位(Arbitration Field),控制欄位(Control Field),資料欄位(Data Field),CRC欄位(CRC Field),應答欄位(ACK Field),幀結尾(End Of Frame)。
型別 SOF 仲裁 控制 資料 CRC ACK EOF 標準 0 11+1 2+4 =dlc .. … … 擴充套件 0 29+1 2+4 =dlc .. … … SOF 只有在匯流排空閒狀態才可以開始一幀的傳送。
仲裁 標準格式仲裁欄位 標準格式版本較早,當時還沒有考慮到擴充套件格式。所以在標準格式中,仲裁欄位由11位ID+1位RTR組成。
仲裁欄位 控制欄位 ID(11)+RTR(1) R1(1)+R0(1)+DLC(4) 標準格式與擴充套件格式的區分方法 當發展到後期,發現11位ID識別符號不夠使用,需要擴充ID位數,幸好在控制欄位中,有2位保留欄位沒有使用,都填充了0。於是擴充套件格式就通過控制欄位中的R1位來表示當前是標準格式還是擴充套件格式。因此R1這一位在擴充套件格式中就成了IDE,就是擴充套件格式識別符號。這一位被置1,表示是擴充套件格式報文。
擴充套件格式仲裁欄位 仲裁欄位 控制欄位 ID(11)+SRR(1)+IDE(1)+ID2(18)+RTR(1) R1(1)+R0(1)+DLC(4) 可以看到,擴充套件格式相容標準格式。當老版本2.0A的CAN晶片解析擴充套件格式報文的時候,發現IDE位的值是1,與原始規定的R1應該是0不同,因此這個版本的CAN晶片無法理解該報文。 而支援2.0B的CAN晶片發現IDE位為1,知道是擴充套件格式。 可以發現擴充套件格式的控制欄位,又有2位保留欄位。是否還可以繼續進行新的升級呢?說不定。
資料幀與遠端傳送請求幀區別 RTR位用來區分資料幀與遠端傳送請求幀的區別。 RTR:Remote Transmission Request 如果RTR位為1,表示是遠端請求幀。否則是資料幀。 遠端請求幀中,資料欄位位數為0.所以控制欄位中的DLC沒有意義。
SRR位 在擴充套件幀中,有SRR位,這是標準幀格式中的RTR位,SRR表示替代遠端請求位(substitute Remote request)。在擴充套件幀中它的值永遠是1. 這種設計,就是CAN BUS硬體仲裁的機制利用。假設有一個基本幀,表示的ID為0xabcde。而一個擴充套件幀中,ID為0xa00abcde。 那麼abcde會出現在報文中的基本ID欄位中。兩個幀格式基本相同。而節點發送報文是按位傳送。如何仲裁擴充套件幀退出?SRR位是1,隱性位,需要讓位於顯性位。 如果標準格式的遠端請求幀與擴充套件格式的資料幀呢?誰優先順序高?
控制 包括2位保留欄位,當前都為0。 以及4位資料欄位長度編碼DLC。可以表示64位資訊。剛好資料最大有8個位元組,足夠表示。
以下幾個欄位都是硬體工程師需要了解的。軟體就不管了。
資料 CRC ACK EOF 錯誤幀 附錄 顯性=0/隱性=1 CAN2.0B規範定義了兩種互補的邏輯數值:“顯性”和“隱性”,同時傳送“顯性”和“隱性”位時,匯流排結果值為“顯性”。“顯性”(“Daminant”)數值表示邏輯“0”,而“隱性”(“Recessive”)表示邏輯“1”。
RS-232和CAN在電平和幀格式上都是很大的不同。具體表現如下: RS-232標準電平採用負邏輯,規定+3V~+15V之間的任意電平為邏輯“0”電平,-3V~-15V之間的任意電平為邏輯“1”電平。 而CAN訊號則使用差分電壓傳送,兩條訊號線稱為“CAN_H”和“CAM_L”,靜態時均為2.5V左右,此時的狀態表示為邏輯“1”,也可以叫做“隱性”;用CAN_H比CAN_L高表示邏輯“0”,稱為“顯性”。顯性時,通常電壓值為:CAN_H=3.5V,CAN_L=1.5V;
一個可供參考的can bus java庫 Overview (VI Module API) http://dz.prosyst.com/pdoc/mBS_TM_SDK_7.3.0/modules/vi/api/index.html?com/prosyst/mbs/services/vi/j2socketcan/CanSocket.html --------------------- 作者:w8u 來源:CSDN 原文:https://blog.csdn.net/w8u/article/details/61914994 版權宣告:本文為博主原創文章,轉載請附上博文連結!