无主之地2配置高吗|看真人裸体BBBBB|秋草莓丝瓜黄瓜榴莲色多多|真人強奷112分钟|精品一卡2卡3卡四卡新区|日本成人深夜苍井空|八十年代动画片

網(wǎng)易首頁(yè) > 網(wǎng)易號(hào) > 正文 申請(qǐng)入駐

CAN 總線仲裁機(jī)制詳解 + C++ 模擬代碼

0
分享至


CAN(Controller Area Network)總線最核心的精妙設(shè)計(jì)之一就是 非破壞性位仲裁。當(dāng)多個(gè)節(jié)點(diǎn)同時(shí)開始發(fā)送消息時(shí),總線不會(huì)像以太網(wǎng)那樣發(fā)生“碰撞”并丟棄數(shù)據(jù),而是通過 ID 逐位比較,優(yōu)先級(jí)高的節(jié)點(diǎn)繼續(xù)發(fā)送,優(yōu)先級(jí)低的節(jié)點(diǎn)自動(dòng)退出,整個(gè)過程不丟失任何數(shù)據(jù),也無(wú)需重傳整個(gè)幀。

1. 仲裁原理

  • 顯性位 (0) 和 **隱性位 (1)**:CAN 總線采用“線與”邏輯,顯性位(0)可以覆蓋隱性位(1)。

  • 仲裁過程 :所有節(jié)點(diǎn)同時(shí)發(fā)送自己的消息 ID(從高位到低位)。每個(gè)節(jié)點(diǎn)在發(fā)送每一位的同時(shí),也監(jiān)聽總線狀態(tài)。

    • 如果節(jié)點(diǎn)發(fā)送的是隱性位 (1),但總線上檢測(cè)到顯性位 (0),說明有其他節(jié)點(diǎn)正在發(fā)送優(yōu)先級(jí)更高的 ID(0 比 1 優(yōu)先級(jí)高)。

    • 該節(jié)點(diǎn)立即 退出仲裁 ,停止發(fā)送,轉(zhuǎn)為接收模式。

    • 仲裁獲勝的節(jié)點(diǎn)(ID 數(shù)值最小,即顯性位最多)繼續(xù)發(fā)送完整的數(shù)據(jù)幀。

  • 失敗節(jié)點(diǎn)處理 :退出仲裁的節(jié)點(diǎn)會(huì)在總線空閑后 自動(dòng)重發(fā) ,無(wú)需軟件干預(yù)。

為什么更適合實(shí)時(shí)控制? 以太網(wǎng)發(fā)生沖突需要隨機(jī)退避重試,延遲不可預(yù)測(cè);CAN 的仲裁機(jī)制保證了高優(yōu)先級(jí)消息最多在一個(gè)幀時(shí)間內(nèi)就能成功發(fā)送,延遲確定且極低。
2. C++ 模擬代碼

下面用 C++ 模擬三個(gè)節(jié)點(diǎn)同時(shí)發(fā)送的場(chǎng)景,演示位仲裁過程。為了清晰,我們將 CAN 幀簡(jiǎn)化為 11 位標(biāo)準(zhǔn) ID(實(shí)際還有控制域、數(shù)據(jù)域等,但仲裁只依賴 ID)。

#include  
          
#include
#include
#include
#include

using namespace std;

// 模擬一個(gè) CAN 節(jié)點(diǎn)
class CANNode {
public:
int nodeId; // 節(jié)點(diǎn)編號(hào)
int messageId; // 消息 ID(越小優(yōu)先級(jí)越高)
bool sending; // 是否正在發(fā)送
bool arbitrationLost;// 仲裁是否失敗

CANNode(int id, int msgId) : nodeId(id), messageId(msgId), sending(false), arbitrationLost(false) {}

// 返回 11 位 ID 的二進(jìn)制字符串(高位在前)
string getIdBits() const {
return bitset<11>(messageId).to_string();
}
};

// 模擬總線仲裁
// 參數(shù):參與仲裁的節(jié)點(diǎn)列表
// 返回值:獲勝的節(jié)點(diǎn)指針,如果沒有節(jié)點(diǎn)返回 nullptr
CANNode* arbitrate(vector & nodes) {
if (nodes.empty()) return nullptr;

// 所有節(jié)點(diǎn)同時(shí)開始發(fā)送
for (auto node : nodes) {
node->sending = true;
node->arbitrationLost = false;
}

cout << "\n========== 仲裁開始 ==========" << endl;
cout << "參與節(jié)點(diǎn): ";
for (auto node : nodes) {
cout << "Node" << node->nodeId << "(ID=" << node->messageId << ") ";
}
cout << endl;

// 獲取所有節(jié)點(diǎn)的 ID 位串
vector bitStrings;
for (auto node : nodes) {
bitStrings.push_back(node->getIdBits());
}

// 逐位仲裁(從高位到低位,即索引 0 到 10)
for (int bitPos = 0; bitPos < 11; ++bitPos) {
// 收集當(dāng)前位所有節(jié)點(diǎn)發(fā)送的值(0 顯性,1 隱性)
vector bits;
for (auto node : nodes) {
if (node->sending) { // 只考慮尚未退出的節(jié)點(diǎn)
int bit = node->getIdBits()[bitPos] - '0';
bits.push_back(bit);
}
}

if (bits.empty()) break; // 沒有活躍節(jié)點(diǎn)了

// 總線狀態(tài):線與邏輯,只要有一個(gè) 0(顯性),總線就是 0
int busState = 0;
for (int b : bits) {
if (b == 0) {
busState = 0;
break;
}
}
// 如果所有位都是 1,總線才是 1
bool allOne = true;
for (int b : bits) if (b != 1) { allOne = false; break; }
if (allOne) busState = 1;

// 輸出當(dāng)前位的比較情況
cout << "位 " << bitPos << " (從高位起): ";
for (size_t i = 0; i < nodes.size(); ++i) {
if (nodes[i]->sending) {
cout << "Node" << nodes[i]->nodeId << "=" << nodes[i]->getIdBits()[bitPos];
cout << " ";
}
}
cout << "| 總線=" << busState << endl;

// 檢查哪些節(jié)點(diǎn)失?。喊l(fā)送了 1 但總線是 0
for (auto node : nodes) {
if (node->sending) {
int sentBit = node->getIdBits()[bitPos] - '0';
if (sentBit == 1 && busState == 0) {
node->sending = false;
node->arbitrationLost = true;
cout << " -> Node" << node->nodeId << " 仲裁失敗,退出" << endl;
}
}
}
}

// 找出唯一獲勝者(仍然 sending 為 true 且未失?。?br/> CANNode* winner = nullptr;
for (auto node : nodes) {
if (node->sending && !node->arbitrationLost) {
winner = node;
break;
}
}

if (winner) {
cout << "\n★★★ 仲裁勝出: Node" << winner->nodeId
<< " (ID=" << winner->messageId << ") ★★★" << endl;
} else {
cout << "\n仲裁異常:無(wú)勝出節(jié)點(diǎn)" << endl;
}
cout << "========== 仲裁結(jié)束 ==========\n" << endl;
return winner;
}

int main() {
// 創(chuàng)建三個(gè)節(jié)點(diǎn),消息 ID 分別為 0x123, 0x0FF, 0x100
// 注意:ID 是 11 位,范圍 0~0x7FF。數(shù)值越小優(yōu)先級(jí)越高。
CANNode nodeA(1, 0x123); // 二進(jìn)制: 001 0010 0011 -> 0x123
CANNode nodeB(2, 0x0FF); // 二進(jìn)制: 000 1111 1111 -> 0x0FF (更小,優(yōu)先級(jí)高)
CANNode nodeC(3, 0x100); // 二進(jìn)制: 001 0000 0000 -> 0x100

vector nodes = { &nodeA, &nodeB, &nodeC };

// 模擬同時(shí)發(fā)送
CANNode* winner = arbitrate(nodes);

// 輸出仲裁后各節(jié)點(diǎn)的狀態(tài)
cout << "仲裁結(jié)果:" << endl;
for (auto node : nodes) {
cout << "Node" << node->nodeId << " (ID=" << node->messageId << ") : "
<< (node->arbitrationLost ? "仲裁失敗,等待重發(fā)" : "獲勝,繼續(xù)發(fā)送數(shù)據(jù)幀")
<< endl;
}

// 模擬失敗節(jié)點(diǎn)在總線空閑后自動(dòng)重發(fā)(此處簡(jiǎn)化:隨機(jī)退避后重試)
cout << "\n[模擬] 總線空閑后,失敗節(jié)點(diǎn)自動(dòng)重發(fā)..." << endl;
vector failedNodes;
for (auto node : nodes) {
if (node->arbitrationLost) failedNodes.push_back(node);
}
if (!failedNodes.empty()) {
// 重新仲裁(實(shí)際會(huì)按優(yōu)先級(jí)再次競(jìng)爭(zhēng))
arbitrate(failedNodes);
}

return 0;
}
3. 運(yùn)行結(jié)果示例

========== 仲裁開始 ==========
參與節(jié)點(diǎn): Node1(ID=291) Node2(ID=255) Node3(ID=256)
位 0 (從高位起): Node1=0 Node2=0 Node3=0 | 總線=0
位 1 (從高位起): Node1=0 Node2=0 Node3=0 | 總線=0
位 2 (從高位起): Node1=1 Node2=0 Node3=1 | 總線=0
-> Node1 仲裁失敗,退出
-> Node3 仲裁失敗,退出
位 3 (從高位起): Node2=1 | 總線=1
位 4 (從高位起): Node2=1 | 總線=1
位 5 (從高位起): Node2=1 | 總線=1
位 6 (從高位起): Node2=1 | 總線=1
位 7 (從高位起): Node2=1 | 總線=1
位 8 (從高位起): Node2=1 | 總線=1
位 9 (從高位起): Node2=1 | 總線=1
位 10 (從高位起): Node2=1 | 總線=1

★★★ 仲裁勝出: Node2 (ID=255) ★★★
========== 仲裁結(jié)束 ==========

仲裁結(jié)果:
Node1 (ID=291) : 仲裁失敗,等待重發(fā)
Node2 (ID=255) : 獲勝,繼續(xù)發(fā)送數(shù)據(jù)幀
Node3 (ID=256) : 仲裁失敗,等待重發(fā)

[模擬] 總線空閑后,失敗節(jié)點(diǎn)自動(dòng)重發(fā)...
========== 仲裁開始 ==========
參與節(jié)點(diǎn): Node1(ID=291) Node3(ID=256)
位 0: Node1=0 Node3=0 | 總線=0
位 1: Node1=0 Node3=0 | 總線=0
位 2: Node1=1 Node3=1 | 總線=1
位 3: Node1=0 Node3=0 | 總線=0
-> Node1 仲裁失敗,退出
位 4: Node3=0 | 總線=0
位 5: Node3=0 | 總線=0
位 6: Node3=0 | 總線=0
位 7: Node3=0 | 總線=0
位 8: Node3=0 | 總線=0
位 9: Node3=0 | 總線=0
位 10: Node3=0 | 總線=0

★★★ 仲裁勝出: Node3 (ID=256) ★★★
========== 仲裁結(jié)束 ==========
4. 代碼核心邏輯解釋
  • ** getIdBits() **:將 11 位 ID 轉(zhuǎn)換為二進(jìn)制字符串,高位在前,便于逐位比較。

  • ** arbitrate() **:

    1. 收集所有節(jié)點(diǎn)發(fā)送的當(dāng)前位。

    2. 計(jì)算總線狀態(tài)(線與:任意 0 → 總線 0)。

    3. 檢查每個(gè)活躍節(jié)點(diǎn):如果自己發(fā)的是 1 但總線是 0,則仲裁失敗,標(biāo)記 sending=false

    4. 繼續(xù)下一位,直到所有位比較完畢或只剩一個(gè)節(jié)點(diǎn)。

  • 失敗重試 :主函數(shù)中模擬了失敗節(jié)點(diǎn)在總線空閑后重新參與仲裁(實(shí)際 CAN 控制器硬件自動(dòng)完成)。

5. 總結(jié)
  • 非破壞性仲裁 :低 ID 勝出,高 ID 自動(dòng)退讓, 無(wú)數(shù)據(jù)沖突 。

  • 實(shí)時(shí)性保障 :高優(yōu)先級(jí)消息最多等待一個(gè)最長(zhǎng)幀時(shí)間(如 134 位時(shí)間)即可發(fā)送。

  • C++ 模擬 :清晰展示了逐位比較、顯性覆蓋隱性的過程,以及失敗節(jié)點(diǎn)的自動(dòng)重試機(jī)制。

這個(gè)機(jī)制使得 CAN 總線在工業(yè)控制、汽車電子等領(lǐng)域成為事實(shí)標(biāo)準(zhǔn),完美兼顧了實(shí)時(shí)性和可靠性。

特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關(guān)推薦
熱點(diǎn)推薦
100萬(wàn)公里,成了汽車行業(yè)不敢提的詞?

100萬(wàn)公里,成了汽車行業(yè)不敢提的詞?

虎嗅APP
2026-05-14 18:07:07
44歲卡里克確認(rèn)轉(zhuǎn)正!簽約3年 救火4個(gè)月率曼聯(lián)重返歐冠+15戰(zhàn)10勝

44歲卡里克確認(rèn)轉(zhuǎn)正!簽約3年 救火4個(gè)月率曼聯(lián)重返歐冠+15戰(zhàn)10勝

我愛英超
2026-05-15 22:10:38
特朗普離京前,對(duì)臺(tái)灣問題已作明確表態(tài),解讀如下:

特朗普離京前,對(duì)臺(tái)灣問題已作明確表態(tài),解讀如下:

大中國(guó)
2026-05-15 21:04:02
新婚15天就爆不倫!日諧星床戰(zhàn)照外泄 人妻私訊「穿最色內(nèi)褲」求歡

新婚15天就爆不倫!日諧星床戰(zhàn)照外泄 人妻私訊「穿最色內(nèi)褲」求歡

ETtoday星光云
2026-05-14 15:58:05
中央氣象臺(tái)連發(fā)大霧暴雨強(qiáng)對(duì)流預(yù)警!廣東南部沿海有大暴雨

中央氣象臺(tái)連發(fā)大霧暴雨強(qiáng)對(duì)流預(yù)警!廣東南部沿海有大暴雨

南方都市報(bào)
2026-05-15 10:50:26
中美這場(chǎng)舉世矚目的會(huì)晤,釋放了哪些重要信號(hào)?

中美這場(chǎng)舉世矚目的會(huì)晤,釋放了哪些重要信號(hào)?

補(bǔ)壹刀
2026-05-15 14:03:13
新能源概念通脹退潮后,誰(shuí)在裸泳?

新能源概念通脹退潮后,誰(shuí)在裸泳?

虎嗅APP
2026-04-23 22:36:41
江西舉報(bào)恩人沈女士已社死,正臉照曝光,大叔崗位被調(diào),景區(qū)回應(yīng)

江西舉報(bào)恩人沈女士已社死,正臉照曝光,大叔崗位被調(diào),景區(qū)回應(yīng)

奇思妙想草葉君
2026-05-15 07:33:51
U17國(guó)足極速扳平!萬(wàn)項(xiàng)戲耍沙特防線,3場(chǎng)造4球,鄺兆鐳助攻

U17國(guó)足極速扳平!萬(wàn)項(xiàng)戲耍沙特防線,3場(chǎng)造4球,鄺兆鐳助攻

奧拜爾
2026-05-16 01:35:34
悲催!網(wǎng)傳四川一貿(mào)易公司半夜倒閉,工資馬上發(fā),員工哭訴失業(yè)了

悲催!網(wǎng)傳四川一貿(mào)易公司半夜倒閉,工資馬上發(fā),員工哭訴失業(yè)了

火山詩(shī)話
2026-05-15 14:45:12
國(guó)企為什么不上桌?

國(guó)企為什么不上桌?

家傳編輯部
2026-05-15 15:17:35
馬特·達(dá)蒙新片大賣,全員發(fā)獎(jiǎng)金

馬特·達(dá)蒙新片大賣,全員發(fā)獎(jiǎng)金

娛圈觀察員
2026-05-15 01:31:22
持續(xù)引領(lǐng)百萬(wàn)級(jí)豪華市場(chǎng),攬勝與路虎衛(wèi)士的不可替代性從何而來(lái)?

持續(xù)引領(lǐng)百萬(wàn)級(jí)豪華市場(chǎng),攬勝與路虎衛(wèi)士的不可替代性從何而來(lái)?

球叔教你買車
2026-04-29 09:24:34
影壇大咖去世,66歲鐘楚紅淚灑靈堂,周星馳周潤(rùn)發(fā)送花,眾星現(xiàn)身

影壇大咖去世,66歲鐘楚紅淚灑靈堂,周星馳周潤(rùn)發(fā)送花,眾星現(xiàn)身

開開森森
2026-05-15 08:51:25
戛納紅毯第二彈!章澤天好美,袁姍姍嚇我一跳,周也沒扛住生圖

戛納紅毯第二彈!章澤天好美,袁姍姍嚇我一跳,周也沒扛住生圖

八卦南風(fēng)
2026-05-15 15:58:56
特朗普結(jié)束訪華,大贊中南海景致:若待得慣都不想走

特朗普結(jié)束訪華,大贊中南海景致:若待得慣都不想走

澎湃新聞
2026-05-15 18:28:12
英超官方承認(rèn)曼城獲利,VAR漏判恐讓阿森納痛失冠軍

英超官方承認(rèn)曼城獲利,VAR漏判恐讓阿森納痛失冠軍

樂道足球C
2026-05-15 20:34:33
保時(shí)捷中國(guó)高管喊話被抄襲無(wú)奈,羅永浩怒懟:論流氓誰(shuí)能跟保時(shí)捷比,新能源抄了保時(shí)捷的,不是只有那個(gè)誰(shuí)和那個(gè)誰(shuí)嗎

保時(shí)捷中國(guó)高管喊話被抄襲無(wú)奈,羅永浩怒懟:論流氓誰(shuí)能跟保時(shí)捷比,新能源抄了保時(shí)捷的,不是只有那個(gè)誰(shuí)和那個(gè)誰(shuí)嗎

大風(fēng)新聞
2026-05-15 12:21:07
成交價(jià)1.1億!國(guó)際足聯(lián)低頭,央視拿下世界杯版權(quán),卻遭全網(wǎng)吐槽

成交價(jià)1.1億!國(guó)際足聯(lián)低頭,央視拿下世界杯版權(quán),卻遭全網(wǎng)吐槽

譚談社會(huì)
2026-05-15 16:49:00
張雪機(jī)車再拿第一!WSBK捷克站自由賽:53號(hào)車手德比斯奪全場(chǎng)第一

張雪機(jī)車再拿第一!WSBK捷克站自由賽:53號(hào)車手德比斯奪全場(chǎng)第一

快科技
2026-05-15 18:00:34
2026-05-16 03:00:49
新能源自動(dòng)駕駛 incentive-icons
新能源自動(dòng)駕駛
專注于半導(dǎo)體行業(yè)資訊
977文章數(shù) 347關(guān)注度
往期回顧 全部

科技要聞

直降千元起步!蘋果華為率先開啟618讓利

頭條要聞

黃仁勛在北京喝豆汁痛苦皺眉 問“這是什么東西”

頭條要聞

黃仁勛在北京喝豆汁痛苦皺眉 問“這是什么東西”

體育要聞

德約科維奇買的球隊(duì),從第6級(jí)聯(lián)賽升入法甲

娛樂要聞

方媛為何要來(lái)《桃花塢6》沒苦硬吃?

財(cái)經(jīng)要聞

騰訊掉隊(duì),馬化騰戳破真相

汽車要聞

高爾夫GTI刷新紐北紀(jì)錄 ID. Polo GTI迎全球首秀

態(tài)度原創(chuàng)

藝術(shù)
家居
教育
游戲
公開課

藝術(shù)要聞

1008米!沙特“世界第一高樓”項(xiàng)目,為何極有可能建成?

家居要聞

110㎡淡而有致的生活表達(dá)

教育要聞

2027英國(guó)留學(xué)費(fèi)用+排名+雅思要求一篇看懂

《街霸6》春麗新品來(lái)了!招牌肉腿完美還原

公開課

李玫瑾:為什么性格比能力更重要?

無(wú)障礙瀏覽 進(jìn)入關(guān)懷版