CAN總線要點
前言
CAN總線的應用在現在看來越來越廣泛,我廠設備從最初的ARM9與ARM7平台、期間升級過度到CortexA8與Cortex M3平台,再到現在的Cortex M4平台,圍繞CAN進行了一系列產品的開發,CAN總線的穩定性是毋庸置疑的。
CAN總線物理結構與特性
CAN總線網絡
CAN總線網絡主要掛在CAN_H和CAN_L,各個節點通過這兩條線實現信號的串行差分傳輸,為了避免信號的反射和干擾,還需要在CAN_H和CAN_L之間接上120歐姆的終端電阻,但是為什么是120歐姆呢?那是因為電纜的特性阻抗為120歐。
CAN收發器
CAN收發器的作用是負責邏輯電平和信號電平之間的轉換。
即從CAN控制芯片輸出邏輯電平到CAN收發器,然后經過CAN收發器內部轉換將邏輯電平轉換為差分信號輸出到CAN總線上,CAN總線上的節點都可以決定自己是否需要總線上的數據。具體的管教定義如下:
信號表示
CAN總線采用不歸零碼位填充技術,也就是說CAN總線上的信號有兩種不同的信號狀態,分別是顯性的(Dominant)邏輯0和隱形的(recessive)邏輯1,信號每一次傳輸完后不需要返回到邏輯0(顯性)的電平。
位填充規則:發送器只要檢測到位流里有5個連續相同值的位,便自動在位流里插入補充位。
觀察下圖:
可以看到上圖中的當第一段為隱性(recessive),CAN_H和CAN_L電平幾乎一樣,也就是說CAN_H和CAN_L電平很接近甚至相等的時候,總線表現隱性的,而兩線點位差較大時表現為顯性的,按照定義的:
- CAN_H-CAN_L < 0.5V 時候為隱性的,邏輯信號表現為"邏輯1"- 高電平。
- CAN_H-CAN_L > 0.9V 時候為顯性的,邏輯信號表現為"邏輯0"- 低電平。
下面將差分信號和顯隱性之間對應關系總結為下表:
由上面的分析我們可以知道:
CAN總線采用的"線與"的規則進行總線沖裁。即1&0=0;所以0為顯性。
這句話隱含的意思是,如果總線上只要有一個節點將總線拉到低電平(邏輯0)即顯性狀態,總線就為低電平(邏輯0)即顯性狀態而不管總線上有多少節點處於傳輸隱性狀態(高電平或是邏輯1),只有所有節點都為高(隱性),總線才為高,即隱性。
通訊速率與通訊距離
下面的SAE J2411為美國汽車標准。
類型 |
標准 |
最高速率 |
描述 |
高速CAN |
CAN/ISO 11839-2 |
1Mbit/秒 |
最通用的CAN總線類型 |
低速CAN |
ISO/ISO 11839-3 |
125Kbit/秒 |
容錯,在一條總線短路的時候仍然能工作 |
單線CAN |
SAE J2411 |
50Kbit/秒 |
高速模式可達到100Kbit/s主要用在汽車上,例如通用公司 |
CAN總線上任意兩個節點的最大傳輸距離與其位速率有關,如下表:
位速率/kbps |
1000 |
500 |
250 |
125 |
100 |
50 |
20 |
10 |
5 |
最大距離/m |
40 |
130 |
270 |
530 |
620 |
1300 |
3300 |
6700 |
10000 |
這里的最大通信距離指的是同一條總線上兩個節點之間的距離。可以看到速率越低通訊距離就越遠,也就是說CAN總線的通訊距離和波特率成反比。在位速率為5千比特位每秒的時候達到最大的傳輸距離10公里。其中一般的工程中比較常用的為500K每秒的通訊速率。這個速率在實際測試的時候也是非常可靠的。
如果想要更遠的傳輸(大於10公里);可以考慮用多個CAN控制器連接或是加其他通訊協議(如485或是TCP/IP)的接口芯片組成的一個設備,這樣就可實現長距離的通訊需求。
CAN總線關鍵概念
仲裁
只要總線空閑,總線上任何節點都可以發送報文,如果有兩個或兩個以上的節點開始傳送報文,那么就會存在總線訪問沖突的可能。但是CAN使用了標識符的逐位仲裁方法可以解決這個問題。
在仲裁期間,每一個發送器都對發送的電平與被監控的總線電平進行比較。如果電平相同,則這個單元可以繼續發送。如果發送的是一"隱性"電平而監視到的是一"顯性"電平,那么這個節點失去了仲裁,必須退出發送狀態。如果出現不匹配的位不是在仲裁期間則產生錯誤事件。
幀ID越小,優先級越高。由於數據幀的RTR位為顯性電平,遠程幀為隱性電平,所以幀格式和幀ID相同的情況下,數據幀優先於遠程幀;由於標准幀的IDE位為顯性電平,擴展幀的IDE位為隱形電平,對於前11位ID相同的標准幀和擴展幀,標准幀優先級比擴展幀高。
CAN總線協議
CAN 總線是一個廣播類型的總線,所以任何在總線上的節點都可以監聽總線上傳輸的數據。也就是說總線上的傳輸不是點到點的,而是一點對多點的傳輸,這里多點的意思是總線上所有的節點。但是總線上的節點如何知道那些數據是傳送給自己的呢?CAN總線的硬件芯片提供了一種叫做本地過濾的功能,通過這種本地過濾的功能可以過濾掉一些和自己無關的數據,而保留一些和自己有關的信息。
CAN消息機制
CAN標准定義了四種消息類型,每條消息用一種叫做比特位仲裁(Arbitration)機制來控制進入CAN總線,並且每條消息都標記了優先權。另外CAN標准還定義了一系列的錯誤處理機制。
CAN報文的四種消息類型:
- 數據幀:數據幀將數據從發送器傳輸到接收器。
- 遠程幀:總線單元發出遠程幀,請求發送具有同一標識符的數據幀。
- 錯誤幀:任何單元檢測到總線錯誤就發出錯誤幀。
- 過載幀:過載幀用在相鄰數據幀或遠程幀之間的提供附加的延時。
數據幀
下圖為基本的格式:
CAN總線中有標准幀和擴展幀兩種格式,兩種格式不同的地方在於仲裁域格式的不同,看下面兩個表格可以很清楚的看出兩者的不同,下面第一個表是標准幀(CAN2.0 A),第二個為擴展幀(CAN2.0 B):
下面為擴展幀格式(CAN2.0B):
其中
- SOF為幀開始
- SRR為"替代遠程請求位
- IDE為擴展標識符位
- RTR為遠程傳輸請求位
- CRC delimiter 為CRC定界符。
- ACK delimiter 為應答定界符.
我們看到上圖中的基本幀格式可以總結為以下幾個域:
域 |
描述 |
仲裁域 |
仲裁域決定了當總線上兩個或是多個節點爭奪總線時的優先權。 |
數據域 |
包含了0到8字節的數據。 |
CRC域 |
包含了15位的校驗和,校驗和用來做錯誤檢測。 |
應答槽 |
任何一個已經正確接收到消息的控制器在每一條消息的末端發送一個應答位,發送器檢查消息是否存在應答位,如果沒有就重發消息。 |
遠程幀
作為數據接收器的站,通過發送遠程幀,可以啟動其資源節點傳送它們各自的數據。遠程幀和數據幀非常類似,只是遠程幀沒有數據域。
上圖就是遠程幀的幀格式,它相對與數據幀沒有遠程幀,但是要注意發送遠程幀的時候RTR位要置1,表示發送的是遠程幀。下圖更加清晰了呈現了這種結構。
錯誤幀
錯誤幀是當總線的某一個節點檢測到錯誤后發送出來的,它會引起所有節點檢測到一個錯誤,所以當有任何一個節點檢測到錯誤,總線上的其他節點也會發出錯誤幀。CAN總線設計了一套詳盡的錯誤計數機制來確保不會由於任何一個節點反復的發送錯誤幀而導致CAN總線的崩潰。
如上圖所示錯誤標志和錯誤定界符組成,高低代表分別代表隱性和顯性,其中錯誤標志為所有節點發過來的錯誤標志的疊加(Superposition)。下圖更為清楚的看出各個數據位的分布:
下面通過以下數據結構框圖概括各個部分的定義:
錯誤標志有兩種形式:
- 主動錯誤標志,它由6個連續的顯性位0組成,它是節點主動發送的錯誤標志。
-
被動錯誤標志,它由6個連續的隱性位1組成,除非被其他節點的顯性位覆蓋。
剛才說到一個節點上檢測到錯誤會導致總線上所有的節點都會檢測到錯誤並發送錯誤標志,這是為什么呢?
因為單一節點上的錯誤標志格式違背了從幀起始到CRC界定符的位填充規則,也破壞了ACK域或幀結尾的固定格式。下面簡要說下位填充規則。
位填充規則:發送器只要檢測到位流里有5個連續相同值的位,便自動在位流里插入補充位。
注意:位填充規則只是針對數據幀和遠程幀,錯誤幀和過載幀格式固定。
所以所有其他的節點會檢測到錯誤條件並且開始發送錯誤標志,因此錯誤幀就是各個站的不同錯誤標志疊加在一起的結果。
當某個節點發送錯誤幀(帶有錯誤標志),其他節點收到了錯誤幀,檢測到錯誤條件,就通過發送"被動錯誤標志"的錯誤幀來提示錯誤。
錯誤定界符:
傳送了錯誤標志以后,每一個站就發送一個隱性位,並一直監視總線直到檢測出一個隱性位為止,然后就開始發送其余7個隱性位。
過載幀
過載幀是接收節點用來向發送節點告知自身接收能力的幀。
過載幀,意思就是某個接收節點來不及處理數據了,希望其他節點慢點發送數據幀或者遠程幀,所以告訴發送節點,我已經沒有能力處理你發送過來的數據了。
過載幀跟錯誤幀結構類似包括過載標志和過載定界符,有3中情況會引起過載:
- 接收器內部的原因,它需要延遲下一個數據幀或是遠程幀。
- 在間歇字段(看下面的幀間空間)的第一位和第二位檢測到一個顯性位(間歇字段都是隱性位的)
- 如果CAN節點在錯誤界定符或是過載界定符的第八位(最后一位)采樣到一個顯性位邏輯0,節點會發送一個過載幀,錯誤計數器不會增加。
上圖中很清晰的表示了過載標志有6個顯性位組成,而疊加部分和"主動錯誤"標志一樣,過載的標志破壞的是間歇域的固定格式。所以導致其他的節點都檢測到過載條件,並一同發出過載標志。
過載定界符:
也就是上圖的過載結束符,過載標志被傳送以后,節點就一直監聽着總線,直到檢測到有一個從顯性位到隱性位的跳變為止。當從總線上檢測到這樣的跳變,則就標志着每一個節點都完成了各自過載標志的發送,並開始同時發送其余7個隱性位。
幀間空間(Interframe Space)
幀間空間說白了就是幀與幀之間的間隔,但是這種間隔在CAN的幀中只存在於數據幀和遠程幀,其他的幀就不一定是幀間空間隔開的,而是其他形式,或是直接是沒有間隔,例如過載幀和錯誤幀之間就沒幀間空間。過個過載幀之間有間隔但是不是有幀間空間隔開的。
這里所說的針間空間包括"間歇"、"總線空閑"的位域。如果是發送前一報文的"被動錯誤"的站,則還包括叫做"掛起傳輸"的位域。
若不是"被動錯誤"的站,或作為前一報文的接收器的站,幀間空間格式為下圖:
若是"被動錯誤"的站,如果想要發送8個隱性電平,在發送其他幀,幀間空間格式為下圖,即包括了掛起傳輸,
可以看到
- 間歇字段有3個隱性位。
特別的在間歇期間,所有的節點都不允許傳送數據幀和遠程幀,唯一看做的是標示一個過載條件。
- 總線空閑:
只要總線空閑,任何節點就可以往總線發送數據,並且是開始於間歇之后的第一個位。一旦總線上檢測到顯性位即邏輯"0",可以認為是幀的開始。
- 掛起傳輸
"被動錯誤"的節點發送報文之后,在下一個報文開始傳送之前或是確認總線空閑之前發出8個隱性位跟隨在間歇的后面。如果這個時候有一個報文從其他的節點發過來,則這個節點就成為了接收器。
錯誤處理機制
錯誤偵測
下標是幾個錯誤類型:
錯誤類型 |
出錯條件 |
出錯域 |
幀測單元 |
|
比特錯誤 bit error |
發送的位值與所監控的位值不相符合(填充比特和ACK比特除外) |
遠程幀(SOF~EOF) 錯誤幀 過載幀 |
發送單元 接收單元 |
|
填充錯誤stuff error |
偵測到6個連續相同的電平 |
數據幀(SOF~CRC) 遠程幀(SOF~CRC) |
發送單元 接收單元 |
|
CRC 錯誤 |
計算結果和接收到的CRC不同 |
數據幀(CRC) 遠程幀(CRC) |
接收單元 |
|
格式錯誤 Form Error |
某個固定的格式位置出現無效的比特 |
數據幀: (CRC Delimiter, ACK Delimiter EOF) 遠程幀: (CRC Delimiter,ACK Delimiter) 錯誤幀: (Error Frame Delimiter) 過載幀: (Overload Delimiter) |
接收單元 |
|
應答錯誤 Acknowledgment |
發送端在應答間隙所監視的位不為顯性,即邏輯0,發送器就檢測到一個應答錯誤。 |
數據幀(ACK slot) 遠程幀(ACK slot) |
發送單元 |
錯誤計數
下面是錯誤計數表:
錯誤條件 |
Transmit Error Counter |
Receive Error Counter |
|
1 |
RECEIVER端偵測到一個位Error錯誤,除了發送ACTIVE ERROR FLAG 和OVERLOAD FLAG |
- |
+1 |
2 |
TRANSMITIER 發送ERROR FLAG |
+8 |
|
3 |
TRANSMITTER發送ACTIVE ERROR FLAG OVERFLAG時偵測到BIT ERROR |
+8 |
|
4 |
當RECEIVER發送ACTIVE ERROR FLAG或OVERFLAG時偵測到BIT ERROR |
+8 |
|
5 |
一個幀被成功發送之后(取得ACK並且知道END OF FRAME完成都沒有錯誤) |
-1 IF TEC=0,TEC will not be changed |
- |
6 |
一個幀被成功接收(知道ACK域都沒有檢測到錯誤,並成功發送ACK比特) |
- |
1. if 1 <= REC <= 127 -> REC-1 2. if REC = 0 -> REC = 0 3. if REC > 127 -> REC = a value Between 119 to 127 |
7 |
在總線上檢測到128此連續的11個1,"bus off"的節點允許變成不再是"bus off" |
Cleared to TEC = 0 |
Cleared to REC = 0 |
錯誤抑制
為防止某些節點自身出錯而一直發送錯誤幀,干擾其他節點通信,CAN協議規定了節點的3種狀態及行為,如下圖:
一個節點掛到CAN總線上之后,處於ACTIVE狀態;TEC>127或者REC>127導致節點進入passive狀態;TEC>255之后節點處於bus off狀態,就是不允許再往bus上發送東西了;處於bus off狀態的節點,在檢測到128個連續的11個1之后將回到active狀態。