1. 程式人生 > >CAN網路學習總結

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  版權宣告:本文為博主原創文章,轉載請附上博文連結!