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);//消息掛起中斷使能,必需要有這一句,否則只中斷一次就不能進入中斷了
}
}