文章目錄
- 前言
- 1. CAN協議基礎
- 1.1 物理層特性
- 差分信號線
- 終端電阻
- 通信速率
- 總線拓撲
- 1.2 幀類型
- 1.3 數據幀格式
- 2. STM32F103RCT6的CAN硬件配置
- 2.1 硬件連接
- 2.2 CubeMX配置
- 啟用CAN1
- 模式
- 波特率
- 引腳分配
- 過濾器配置(可選)
- 3. HAL庫代碼實現
- 3.1 CAN初始化
- 3.2 發送CAN數據幀
- 3.3 接收CAN數據幀(中斷模式)
- 4. 過濾器配置(接收特定ID)
- 5. 波特率計算
- 6. 常見問題與調試
- 6.1 通信失敗原因
- 波特率不匹配
- 終端電阻缺失
- ID沖突
- 硬件連接錯誤
- 6.2 邏輯分析儀抓包
- 7. 完整示例:雙機通信
- 節點A(發送數據)
- 節點B(接收數據)
- 總結
- 硬件配置
- 數據收發
- 調試工具
- 應用場景
前言
CAN(Controller Area Network)是一種高可靠性、多主機的串行通信協議,廣泛應用于汽車電子、工業控制等領域。STM32F103RCT6內置了bxCAN控制器(Basic Extended CAN),支持CAN 2.0A/B標準。以下是詳細協議解析及代碼實現。
1. CAN協議基礎
1.1 物理層特性
差分信號線
CAN_H(高電平線)
CAN_L(低電平線)
終端電阻
終端電阻:120Ω(兩端各一個,抑制反射)。
通信速率
通信速率:最高1 Mbps(常見波特率:125kbps、250kbps、500kbps)。
總線拓撲
總線拓撲:線性總線結構,支持多節點(最多110個節點)。
1.2 幀類型
幀類型 用途
數據幀 傳輸實際數據(核心幀類型)
遠程幀 請求其他節點發送數據
錯誤幀 報告通信錯誤
過載幀 通知節點延遲響應
1.3 數據幀格式
[幀起始] [仲裁段] [控制段] [數據段] [CRC段] [ACK段] [幀結束]
仲裁段:
標準幀(11位ID):CAN 2.0A。
擴展幀(29位ID):CAN 2.0B。
數據段:0~8字節有效載荷。
2. STM32F103RCT6的CAN硬件配置
2.1 硬件連接
CAN信號 STM32引腳 說明
CAN_RX PA11 接收引腳
CAN_TX PA12 發送引腳
CAN_H 連接總線 高電平線
CAN_L 連接總線 低電平線
終端電阻 120Ω 接在總線兩端
2.2 CubeMX配置
啟用CAN1
模式
模式:Normal(正常模式)。
波特率
波特率:500kbps(時鐘分頻需匹配APB1時鐘,默認36MHz)。
引腳分配
引腳分配:
CAN_RX → PA11
CAN_TX → PA12
過濾器配置(可選)
設置接收過濾器(如僅接收特定ID的幀)。
3. HAL庫代碼實現
3.1 CAN初始化
#include "stm32f1xx_hal.h"CAN_HandleTypeDef hcan;void MX_CAN_Init(void) {hcan.Instance = CAN1;hcan.Init.Prescaler = 9; // 波特率 = 36MHz / (Prescaler * (1 + BS1 + BS2)) = 500kbpshcan.Init.Mode = CAN_MODE_NORMAL; // 正常模式(非環回)hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;hcan.Init.TimeSeg1 = CAN_BS1_4TQ; // BS1 = 4時間單位hcan.Init.TimeSeg2 = CAN_BS2_3TQ; // BS2 = 3時間單位hcan.Init.TimeTriggeredMode = DISABLE;hcan.Init.AutoBusOff = DISABLE;hcan.Init.AutoWakeUp = DISABLE;hcan.Init.AutoRetransmission = ENABLE; // 自動重傳hcan.Init.ReceiveFifoLocked = DISABLE;hcan.Init.TransmitFifoPriority = DISABLE;if (HAL_CAN_Init(&hcan) != HAL_OK) {Error_Handler();}}
3.2 發送CAN數據幀
void CAN_Send(uint32_t id, uint8_t *data, uint8_t len) {CAN_TxHeaderTypeDef tx_header;uint32_t tx_mailbox;tx_header.StdId = id; // 標準ID(11位)tx_header.ExtId = 0; // 擴展ID(未使用)tx_header.IDE = CAN_ID_STD; // 標準幀tx_header.RTR = CAN_RTR_DATA; // 數據幀tx_header.DLC = len; // 數據長度(0~8)tx_header.TransmitGlobalTime = DISABLE;if (HAL_CAN_AddTxMessage(&hcan, &tx_header, data, &tx_mailbox) != HAL_OK) {Error_Handler();}
}// 示例:發送8字節數據(ID=0x123)
uint8_t msg[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
CAN_Send(0x123, msg, 8);
3.3 接收CAN數據幀(中斷模式)
CAN_RxHeaderTypeDef rx_header;
uint8_t rx_data[8];void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data) == HAL_OK) {printf("Received ID: 0x%03X, Data: ", rx_header.StdId);for (uint8_t i = 0; i < rx_header.DLC; i++) {printf("%02X ", rx_data[i]);}printf("\n");}
}// 主函數中啟用接收中斷
int main(void) {HAL_Init();MX_CAN_Init();HAL_CAN_Start(&hcan);HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);while (1) { /* 其他任務 */ }
}
4. 過濾器配置(接收特定ID)
CAN控制器通過過濾器篩選接收的幀。以下配置僅接收ID=0x123的幀:
CAN_FilterTypeDef filter;filter.FilterBank = 0; // 過濾器組0
filter.FilterMode = CAN_FILTERMODE_IDMASK; // 掩碼模式
filter.FilterScale = CAN_FILTERSCALE_32BIT; // 32位過濾
filter.FilterIdHigh = 0x123 << 5; // ID高16位(左移5位對齊)
filter.FilterIdLow = 0x0000; // ID低16位
filter.FilterMaskIdHigh = 0xFFFF; // 掩碼高16位(全匹配)
filter.FilterMaskIdLow = 0x0000; // 掩碼低16位
filter.FilterFIFOAssignment = CAN_RX_FIFO0; // 存入FIFO0
filter.FilterActivation = ENABLE; // 啟用過濾器HAL_CAN_ConfigFilter(&hcan, &filter);
5. 波特率計算
CAN波特率由以下公式決定:
波特率= Prescaler×(BS1+BS2+1)
APB1時鐘:STM32F103默認36MHz。
BS1:TimeSeg1(例中為4)。
BS2:TimeSeg2(例中為3)。
Prescaler:分頻系數(例中為9)。
6. 常見問題與調試
6.1 通信失敗原因
波特率不匹配
波特率不匹配:確保所有節點波特率一致。
終端電阻缺失
終端電阻缺失:總線兩端需接120Ω電阻。
ID沖突
ID沖突:避免多個節點使用相同ID發送。
硬件連接錯誤
硬件連接錯誤:檢查CAN_H/CAN_L是否接反。
6.2 邏輯分析儀抓包
使用CAN分析儀(如PCAN-USB)或示波器觀察:
差分信號電平(CAN_H - CAN_L應為2V(顯性)或0V(隱性))。
幀結構:起始位、ID、數據等是否正常。
7. 完整示例:雙機通信
節點A(發送數據)
uint8_t data[8] = {0xAA, 0xBB, 0xCC, 0xDD};
CAN_Send(0x123, data, 4); // 發送ID=0x123的4字節數據
節點B(接收數據)
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {CAN_RxHeaderTypeDef rx_header;uint8_t rx_data[8];HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data);if (rx_header.StdId == 0x123) {HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); // 收到數據后翻轉LED}
}
總結
硬件配置
硬件配置:正確設置波特率、過濾器。
數據收發
數據收發:使用HAL_CAN_AddTxMessage和中斷回調。
調試工具
調試工具:邏輯分析儀、CAN分析儀是關鍵。
應用場景
應用場景:汽車ECU通信、工業傳感器網絡等。
通過上述代碼,STM32F103RCT6可穩定實現CAN通信,適用于高可靠性要求的嵌入式系統。