STM32 HAL庫的CAN匯流排濾波器設定

2020-09-24 14:00:41

STM32 HAL庫的CAN匯流排濾波器設定

stm32cubemx生成的can初始化程式碼

#include "can.h"

#include "gpio.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

CAN_HandleTypeDef hcan1;
CAN_HandleTypeDef hcan2;

/* CAN1 init function */
void MX_CAN1_Init(void)
{

  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 3;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SJW = CAN_SJW_1TQ;
  hcan1.Init.BS1 = CAN_BS1_9TQ;
  hcan1.Init.BS2 = CAN_BS2_4TQ;
  hcan1.Init.TTCM = DISABLE;
  hcan1.Init.ABOM = ENABLE;
  hcan1.Init.AWUM = DISABLE;
  hcan1.Init.NART = DISABLE;
  hcan1.Init.RFLM = DISABLE;
  hcan1.Init.TXFP = DISABLE;
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}
/* CAN2 init function */
void MX_CAN2_Init(void)
{

  hcan2.Instance = CAN2;
  hcan2.Init.Prescaler = 3;
  hcan2.Init.Mode = CAN_MODE_NORMAL;
  hcan2.Init.SJW = CAN_SJW_1TQ;
  hcan2.Init.BS1 = CAN_BS1_9TQ;
  hcan2.Init.BS2 = CAN_BS2_4TQ;
  hcan2.Init.TTCM = DISABLE;
  hcan2.Init.ABOM = ENABLE;
  hcan2.Init.AWUM = DISABLE;
  hcan2.Init.NART = DISABLE;
  hcan2.Init.RFLM = DISABLE;
  hcan2.Init.TXFP = DISABLE;
  if (HAL_CAN_Init(&hcan2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

針對濾波器的設定

#include "my_can.h"
//改變成中文字元模式,現在一箇中文字元佔一個空格
uint16_t data[4]={0};
void My_CAN_FilterConfig(CAN_HandleTypeDef* _hcan)   
{
	//can1 &can2 use same filter config
	CAN_FilterConfTypeDef		CAN_FilterConfigStructure;
	static CanTxMsgTypeDef		Tx1Message;
	static CanRxMsgTypeDef 		Rx1Message;
	static CanTxMsgTypeDef		Tx2Message;
	static CanRxMsgTypeDef 		Rx2Message;
    
	CAN_FilterConfigStructure.FilterNumber = 0;//指定初始化第0組的過濾器
	CAN_FilterConfigStructure.FilterFIFOAssignment = CAN_FilterFIFO0;  // Filter FIFO 0 assignment for filter x
	CAN_FilterConfigStructure.BankNumber = 14;//can1(0-13) can2(14-27)//這個是can2可以使用過濾器組的起點
	CAN_FilterConfigStructure.FilterActivation = ENABLE;//使能過濾器組

	if(_hcan == &hcan1){
        CAN_FilterConfigStructure.FilterMode = CAN_FILTERMODE_IDLIST;//標誌符列表模式
        CAN_FilterConfigStructure.FilterScale = CAN_FILTERSCALE_16BIT;//設定成16位元,這樣每組過濾器就有4個過濾器
        CAN_FilterConfigStructure.FilterIdHigh = (0x201 << 5);//因為每個標準ID都是11位的,在過濾的時候要左對齊,而過濾器是16位元,所以要左移5位
        CAN_FilterConfigStructure.FilterIdLow = (0x202 << 5);
        CAN_FilterConfigStructure.FilterMaskIdHigh = (0x203 << 5);
        CAN_FilterConfigStructure.FilterMaskIdLow = (0x204 << 5);
        
				if(HAL_CAN_ConfigFilter(_hcan, &CAN_FilterConfigStructure) != HAL_OK)
					{
						while(1);//show error!
					}
					_hcan->pTxMsg = &Tx1Message;
					_hcan->pRxMsg = &Rx1Message;
	}
    
	if(_hcan == &hcan2){
        CAN_FilterConfigStructure.FilterMode = CAN_FILTERMODE_IDLIST;
        CAN_FilterConfigStructure.FilterScale = CAN_FILTERSCALE_16BIT;
        CAN_FilterConfigStructure.FilterIdHigh = (0x301 << 5);
        CAN_FilterConfigStructure.FilterIdLow = (0x302<< 5);
        CAN_FilterConfigStructure.FilterMaskIdHigh = (0x303<< 5);
        CAN_FilterConfigStructure.FilterMaskIdLow = (0x304<<5);
        
        CAN_FilterConfigStructure.FilterNumber = 14;//這個是選擇can2的過濾器,因為之前設定的為0,所以這裡針對can2還要初始化一下
		//14也是can2使用的過濾器,也是要初始化的過濾器組,也就是說,can1使用第0組,can2使用第14組
        if(HAL_CAN_ConfigFilter(_hcan, &CAN_FilterConfigStructure) != HAL_OK)
        {
            while(1);//show error!
        }
					_hcan->pTxMsg = &Tx2Message;
					_hcan->pRxMsg = &Rx2Message;
	}	
}

通過can傳送資料

HAL_StatusTypeDef  CAN2_SEND_Data(uint16_t *p)
{
		HCAN_2.pTxMsg->RTR = CAN_RTR_DATA;//資料框
		HCAN_2.pTxMsg->IDE = CAN_ID_STD; //標準幀
		HCAN_2.pTxMsg->DLC = 8;      
    HCAN_2.pTxMsg->StdId = 0x123; //ID 
    HCAN_2.pTxMsg->Data[0] = (uint8_t)(((int16_t)p[0])>>8);
    HCAN_2.pTxMsg->Data[1] = (uint8_t)(p[0]);      
    HCAN_2.pTxMsg->Data[2] = (uint8_t)(p[1]>>8);   
    HCAN_2.pTxMsg->Data[3] = (uint8_t)(p[1]); 
    HCAN_2.pTxMsg->Data[4] = (uint8_t)((p[2])>>8);
    HCAN_2.pTxMsg->Data[5] = (uint8_t)(p[2]);
    HCAN_2.pTxMsg->Data[6] = (uint8_t)(((int16_t)p[3])>>8);
    HCAN_2.pTxMsg->Data[7] = (uint8_t)(p[3]);  

    return(HAL_CAN_Transmit(&HCAN_2, 100));    
}

can匯流排中斷服務函數以及資料處理常式

void Receive_DATA(CAN_HandleTypeDef* hcan)
{
	data[0] = (uint16_t)(hcan->pRxMsg->Data[0]<<8 | hcan->pRxMsg->Data[1]);    //角度值
	data[1] =  (int16_t)(hcan->pRxMsg->Data[2]<<8 | hcan->pRxMsg->Data[3]);    //速度值
 
  data[2]  =  (int16_t)(hcan->pRxMsg->Data[4]<<8 | hcan->pRxMsg->Data[5]);
	data[3]  = (int16_t)(hcan->pRxMsg->Data[6]<<8 | hcan->pRxMsg->Data[7]);
   
    
}
/*****************************************************
@ Brief: Callback函數,can接收的軟中斷,要事先在main中開啟接收中斷
@ Param: can的結構體指標
*****************************************************/
//這個函數只能中斷一次,所以在離開中斷處理常式之前要再次使能
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* _hcan)
{
	if(_hcan==&HCAN)
	{
		switch (_hcan->pRxMsg->StdId)
		{
            case 0x201:
							Receive_DATA(_hcan);
               //處理程式碼
                 break;               
		}
		//_hcan->Instance->IER|=0x00008F02;//這一行的作用也是訊息掛起中斷使能,和下面的作用一樣
		__HAL_CAN_ENABLE_IT(_hcan, CAN_IT_FMP0);//訊息掛起中斷使能
	}
    
  else if(_hcan==&HCAN_2)
    {
        switch (_hcan->pRxMsg->StdId)
        {
            case 0x301:
           //處理程式碼
                 break;
                           
        }
        //_hcan->Instance->IER|=0x00008F02; 
		__HAL_CAN_ENABLE_IT(_hcan, CAN_IT_FMP0);//訊息掛起中斷使能,必須要有這一句,不然只中斷一次就不能進入中斷了
    }
    
}