歡迎關注公衆号"嵌入式技術開發",大家可以背景給我留言溝通交流。如果覺得該公衆号對你有所幫助,也歡迎推薦分享給其他人。
1.CAN總線簡介
CAN是控制器區域網路絡(Controller Area Network, CAN)的簡稱,是由以研發和生産汽車電子産品著稱的德國BOSCH公司開發的,是國際上應用最廣泛的現場總線之一。
CAN控制器通過組成總線的2根線(CAN-H和CAN-L)的電位差來确定總線的電平,信号是以兩線之間的“差分”電壓形式出現,這點與RS485類似,但兩者電平值不同。CAN總線電平分為顯性電平和隐性電平。
CAN總線采用兩種互補的邏輯數值"顯性"和"隐性"。"顯性"數值表示邏輯"0",而"隐性"表示邏輯"1"。當總線上同時出現“顯性”位和“隐性”位時,最終呈現在總線上的是“顯性”位。 在“隐性”狀态下,VCAN_H和VCAN_L被固定于平均電壓電平,Vdiff近似為零,此時VCAN_H和VCAN_L的标稱值為2.5V。“顯性”位以大于最小閥值的差分電壓表示,此時VCAN_H的标稱值為3.5V,VCAN_L的标稱值為1.5V。如下圖所示:

2.CAN幀結構
CAN總線節點上的節點發送資料是以封包的形式廣播給網絡中所有節點。收發器接收到資料就把資料傳送給控制器,再由控制器檢查判斷是不是所需資料。不是則忽略。
- 網絡上任何一個節點在任何時候都可以發送資料
- 多個節點發送資料,優先級低主動退出發送
- 短幀結構,每幀資料資訊為0~8位元組(具體使用者定義),對資料編碼而不是位址編碼
-
CAN每幀都有CRC校驗和其他檢驗措施,嚴重錯誤的情況下具有自動關閉輸出的功能
封包傳輸由以下5個不同的幀類型所表示和控制:
- 資料幀:資料幀攜帶資料從發送器至接收器。
- 遠端幀:總線單元發出遠端幀,請求發送具有同一識别符的資料幀。
- 錯誤幀:任何單元檢測到總線錯誤就發出錯誤幀。
- 幀間隔:資料幀(或遠端幀)通過幀間空間與前述的各幀分開。
- 過載幀:過載幀用以在先行的和後續的資料幀(或遠端幀)之間提供附 加的延時。
具體幀結構的介紹,可以參考後面一篇文章。
3.硬體設計
現在很多單片機中内置CAN總線協定控制器,隻要外接總線驅動晶片和适當的抗幹擾電路就可以很友善地建立一個CAN總線智能測控節點。驅動晶片如下:
4.軟體設計
這裡以STM32L431單片機為例,建立STM32CubeMX工程,使能CAN接口,設定時鐘及配置設定系數等參數,如下圖:
STM32L431的系統時鐘為80M,上圖中設定的波特率為100kbps。計算方法如下:
CAN波特率為 = 系統時鐘/Prescaler/ (SJW+BS1+BS2) = 80MHz/32/(1+16+8) = 100KHz
使能接收中斷:
生成代碼後,添加CAN濾波器配置函數,如下:
static CAN_TxHeaderTypeDef TxMessage; //CAN發送的消息的消息頭
static CAN_RxHeaderTypeDef RxMessage; //CAN接收的消息的消息頭
//can總線接收中斷函數
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
uint8_t data[8]; //接收資料緩存
HAL_StatusTypeDef status;
if (hcan == &hcan1)
{
status = HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxMessage, data);
if (HAL_OK == status)
{
//資料處理。。。
}
}
}
//can發送資料函數
void CAN1_Send_Test()
{
uint8_t data[4] = {0x01, 0x02, 0x03, 0x04}; //需要發送的資料
TxMessage.IDE = CAN_ID_STD; //設定ID類型
TxMessage.StdId = 0x222; //設定ID号
TxMessage.RTR = CAN_RTR_DATA; //設定傳送資料幀
TxMessage.DLC = 4; //設定資料長度
if (HAL_CAN_AddTxMessage(&hcan1, &TxMessage, data, (uint32_t*)CAN_TX_MAILBOX0) != HAL_OK)
{
Error_Handler();
}
}
編寫接收中斷函數和發送資料函數:
CANFilter_Config();
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
CAN1_Send_Test();
HAL_Delay(100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
在主函數中調用濾波器配置函數,啟動CAN總線,使能接收中斷,并循環發送測試資料:
通過USB轉CAN的工具可以在電腦端檢視資料是否成功。可以看到,資料可以正常發送。