天天看點

基于CubeMX-STM32F302_CAN通信1、簡介2、準備3、CubeMX 工程配置4、代碼配置

1、簡介

STM32F302的核心為Cortex-M4。

bxCAN是基本擴充CAN(Basic Extended CAN)的縮寫,它支援CAN協定2.0A和2.0B。它的設計目标是,以最小的CPU負荷來高效處理大量收到的封包。它也支援封包發送的優先級要求(優先級特性可軟體配置)。對于安全緊要的應用, bxCAN提供所有支援時間觸發通信模式所需的硬體功能。

2、準備

2.1、軟體

1、HAL 庫版本:STM32Cube FW_F3 V1.11.2

2.2、開發工具

1、STM32CubeMX 6.2.0

2、Keil uVision5 V5.34.0.0

2.3、代碼測試時間

2021年7月25日

2.4、參考文檔

STM32F302參考手冊:RM0365

STM32F3 HAL庫使用者手冊:UM1786

3、CubeMX 工程配置

3.1、參數配置

在該項配置中的波特率配置如下圖所示。其中Tpclk為經過分頻的時鐘,其中bxCAN在外設時鐘APB1上為36MHz,經過分頻為6MHz。

其中TS1配置為2、TS2配置為3。波特率為1MHz。此處配置可參考下面圖檔進行了解。

基于CubeMX-STM32F302_CAN通信1、簡介2、準備3、CubeMX 工程配置4、代碼配置
基于CubeMX-STM32F302_CAN通信1、簡介2、準備3、CubeMX 工程配置4、代碼配置
基于CubeMX-STM32F302_CAN通信1、簡介2、準備3、CubeMX 工程配置4、代碼配置

 3.2、中斷配置

基于CubeMX-STM32F302_CAN通信1、簡介2、準備3、CubeMX 工程配置4、代碼配置

3.3、中斷優先級配置

基于CubeMX-STM32F302_CAN通信1、簡介2、準備3、CubeMX 工程配置4、代碼配置

4、代碼配置

4.1、配置辨別符過濾

硬體過濾的做法節省了CPU開銷, 每個過濾器組x由2個32位寄存器, CAN_FxR0 和 CAN_FxR1 組成。

主要的配置寄存器為:CAN_FM1R、CAN_FS1R、CAN_FA1R。參考下圖,此處我們配置為:1 個 32 位過濾器-辨別符屏蔽模式

看圖可以了解到過濾器中的低三位是 IDE、RTR、0 三個,在擴充幀中ID 的位數為29位,是以我們定義的 ID 低29位是有效位,高三位我們通過移位操作去除掉。

我們跳轉到 CAN 通信濾波器配置函數中就可以看出來,

參數 FilterIdHigh、 FilterIdLow 對應寄存器 CAN_FxR1、

參數 FilterMaskIdHigh、 FilterMaskIdLow 對應寄存器 CAN_FxR2。

對照下表我們就知道如何進行配置。

基于CubeMX-STM32F302_CAN通信1、簡介2、準備3、CubeMX 工程配置4、代碼配置

4.2、濾波器配置初始化

根據上述講解我們将相應的 ID 左移三位,對應到 ID 的區域,配置 IDE 為1(我們用的擴充幀格式),代碼如下圖所示

記得初始化過濾器的結構體,此處代碼截圖未截到:CAN_FilterTypeDef My_CanFilter0,My_CanFilter1,My_CanFilter2,My_CanFilter3;

如果要過濾多個 ID 可以增加對濾波器(在STM32F302CBT6中共有13個濾波器),對應的參數為 FilterBank(0-12)

基于CubeMX-STM32F302_CAN通信1、簡介2、準備3、CubeMX 工程配置4、代碼配置

代碼:

My_CanFilter0.FilterActivation = ENABLE;
	My_CanFilter0.FilterBank = 0;
	My_CanFilter0.FilterFIFOAssignment = CAN_FilterFIFO0;
	My_CanFilter0.FilterScale = CAN_FILTERSCALE_32BIT;
	My_CanFilter0.FilterMode = CAN_FILTERMODE_IDMASK;
  
	My_CanFilter0.FilterIdHigh = ((CAN_IMU_ID<<3)>>16)&0xffff;
	My_CanFilter0.FilterIdLow = ((CAN_IMU_ID<<3)&0xffff)|CAN_ID_EXT;
	My_CanFilter0.FilterMaskIdHigh = ((DeviceMask<<3)>>16)&0xffff;
	My_CanFilter0.FilterMaskIdLow = ((DeviceMask<<3)&0xffff)|CAN_ID_EXT;
  
	if(HAL_CAN_ConfigFilter(&hcan,&My_CanFilter0) != HAL_OK)
	{
		Error_Handler();
	}
	
  
	My_CanFilter1.FilterActivation = ENABLE;
	My_CanFilter1.FilterBank = 1;
	My_CanFilter1.FilterFIFOAssignment = CAN_FilterFIFO0;
	My_CanFilter1.FilterScale = CAN_FILTERSCALE_32BIT;
	My_CanFilter1.FilterMode = CAN_FILTERMODE_IDMASK;
  
	My_CanFilter1.FilterIdHigh = ((CAN_ROLL_ID<<3)>>16)&0xffff;
	My_CanFilter1.FilterIdLow = ((CAN_ROLL_ID<<3)&0xffff)|CAN_ID_EXT;
	My_CanFilter1.FilterMaskIdHigh = ((DeviceMask<<3)>>16)&0xffff;
	My_CanFilter1.FilterMaskIdLow = ((DeviceMask<<3)&0xffff)|CAN_ID_EXT;
  
	if(HAL_CAN_ConfigFilter(&hcan,&My_CanFilter1) != HAL_OK)
	{
		Error_Handler();
	}
	
	
	My_CanFilter2.FilterActivation = ENABLE;
	My_CanFilter2.FilterBank = 2;
	My_CanFilter2.FilterFIFOAssignment = CAN_FilterFIFO0;
	My_CanFilter2.FilterScale = CAN_FILTERSCALE_32BIT;
	My_CanFilter2.FilterMode = CAN_FILTERMODE_IDMASK;
  
	My_CanFilter2.FilterIdHigh = ((CAN_PITCH_ID<<3)>>16)&0xffff;
	My_CanFilter2.FilterIdLow = ((CAN_PITCH_ID<<3)&0xffff)|CAN_ID_EXT;
	My_CanFilter2.FilterMaskIdHigh = ((DeviceMask<<3)>>16)&0xffff;
	My_CanFilter2.FilterMaskIdLow = ((DeviceMask<<3)&0xffff)|CAN_ID_EXT;
	
	if(HAL_CAN_ConfigFilter(&hcan,&My_CanFilter2) != HAL_OK)
	{
		Error_Handler();
	}
	
	
	My_CanFilter3.FilterActivation = ENABLE;
	My_CanFilter3.FilterBank = 3;
	My_CanFilter3.FilterFIFOAssignment = CAN_FilterFIFO0;
	My_CanFilter3.FilterScale = CAN_FILTERSCALE_32BIT;
	My_CanFilter3.FilterMode = CAN_FILTERMODE_IDMASK;
  
	My_CanFilter3.FilterIdHigh = ((CAN_YAW_ID<<3)>>16)&0xffff;
	My_CanFilter3.FilterIdLow = ((CAN_YAW_ID<<3)&0xffff)|CAN_ID_EXT;
	My_CanFilter3.FilterMaskIdHigh = ((DeviceMask<<3)>>16)&0xffff;
	My_CanFilter3.FilterMaskIdLow = ((DeviceMask<<3)&0xffff)|CAN_ID_EXT;
	
	if(HAL_CAN_ConfigFilter(&hcan,&My_CanFilter3) != HAL_OK)
	{
		Error_Handler();
	}
           

4.3、添加中斷使能及CAN的啟動

在 HAL 庫中 CAN 有兩種 API 來使能或關閉相應的中斷,我測試的是兩者的效果相同。

大家可以測試一下留言讨論一下

API:

HAL_CAN_ActivateNotification 開啟相應的中斷

HAL_CAN_DeactivateNotification 禁用相應的中斷

__HAL_CAN_ENABLE_IT 開啟相應的中斷

__HAL_CAN_DISABLE_IT 禁用相應的中斷

代碼:

//	if(HAL_CAN_ActivateNotification(&hcan,CAN_IT_TX_MAILBOX_EMPTY|CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
//	{
//		Error_Handler();
//	}
	__HAL_CAN_ENABLE_IT(&hcan,CAN_IT_TX_MAILBOX_EMPTY|CAN_IT_RX_FIFO0_MSG_PENDING);
	
	if(HAL_CAN_Start(&hcan) != HAL_OK)
	{
		Error_Handler();
	}
  /* USER CODE END CAN_Init 2 */

}
           

4.4、中斷函數的配置

在以上配置中我們使能的中斷是發送郵箱空中斷&接收FIFO0挂起中斷

在中斷處理檔案中 stm32f3xx_it.c 的相應中斷函數 USB_HP_CAN_TX_IRQHandler\USB_LP_CAN_RX0_IRQHandler 找到CAN的中斷處理 HAL_CAN_IRQHandler

在 HAL_CAN_IRQHandler 中找到配置使能的中斷處理代碼(我們隻使用了接收挂起中斷),找到對應的處理,使用回調函數

HAL_CAN_RxFifo0MsgPendingCallback 進行相應中斷的處理

基于CubeMX-STM32F302_CAN通信1、簡介2、準備3、CubeMX 工程配置4、代碼配置

 中斷回調處理代碼:

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan->Instance == CAN)
	{
		HAL_CAN_GetRxMessage(hcan,CAN_FilterFIFO0,&My_RxHeader,Rx_DataBuff);
	}
	
	if(My_RxHeader.IDE == CAN_ID_STD)
	{
		if(My_RxHeader.StdId == 0x00500000)
		{
		
		}
	}
	if(My_RxHeader.IDE == CAN_ID_EXT)
	{
		if(My_RxHeader.ExtId == 0x00500000)
		{
			led(1);
		}
		if(My_RxHeader.ExtId == 0x00510000)
		{
			led(2);
		}
		if(My_RxHeader.ExtId == 0x00520000)
		{
			led(3);
		}
		if(My_RxHeader.ExtId == 0x00530000)
		{
			led(4);
		}
	}
}
           

4.4、主函數的配置

添加測試代碼

基于CubeMX-STM32F302_CAN通信1、簡介2、準備3、CubeMX 工程配置4、代碼配置

 代碼:

while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  
	  printf("CAN通信測試 幀ID = %x \r\n",CAN_YAW_ID);
	  
	  CAN_SendData(&hcan,0x00510000,Rx_DataBuff,8);
  }
  /* USER CODE END 3 */
           

5、測試

基于CubeMX-STM32F302_CAN通信1、簡介2、準備3、CubeMX 工程配置4、代碼配置