1. 程式人生 > >CAN匯流排與CANOPEN協議入門

CAN匯流排與CANOPEN協議入門

#1. 什麼是CAN匯流排協議
CAN匯流排協議最早是為了統一汽車車載裝置間通訊的標準而開發的協議,後來由於其高速、穩定、可靠的特點,已經被ISO標準化並廣泛應用於工控、醫療等領域,目前依然是歐洲汽車網路的標準協議。

CAN匯流排協議規定了ISO七層通訊協議模型的物理層和資料鏈路層。其具體實現都已經被固化到CAN匯流排控制晶片中,無需軟體實現。

#2. CAN匯流排的傳輸速率和傳輸距離
理論上,CAN匯流排在速率小於5K時,距離可達10000m;速率接近1M時,距離小於0.4m。現實中常用的高速CAN匯流排速率有500k或250k,低速CAN匯流排有125k和62.5k,傳輸距離在幾米到幾十米間。速率和傳輸距離的選擇還有考慮硬體的要求。

理論上,一條CAN總線上可以連線無數個CAN裝置,但實際上受到其他條件限制,數量總是有限的。例如,使用了更上層的CANOPEN協議,則一條總線上只能有128個裝置。

#3. CAN匯流排協議的特點和要求

  1. CAN匯流排網路屬於廣播網路,同一條匯流排的裝置都可以放送和接受資料。同一時刻只能有一個裝置作為傳送裝置,其他裝置為接收裝置。
  2. 同一條總線上的裝置必須工作在同一速率下。
  3. 當兩個裝置同時傳送資料時,根據其CAN通訊幀(CAN通訊的最小資訊單元詳情見下文)的ID號進行仲裁,ID號小的優先順序高,將獲得傳送權,優先順序低的則需要放棄傳送,轉為接收狀態。
  4. CAN裝置可以檢測總線上的錯誤型別是暫時性的還是持續性的,如果是持續性的,出錯的裝置會不停的向匯流排傳送錯誤幀,一段時間後將自動脫離匯流排。
  5. can匯流排的終端電阻的選擇很重要,選擇的不好會影響通訊質量。

#4. CAN匯流排的通訊幀
CAN匯流排所使用的最基本通訊單元稱為幀,CAN匯流排協議規定了資料幀、遙控幀(也有稱為遠端幀的)、錯誤幀、過載幀和間隔幀。以下僅詳細分析資料幀的幀格式,其他均只描述功能,不詳細描述格式。

有些文件喜歡用顯性電平和隱性電平來描述幀格式,這裡說明一下,顯性電平可以理解為邏輯1,隱性電平可以理解為邏輯0。

##4.1 資料幀
資料幀由7段構成

| |起始段|仲裁段|控制段|資料段|CRC段|ACK段|幀結束|
|-|
|bit|1|12|6|0-64|16|2|7|

起始段:長度固定為1bit,邏輯0

仲裁段:前11bit為幀ID,後1bit為RTR標誌

控制段:前2bit規定為0,後4bit為資料段的BYTE長度

資料段:長度可變,0~8BYTE

CRC段、ACK段、幀結束對於軟體工程師來說可以不關注,比較重要的是理解仲裁段、控制段和資料段的含義。

沒有資料段的資料幀一般用作心跳。

##4.2 遙控幀
遙控幀的作用是向其他單元請求資料。比如裝置A希望裝置B向自己傳送資料,裝置A就向匯流排傳送一個帶有裝置B的幀ID的遙控幀,裝置B就會將資料傳送的總線上。這裡再次說明,CAN匯流排協議是廣播的。

遙控幀的幀格式不具體列出,需要說明的是遙控幀也包含幀ID,當遙控幀與資料幀同時要傳送時,也要根據ID的優先順序仲裁,如果ID相同則資料幀具有更高優先順序。

##4.3 錯誤幀
顧名思義,在檢測到錯誤時傳送到總線上的幀。

錯誤幀分為主動錯誤幀和被動錯誤幀兩類。解釋其不同要了解CAN匯流排的錯誤處理機制,但是其錯誤處理機制過於複雜,這裡描寫一個簡化版。

每一個CAN匯流排晶片都會有錯誤計數器,初值為0。假設裝置A總是傳送錯誤。A傳送一個數據幀後,發現有錯誤(這個發現錯誤的功能也是硬體實現的,應該是A傳送資料的同時,也在校驗總線上的資料),則A會將自己的錯誤計數器加8,併發送一個主動錯誤幀,其他裝置如果接收到這個主動錯誤幀,會將自己的計數器加1;當A的計數器達到127時,A將改為傳送被動錯誤幀,並依然給計數器加8,但不再發送資料幀;最後當A的計數器達到256時,A將不再工作。

以上的描述其實沒有解釋主動錯誤幀和被動錯誤幀在功能上有什麼區別,只是描述了以下發送時機。其實CAN規範協議對此的規定十分複雜,詳情還是找規範慢慢摸索吧,感覺用的不多。
如果發現總線上有錯誤幀,我的經驗是第一檢視所有裝置的波特率是否一致,第二檢測終端電阻是否合適。

##4.4 過載幀和間隔幀
待研究

#5 什麼是CANOPEN協議
CANOPEN協議是基於CAN匯流排協議建立的應用層協議。CANOPEN協議屬於“主-從站協議”,一個CANOPEN網路中有一個主站和若干個從站。每一個從站點都有一個ID號,一個數據字典和四種工作狀態。CANOPEN協議將CAN匯流排協議的通訊幀進行了進一步的封裝和分類,以滿足更高層次通訊的需要。

#6 CANOPEN資料字典
CANOPEN網路中的每一個從站裝置都要有一個數據字典,其實資料字典這個翻譯不太準確,應該叫做“命令ID與功能對照表”。比如網路中有一個訊號燈裝置,則這個裝置就可能有這樣一個數據字典。

|index|subIndex|data|功能|
|-|
|0x400|0|0|開燈|
| |0|1|關燈|

其中index我們可以理解為“命令ID”,subIndex可以理解為“子ID”。

這個“字典”表示,只要有其他裝置向訊號燈傳送一條包含命令ID為0x400和子ID為0的命令,如果data為0,則訊號燈就亮;如果data為1,則訊號燈就滅。所以說“資料字典”更像是“命令ID與功能對照表”。

實際上,CANOPEN協議規定了裝置資料字典的格式,並對命令ID號進行了規定和劃分(具體的規定很複雜,需要請參閱規範)。有一些命令ID的功能是固定的,有一些則可以由裝置生產廠家自己決定。命令ID對應的功能也不總是操作這個裝置,也可以是讀取這個裝置的資訊,比如裝置名等。

接下來的問題是如何向一個裝置傳送命令ID呢?對此,CANOPEN協議也有規定,在下文中會進行介紹。

#7 裝置ID與常用通訊物件
CANOPEN協議是一個“主-從站協議”,其中規定,在總線上每一個作為“從站”的裝置要有一個自己的裝置ID(主站裝置不做強制要求),稱為Node-ID,這個英文名字在許多文章中更常見,範圍是1~127(0有特殊用途,不能作為ID分配給裝置),同一個總線上不能出現ID號相同的兩個從站裝置。所以,基於CANOPEN協議的總線上最多有127個從站裝置。

那麼為什麼是127個呢,為了解釋這個問題,要先了解CANOPEN協議規定的通訊物件。

就像CAN匯流排協議的基本通訊單元稱為“幀”一樣,CANOPEN協議的基本通訊單元叫做“通訊物件”(英文為Object,姑且這麼翻譯吧)。常用的通訊物件有NMT、SYNC、EMERGENCY、TIME STAMP、SDO、PDO這幾個,他們結構相同,包括funciton Code、Node-ID、DLC(資料長度)、DATA(資料)四部分構成,本質上都是通過封裝CAN匯流排協議的資料幀實現的。他們的不同體現在DATA這個部分,有的物件DATA部分可以完全用來傳輸資料,有的物件針對DATA部分進一步做了劃分和要求。

上文說過,CAN匯流排協議的資料幀包含一個仲裁段,其前11位是幀ID。CANOPEN協議進一步把幀ID分為FunctionCode和Node-ID兩部分,如下:

|function Code|Node-ID|
|-|
|4|7|

由於Node-ID只有7位,最大值為127,所以CANOPEN協議的總線上最多有127個從站裝置。functionCode和Node-ID在一起又被稱為COB-ID。

DLC則對應資料幀控制段的後4位,表示後續負載資料的長度。

DATA與資料幀的資料段長度相同,至於有何用途,不同物件有不同要求。

|functionCode|Node-ID|DLC|DATA|
|-|
|4bit|7bit|4bit|8*8bit|

可見,CANOPEN協議的通訊物件就是資料幀,只是進一步規定了資料幀的內容格式,所以說CANOPEN協議是基於CAN匯流排協議的應用層協議。

#8 PDO物件
上文中提到常用的通訊物件有NMT、SYNC、EMERGENCY、TIME STAMP、SDO、PDO,每一種通訊物件都有自己的用途。本章重點介紹PDO物件,瞭解了這個物件的機理,其他物件也可以融會貫通。

##8.1 PDO物件概述
PDO物件稱為“過程資料物件”,用於無連線的資料傳輸,即A站傳送資料給B站後,不需要等待B站給出確認收到的應答。當然B站也可以應答一些資訊給A站,這個有點像網路通訊中的UDP協議,即應答不是強制要求的,B站可以回答,也可以不回答。

PDO物件的DATA部分可以完全用來傳輸資料,沒有進步做要求。

根據上文知道,CAN匯流排本質上是廣播的,對於B站來說,它面臨三個問題(假設B站是主站):

  1. 總線上的通訊物件是不是PDO物件,因為不同物件的資料部分的含義是不同的,需要不同的方式去解析;
  2. 如何知道PDO物件是A站發出的;
  3. 如何回答,即傳送PDO給A站。

對於問題1,B站是通過讀取functionCode來判斷當前總線上是不是PDO物件的。上文提到functionCode有4bit位,即有16個不同的functionCode。CANOPEN協議並沒有硬性規定PDO物件必須使用那一個(或幾個)functionCode,A站和B站可以自行約定。但是CANOPEN協議給了一個劃分的《建議》(用書名號只是為了強調,不是真有一本叫做建議的書),既然是建議,你可以遵守也可以不遵守,但事實上,只要不是特殊情況,所用人都遵守了這個《建議》,如下:

|物件|functionCode|Node-ID|COB-ID|
|-|
|NMT(Model Control)|0x0|0x0|0x0|
|SYNC|0x1|0x0|0x80|
|TIME STAMP|0x2|0x0|0x100|
|EMERGENCY|0x1|0x1-0x7F|0x81-0xFF|
|PDO|0x3-0xA|0x1-0x7F|0x181-0x57F|
|SDO|0xB-0xC|0x1-0x7F|0x581-0x67F|
|NMT(ERROR)|0xD|0x1-0x7F|0x701-0x77F|

對於問題2和問題3,我們先假設A站的Node-ID為1,並且需要進一步引入TPDO和RPDO的概念才能解決。

從上表中我們注意到PDO的functionCode是一個範圍,共8個,即functionCode在此範圍內的所有通訊物件都是PDO物件。剛才提到的《建議》進一步對PDO進行了細分。以A站的PDO為例,如下表:

|物件|functionCode|Node-ID|COB-ID|
|-|
|TPDO1|0x3|0x1|0x181|
|RPDO1|0x4|0x1|0x201|
|TPDO2|0x5|0x1|0x281|
|RPDO2|0x6|0x1|0x301|
|TPDO3|0x7|0x1|0x381|
|RPDO3|0x8|0x1|0x401|
|TPDO4|0x9|0x1|0x481|
|RPDO4|0xA|0x1|0x501|

通過上表,我們可以看出,從站A可以擁有8個PDO物件,其中4個為TPDO,4個為RPDO。下面來回答問題2,B站“如何知道PDO是A站發來的?”。答案就是檢測PDO物件是否屬於A站的TPDO,即COB-ID等於0x181,0x281,0x381或0x481。

對於問題3,答案是B站(主站)傳送屬於A站的RPDO。A站檢查到總線上有自己的RPDO就知道資料是傳送給自己的。

##8.2 PDO物件的引申問題
上一節講了“主-從”站間PDO物件的通訊原理。不過有一個大前提就是我們遵循了《建議》,這就引申出如下兩個問題:

  1. 《建議》給每個從站分配了4個RPDO物件,即每次主站最多隻能傳送4*8BYTE(64位元組)的資料給從站,不夠怎麼辦?
  2. 從站與從站之間如何通訊?

對於問題1,答案是不去遵守《建議》,自己根據需要規定,比如將0x281也規定為RPDO也可以,只要主站和從站都遵守這個規定就行。但這種情況是不多見的,因為《建議》本身是許多廠商共同商討的結果,顯然滿足絕大部分應用情況。

對於問題2,其實超出了CANOPEN協議的應用範圍,因為CANOPEN協議是“主-從站”協議,這類協議的特點就是從站之間沒有通訊的渠道。如果需要通訊,也是通過主站中轉。比如從站A發給主站,主站再發給從站B,來實現從站A與從站B的通訊。從我的工業經驗來看,這種從站之間通訊的情況就沒發生過。

#9 SDO物件
有了PDO物件的基礎,SDO物件的說明就容易多了。

  1. SDO物件也分為TSDO和RSDO兩種。(遵循《建議》)
  2. SDO物件是用來操作從站裝置的資料字典的。
  3. SDO物件是一個有應答的通訊物件,即主站傳送RSDO給從站後,從站如果接收到,必須傳送TSDO給主站進行應答。
  4. SDO物件對DATA段進行了進一步的規定和劃分。

以下為SDO物件的結構

|functionCode|Node-ID|DLC|ControlCode|Index|SubIndex|data|
|-|
|4bit|7bit|4bit|8bit|16bit|8bit|32bit|

其中ControlCode、Index、SubIndex和data就是DATA部分,SDO物件對此進行了細分規定。Index,SubIndex和data的含義,可以參考前文資料字典部分的訊號燈的例子。

ControlCode在RSDO中經常表示此次操作是寫入資料字典還是讀取資料字典,在TSDO中表示寫入是否成功,或者錯誤碼一類的。雖然只有8bit,但是其構成還是挺複雜的,這裡就不詳細描述了,可以在網上找更加詳細的文件來看。