想像車身 ECU 正準備送出一筆燈光狀態,儀表 ECU 也在同一個瞬間要更新顯示。
兩個節點都看到 CAN Bus 處於空閒狀態,也都送出 Start of Frame。
如果這是一條一般通訊線路,兩筆訊息可能直接碰撞,接著只能一起重送。
CAN 的處理方式不同:每個傳送端一邊送出 bit,一邊監看 Bus 上真正出現的狀態。
若兩筆訊息使用不同 ID,優先權較低的節點會在 Identifier 的第一個不同 bit 主動退出,讓獲勝的 Frame 繼續傳完。
這個過程稱為 CAN Arbitration,也就是 CAN 的匯流排仲裁。
今天要把兩個 11-bit Identifier 排在一起,真正看懂:為什麼 dominant 0 能覆蓋 recessive 1,又為什麼 ID 數值越小,通常具有越高優先權。
讀完這篇文章,你應該能夠:
本文的主要例子使用 Classical CAN 的 11-bit Standard Data Frame。
這樣可以先把仲裁機制看清楚,不必同時處理 29-bit Extended ID 的所有欄位。
不過,實際仲裁不只看工具畫面上的 Identifier 數字。
相關 bit 包括 RTR(Remote Transmission Request,遠端傳送請求)、SRR(Substitute Remote Request,替代遠端請求)與 IDE(Identifier Extension,識別碼延伸)。
它們也可能影響 Standard/Extended Frame 或 Data/Remote Frame 之間的結果,後半段會再補上這些條件。
本文提到的 ID 與訊息用途都是教學範例,不代表任何特定車款的真實通訊定義。
Day 03 曾經介紹 High-Speed CAN 的兩種匯流排狀態:
Dominant 中文常稱顯性,Recessive 則稱隱性。
| CAN 狀態 | 一般邏輯表示 | 仲裁時的特性 |
|---|---|---|
| Dominant | 0 |
只要有節點送出 dominant,Bus 就呈現 dominant |
| Recessive | 1 |
只有所有傳送節點都送出 recessive,Bus 才呈現 recessive |
這種關係常以 Wired-AND(線與) 描述:
| 節點 A | 節點 B | Bus 上觀察到的狀態 |
|---|---|---|
recessive 1 |
recessive 1 |
recessive 1 |
dominant 0 |
recessive 1 |
dominant 0 |
recessive 1 |
dominant 0 |
dominant 0 |
dominant 0 |
dominant 0 |
dominant 0 |
所以 dominant 不是「比較大」,而是它在電氣與邏輯結果上可以覆蓋 recessive。
當 Bus idle 時,線路維持 recessive 狀態。
節點要開始傳送 Frame,會先送出 dominant 的 SOF,再從最高有效位元開始送出 Identifier。
CAN 節點傳送 Identifier 時,不是把資料丟出去就不管了。
它會在每個 bit 的取樣點比較兩件事:
我剛才送出的 bit
對照
Bus 上實際讀到的 bit
仲裁期間可能出現三種情況:
| 傳送端送出 | Bus 讀回 | 代表什麼 |
|---|---|---|
dominant 0 |
dominant 0 |
目前仍可能獲勝,繼續傳送 |
recessive 1 |
recessive 1 |
目前仍可能獲勝,繼續傳送 |
recessive 1 |
dominant 0 |
有其他節點送出更高優先權的 bit,立即退出仲裁 |
退出的節點不會送出 Error Frame,因為這不是傳輸錯誤。
它會停止傳送並改為接收目前獲勝的 Frame,等 Bus 再次空閒後重新嘗試。
假設兩個節點同時傳送 11-bit Standard Data Frame:
節點 A:ID 0x180 = 0011000|0|000
節點 B:ID 0x188 = 0011000|1|000
↑
第一個不同 bit:ID3
Identifier 會從 Most Significant Bit(MSB,最高有效位元)開始傳送。
兩個節點在 ID10 到 ID4 送出的內容完全相同,因此都繼續傳送。
到了 ID3:
0
1
0
1 卻讀回 0,因此知道自己輸掉仲裁
圖 1:0x180 與 0x188 從 MSB 開始比較,0x180 在 ID3 送出 dominant 0 並取得 Bus 使用權,使用 Mermaid 繪製
最後,節點 A 繼續送完 0x180 的 Frame。
節點 B 轉為接收者,等這筆 Frame 結束且 Bus 再次可用後,才重新競爭 0x188 的傳送機會。
答案不是 CAN 額外查了一張優先權表,而是二進位數值與 dominant 0 的關係自然產生了這個結果。
兩個相同長度的正整數從 MSB 開始比較時,第一個不同 bit 為 0 的數值一定比較小。
CAN 仲裁剛好又讓 dominant 0 覆蓋 recessive 1。
因此:
第一個不同 bit 送出 0
→ Bus 上仍是 0
→ 這個 Identifier 留在競爭中
→ 它的二進位數值也比較小
若只比較同一格式的 11-bit Standard Data Frame,可以整理成:
| Standard ID | 二進位 | 協定層級的相對優先權 |
|---|---|---|
0x000 |
00000000000 |
最高 |
0x120 |
00100100000 |
高於 0x180 |
0x180 |
00110000000 |
高於 0x188 |
0x188 |
00110001000 |
高於 0x7FF |
0x7FF |
11111111111 |
最低 |
這裡的「最高」與「最低」只描述 CAN 仲裁順位。
實際系統還要依照高層協定與車輛架構分配 Identifier,不代表所有專案都能任意使用 0x000 或 0x7FF。
CAN 的仲裁常被稱為 Non-destructive Bitwise Arbitration(非破壞性逐位元仲裁),可以拆成兩部分理解。
節點不是先送完整個 ID 再比較,而是從 MSB 開始,每送一個 bit 就立即監看結果。
一旦送出 recessive 卻讀到 dominant,該節點便退出競爭。
輸掉的節點送出的 recessive bit 已被 dominant bit 覆蓋,而這個 dominant bit 正是獲勝者原本要傳送的內容。
因此獲勝 Frame 可以直接繼續,不必因為這次競爭而從頭重送。
要注意,「不破壞」不代表所有等待時間都消失:
這種設計讓重要訊息能較快取得 Bus,但前提是 Identifier 與整體流量在系統設計階段已妥善規劃。
對相同格式的 Data Frame 來說,直接比較 Identifier 通常就能判斷結果。
但完整理解仲裁時,還要知道 Identifier 旁邊的控制 bit 可能繼續分出勝負。
在 Classical CAN 中,RTR 是 Remote Transmission Request 的縮寫:
| Frame | RTR |
|---|---|
| Data Frame | dominant 0 |
| Remote Frame | recessive 1 |
若兩者使用相同 Identifier 並同時競爭,前面的 ID bit 全部相同,Data Frame 會在 RTR 位置以 dominant 0 勝過 Remote Frame。
29-bit Extended Frame 會在前 11 個 Base Identifier 後加入 SRR 與 IDE,再傳送後續 18 個 Identifier bit。
當 Standard 與 Extended Frame 的前 11 個 ID bit 相同時,Standard Frame 會在 SRR/RTR 或 IDE 的格式分歧處取得優先權。
因此不能把一個 11-bit ID 與一個 29-bit ID 當成普通整數,直接比較畫面上的十六進位數字就下結論。
CAN 仲裁的是訊息優先權,不是傳送端身分。
如果兩個節點送出相同 Identifier 與相同 Frame 類型,它們不會在仲裁階段分出勝負。
若後續 Data 或其他受監看的 bit 不同,便可能被判定為 bit error,造成 Error Frame 與重送。
因此設計 CAN 網路時,應避免讓不同傳送者用相同 ID 發送不同內容。
把以上條件整理成一張表:
| 同時競爭的 Frame | 決定結果的位置 | 結果 |
|---|---|---|
| 相同格式、不同 ID | 第一個不同的 Identifier bit | 較小 ID 獲勝 |
| 相同 ID 的 Data/Remote Frame | RTR | Data Frame 獲勝 |
| 前 11 個 ID bit 相同的 Standard/Extended Frame | SRR/RTR 或 IDE | Standard Frame 獲勝 |
| 相同 ID 與相同 Frame 類型 | 仲裁期間沒有不同 bit | 無法靠仲裁分辨傳送者 |
假設低優先權 Frame 已經贏得仲裁並進入 Data Field,新的高優先權 Frame 不會在中途把它切斷。
高優先權節點必須等目前的 Frame 完成、經過必要的 Intermission,並再次看到 Bus 可用,才能開始下一輪競爭。
所以 CAN 的優先權代表:
多筆 Frame 同時等待 Bus 時,誰在下一次仲裁先取得完整 Frame 的傳送機會。
它不是作業系統裡可以中斷正在執行工作的搶占式排程。
Frame 長度、bit rate、錯誤重送與 Bus load 都會影響實際延遲。
CAN 的 Identifier 通常在系統設計階段分配,優先權也跟著固定。
這讓設計者可以把時間敏感的訊息放在較高順位,再分析它們的最壞情況延遲。
但「ID 小」不等於「一定準時」。
分析延遲時至少要一起考慮:
如果高優先權流量持續佔用 Bus,低優先權 Frame 可能反覆輸掉仲裁,延遲會愈來愈長,嚴重時甚至長時間得不到傳送機會。
因此 Identifier 不能只依功能名稱隨意編號。
它同時是通訊排程的一部分,需要配合時序需求、負載分析與錯誤情境一起設計。
仲裁可以決定誰先傳送,卻不會驗證誰有資格使用某個 ID。
一筆 Frame 因為 ID 較小而取得優先權,只代表它在仲裁規則中排得更前面,不代表:
如果未受信任的節點已取得同一個 CAN 區段的傳送能力,它也可能送出低數值 ID 與其他節點競爭 Bus。
持續出現的高優先權流量還可能延遲其他訊息,影響可用性。
這裡先建立兩個觀念:
實際是否能形成攻擊,仍取決於攻擊者能否接觸該網路、取得傳送能力,以及 Gateway、分區與其他防護是否有效。
Day 19 會再談 CAN Injection,Day 20 則會處理 Replay、DoS 與 Bus-Off。
在一個已授權的 CAN 測試台上,三個節點同時準備傳送 11-bit Standard Data Frame:
| 節點 | Standard ID | 11-bit 二進位 |
|---|---|---|
| A | 0x188 |
00110001000 |
| B | 0x120 |
00100100000 |
| C | 0x180 |
00110000000 |
假設三筆 Frame 都沒有錯誤,而且輸掉的節點會在 Bus 再次可用時重試,請回答:
0x180 與 0x188 在哪一個 Identifier bit 首次不同?0x100,可能對其他兩筆訊息造成什麼影響?先停在這裡,不要急著往下滑!
請先從每個 11-bit ID 的 MSB 向右比較,找到第一個不同 bit,再往下對照答案。
第一輪的順序如下:
0x120 < 0x180 < 0x188
因此節點 B 的 0x120 優先權最高,先取得 Bus。
節點 A 與節點 C 退出仲裁並接收這筆 Frame。
等 0x120 傳送完成,節點 A 與節點 C 再次競爭:
0x180 = 0011000|0|000
0x188 = 0011000|1|000
↑ ID3
0x180 在 ID3 送出 dominant 0,所以節點 C 第二個傳送,最後才是節點 A 的 0x188。
| 問題 | 作者的答案 |
|---|---|
| 第一筆 | 節點 B,ID 0x120 |
| 第二筆 | 節點 C,ID 0x180 |
| 第三筆 | 節點 A,ID 0x188 |
0x180 與 0x188 首次不同 |
ID3,0x180 為 dominant 0 |
持續高頻的 0x100 |
會反覆以更高優先權取得 Bus,使其他 Frame 延遲,實際影響取決於頻率、Frame 長度與整體 Bus load |
這個練習只是在模擬網路中觀察固定優先權,不代表可以把任意低 ID 訊息送進真實車輛。
安全與法律提醒: CAN 傳送測試只應在模擬環境、隔離測試台或明確取得授權的設備上進行。
不要對道路車輛、他人的設備或公共基礎設施進行未授權測試。
0,可以覆蓋 recessive 1
連續三天看完 CAN Bus、CAN Frame 與 Arbitration 後,下一步要把視野拉到其他車載網路。
Day 06 將介紹 LIN、FlexRay 與 Automotive Ethernet,看看它們的拓樸、頻寬與使用情境有何不同,又為什麼現代汽車通常不會只靠 CAN 完成所有通訊。