一、物理層深度剖析
1.1 差分信號的本質
CAN總線采用****雙線差分傳輸 ,核心原理圖解:
markdown
CAN_H ────── /─────────
/
___/
CAN_L ──────/ ─────────
- 顯性狀態(Dominant) :CAN_H電壓 ≥ 2.5V,CAN_L ≤ 1.5V → 差值≥1V
- 隱性狀態(Recessive) :CAN_H/CAN_L均為2.5V → 差值≈0V
物理層參數對照表 :
參數 | 標準值 | 測試方法 |
---|---|---|
終端電阻 | 120Ω ±1% | 萬用表直接測量 |
最大傳輸距離 | 10km @ ≤5Kbps | 示波器+時延測試儀 |
波特率容差 | ±1% | 專用CAN分析儀 |
共模電壓抑制 | ±2V | 隔離示波器測量 |
1.2 波特率計算公式
markdown
位時間 = 同步段 + 傳播時間段 + 相位緩沖段1 + 相位緩沖段2
總位數 = 同步段(SJW) + 時間段1(TS1) + 時間段2(TS2)
STM32配置示例 (500Kbps):
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ; // 同步跳轉寬度=1TQ
hcan1.Init.TimeSeg1 = CAN_BS1_9TQ; // 時間段1=9TQ
hcan1.Init.TimeSeg2 = CAN_BS2_4TQ; // 時間段2=4TQ
// 總位時間=1+9+4=14TQ → 時鐘頻率=8MHz → TQ=0.125μs → 波特率=1/(14 * 0.125μs)=500Kbps
1.3 終端電阻調試技巧
- 錯誤現象 :總線波形畸變、通信不穩定
- 檢測方法:
- 斷電測量總線兩端電阻(應為120Ω±5%)
- 上電后用示波器觀察終端反射波形
- 解決方案:
# 終端電阻計算公式(單位Ω)
def calc_termination_resistance(length):
# 每米電纜約60Ω特性阻抗
return 120 - (length * 60) / 1000
# 示例:總線長度40m → 120 - 24 = 96Ω → 需補48Ω電阻
二、數據鏈路層全解析(幀結構+仲裁機制)
2.1 CAN幀類型對比表
幀類型 | 標識符長度 | 用途 | DLC最大值 |
---|---|---|---|
標準幀 | 11位 | 普通數據傳輸 | 8字節 |
擴展幀 | 29位 | 復雜設備通信 | 8字節 |
遠程幀 | 11/29位 | 請求數據 | - |
錯誤幀 | - | 錯誤通知 | - |
2.2 經典仲裁過程演示
場景 :三個節點同時發送數據
markdown
節點A: ID=0x100 (0b000100000000)
節點B: ID=0x200 (0b001000000000)
節點C: ID=0x080 (0b000010000000)
仲裁過程 :
- 第一位:全顯性 → 繼續比較
- **第二位:A=0, B=0, C=1 → C失去仲裁權**
- 后續位比較后,A勝出總線使用權
STM32仲裁配置要點 :
// 使能自動重傳功能(默認開啟)
hcan1.Init.AutoRetransmission = ENABLE;
// 設置重試次數(最大16次)
hcan1.Init.RetryCount = 3;
2.3 錯誤檢測機制詳解
五級錯誤防護體系 :
- CRC校驗 :15位循環冗余校驗
- 位填充 :每5個相同電平插入相反電平
- ACK校驗 :接收節點必須發送顯性確認
- 幀格式校驗 :7個保留位必須為隱性
- 總線監控 :持續檢測總線邏輯電平
錯誤計數器動態調整算法 :
markdown
當檢測到錯誤時:
TEC += 8(發送錯誤)或 REC += 1(接收錯誤)
當TEC > 127時:進入總線關閉狀態
2.4 位時間同步技術
同步機制 :
- 硬同步 :在幀起始位強制對齊
- 重新同步 :通過調整時間段2補償時鐘偏差
STM32時間參數配置示例 :
// 配置同步跳轉寬度為1個時間量子
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
?
// 時間段分配(假設系統時鐘16MHz)
CAN_BtrTypeDef sCanBtr;
sCanBtr.SyncJumpWidth = CAN_SJW_1TQ;
sCanBtr.TimeSeg1 = CAN_BS1_9TQ; // 傳播延遲補償
sCanBtr.TimeSeg2 = CAN_BS2_4TQ; // 相位緩沖
三、數據鏈路層核心機制
3.1 CAN協議棧全景圖
應用層(CANopen/J1939)
↓
網絡層(路由/錯誤處理)
↓
數據鏈路層(幀結構/仲裁)
↓
物理層(差分信號/終端電阻)
3.2 幀結構深度拆解
標準幀格式(11位ID) :
| 仲裁場(11b) | 控制場(6b) | 數據場(0-8B) | CRC場(15b) | ACK場(1b) | 幀結束(7b) |
- 仲裁場 :包含節點ID和幀類型標識
- 控制場 :DLC(數據長度碼) + IDE(擴展標識符)
- CRC場 :15位循環冗余校驗(生成多項式:x1?+x1?+...+1)
STM32 CRC配置示例 :
// CAN1 CRC初始化
hcan1.Instance- >CRCD = 0xFFFF; // 初始值
hcan1.Instance- >CRCSA = 0x0000; // 起始地址
3.3 仲裁機制詳解
29位擴展幀仲裁過程 :
優先級位 → 源地址 → 參數組號(PGN)
- 優先級計算 :ID31-ID26位決定(數值越小優先級越高)
- 源地址沖突檢測 :同一網絡內節點地址必須唯一
仲裁時序仿真 :
def can_arbitration(id_list):
sorted_ids = sorted(id_list, key=lambda x: bin(x).count('1'))
return sorted_ids[0]
?
# 示例:三個節點同時發送
nodes = [0x18FEF100, 0x18FEF200, 0x18FEF300]
winner = can_arbitration(nodes) # 輸出0x18FEF100
四、CANopen協議深度實戰
4.1 對象字典(Object Dictionary)
OD結構示例 :
索引 類型 描述
0x2000 ARRAY 電機控制參數
0x2000[0] UINT16 目標轉速(rpm)
0x2000[1] FLOAT 加速度(m/s2)
0x2001 RECORD 故障代碼
0x2001[0] BITFIELD 故障標志位
STM32 SDO傳輸實現 :
// SDO客戶端上傳數據
void SDO_Upload(uint16_t index, uint8_t subindex) {
CO_SDO_Req req;
CO_SDO_ReqInit(&req);
req.Cmd = CO_SDO_CMD_UPLOAD_REQ;
req.Index = index;
req.SubIndex = subindex;
if (CO_SDO_Transmit(&req) == CO_SDO_OK) {
Process_SDO_Response(req.Data);
}
}
4.2 NMT網絡管理
狀態遷移圖 :
INIT → PRE-OPERATIONAL → OPERATIONAL → STOPPED
↑ ↑ ↓
└──RESET←───────────────────┘
心跳報文配置 :
// 心跳生產者配置
CO_NMT_HeartbeatConfig(0x01, 0x00, 500); // 節點ID=1,周期500ms
五、J1939協議核心要點
5.1 參數組號(PGN)編碼規則
PGN = PF(8b) < < 8 | PS(8b)
PF: 參數組功能(0-255)
PS: 參數組子功能(0-255)
典型PGN解析 :
PGN | PF | PS | 描述 |
---|---|---|---|
0xFEFC | 0xFE | 0xFC | 發動機轉速請求 |
0xFEF0 | 0xFE | 0xF0 | 冷卻液溫度 |
0xFECA | 0xFE | 0xCA | 車輛位置報告 |
5.2 多包數據傳輸
傳輸流程 :
請求 → 確認 → 數據包1 → 數據包2 → ... → 結束符
STM32多包發送實現 :
// 多包數據發送(最大12字節/包)
void CAN_Send_MultiPacket(uint8_t *data, uint16_t length) {
uint8_t packets[6][8] = {0};
uint8_t packet_count = (length + 7) / 8;
for (int i=0; i< packet_count; i++) {
packets[i][0] = 0x00; // 流控制字段
memcpy(&packets[i][1], &data[i*8], 8);
CAN_TransmitPacket(packets[i]);
}
}
六、STM32HAL庫實戰進階
6.1 完整初始化流程
// 1. GPIO配置(CubeMX生成)
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE();
// CAN_RX/TX引腳配置
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
?
// 2. CAN初始化(含過濾器配置)
void MX_CAN1_Init(void)
{
CAN_HandleTypeDef hcan1;
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 5; // 500Kbps
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_9TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_4TQ;
hcan1.Init.Mode = CAN_MODE_NORMAL;
if (HAL_CAN_Init(&hcan1) != HAL_OK) {
Error_Handler();
}
// 濾波器配置(接收ID=0x100-0x1FF)
CAN_FilterTypeDef sFilterConfig = {0};
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x100 < < 13;
sFilterConfig.FilterIdLow = 0x1FF < < 13 | 0xFFFF;
HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig);
}
6.2 數據收發實戰
// 數據發送(PDO模擬)
void CAN_Send_PDO(uint8_t node_id, uint16_t position) {
CAN_TxHeaderTypeDef TxHeader = {0};
uint8_t TxData[8] = {0};
TxHeader.StdId = 0x200 + node_id; // PDO ID
TxHeader.IDE = CAN_ID_STD;
TxHeader.DLC = 2;
TxData[0] = (position > > 8) & 0xFF;
TxData[1] = position & 0xFF;
HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TxData, &TxMailbox);
}
?
// 接收回調(帶錯誤檢測)
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
CAN_RxHeaderTypeDef RxHeader;
uint8_t RxData[8] = {0};
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK) {
if (RxHeader.DLC != 2) {
// 數據長度異常處理
return;
}
uint16_t value = (RxData[0] < < 8) | RxData[1];
Process_Sensor_Data(value);
}
}
七、工業級應用案例解析
7.1 電動汽車三電系統
通信拓撲 :
BMS → CAN → MCU → CAN → 電機控制器
↑↓
充電樁
7.2 智能倉儲機器人
- 多機協同 :50+臺AGV通過CAN總線同步路徑規劃
- 實時監控 :電量/故障狀態實時上報
- 抗干擾方案:
- 雙絞線屏蔽層接地
- 隔離收發器(如ADuM1201)
- 冗余幀重傳機制
八、調試與優化技巧
- 示波器觀察 :
- 檢查CAN_H/CAN_L差分波形(正常應為方波)
- 波特率驗證(500Kbps對應周期2μs)
- 錯誤分析 :
- 錯誤幀計數:HAL_CAN_GetError(&hcan1)
- 總線負載率:CAN總線分析儀檢測
- 性能優化 :
九、擴展學習資源
- 經典CAN vs CAN FD :帶寬從1Mbps提升至5Mbps
- AUTOSAR架構 :標準化汽車軟件架構
- TSN時間敏感網絡 :工業4.0通信新標準
更多嵌入式知識,關注“逸云客嵌入式”公眾號!
審核編輯 黃宇
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
CAN總線
+關注
關注
145文章
1978瀏覽量
132526 -
STM32
+關注
關注
2291文章
11022瀏覽量
363481
發布評論請先 登錄
相關推薦
熱點推薦
手把手教你如何調優Linux網絡參數
在高并發網絡服務場景中,Linux內核的默認網絡參數往往無法滿足需求,導致性能瓶頸、連接超時甚至服務崩潰。本文基于真實案例分析,從參數解讀、問題診斷到優化實踐,手把手教你如何調優Linux網絡參數,支撐百萬級并發連接。
明晚七點!手把手教你做PC第九課:全功能TypeC驅動框架適配
《手把手教你做PC》系列直播課再度開播!《KaihongOS筆記本電腦開發實戰第九課:全功能TypeC驅動框架適配》將于5月21日19:00開播↑掃碼入群,領課程講義資料包↑深開鴻資深工程師親臨直播

正點原子Linux系列全新視頻教程來啦!手把手教你MP257開發板,讓您輕松入門!
正點原子Linux系列全新視頻教程來啦!手把手教你MP257開發板,讓您輕松入門!
一、視頻觀看
正點原子手把手教你學STM32MP257
發表于 05-16 10:42
【手把手教你玩轉CAN總線】從原理到STM32實戰
一、物理層深度剖析
1.1 差分信號的本質
CAN總線采用****雙線差分傳輸,核心原理圖解:
markdown
CAN
發表于 04-10 11:08
《零基礎開發AI Agent——手把手教你用扣子做智能體》
《零基礎開發AI Agent——手把手教你用扣子做智能體》是一本為普通人量身打造的AI開發指南。它不僅深入淺出地講解了Agent的概念和發展,還通過詳細的工具介紹和實戰案例,幫助讀者快速掌握
發表于 03-18 12:03
《手把手教你做星閃無人機—KaihongOS星閃無人機開發實戰》系列課程課件匯總
—KaihongOS星閃無人機開發實戰》系列課程,該課程與《手把手教你做PC—KaihongOS筆記本電腦開發實戰》同步并行,兩個系列課隔周交替播出。
《
發表于 03-18 10:33
《手把手教你做PC-KaihongOS筆記本電腦開發實戰》課件匯總
”攜手“電子發燒友”聯合推出了 《KaihongOS手把手系列直播課程》,該系列課程以實際產品為案例,詳細講解每個產品的開發全流程。
此次首發內容是《手把手教你做PC-KaihongOS筆記本電腦開發
發表于 03-18 10:25
【第四章 定時任務】手把手教你玩轉新版正點原子云
【第四章 定時任務】手把手教你玩轉新版正點原子云
承接上篇,除了報警聯動這個功能,原子云還有一個特色功能也是各開發者喜歡用的,定時任務功能。
【正點原子】云平臺:原子云(點擊登錄原子云)
前言
發表于 03-13 10:19
【第二章 模型與設備連接】手把手教你玩轉新版正點原子云
【第二章 模型與設備連接】手把手教你玩轉新版正點原子云玩過物聯網的朋友們都知道,我們在接觸各大主流云平臺時會知道物模型的概念。
本實驗就是針對原子云中模型與設備連接,舉個簡單例子說明,溫度傳感器通過
發表于 03-12 09:27
【第一章 透傳策略】手把手教你玩轉新版正點原子云
【第一章 透傳策略】手把手教你玩轉新版正點原子云
1. 本次實驗使用正點原子D40 Mini 4G Cat1 DTU數傳模塊
1.1 D40數傳模塊資料
具體使用和資料下載可到:D40 Mini
發表于 03-05 16:52
《手把手教你做PC》課程即將啟動!深開鴻引領探索KaihongOS筆記本電腦開發實戰
”攜手“電子發燒友”聯合推出了《KaihongOS手把手系列直播課程》,該系列課程以實際產品為案例,詳細講解每個產品的開發全流程。此次首發內容是《手把手教你做PC-

手把手教你通過宏集物聯網工控屏&網關進行協議轉換,將底層PLC/傳感器的數據轉換為TCP協議并傳輸到用戶
手把手教你通過宏集物聯網工控屏&網關進行協議轉換,將底層PLC/傳感器的數據轉換為TCP協議并傳輸到用戶終端

評論