Bootstrap

STM32CubeMX生成CAN相关程序一(发送中断与接收中断)

一、CubeMX配置

1、时钟设置

在这里插入图片描述
在这里插入图片描述
最高频率:216MHz
APB1:54MHz

2、CAN1设置

1)引脚修改

在这里插入图片描述
STM32F767IGT默认使用PI9作为接收引脚,为好了使用开发板做实验,手动将接收引脚改为PA11

在这里插入图片描述

2)中断使能

在这里插入图片描述

3)波特率计算

波特率=peripheral clocks/((TQ1+TQ2+SJW)*prescaler)
即:54MHz/((11+6+1)*6)=0.5MHz
设置波特率为:500KHz
在这里插入图片描述

3、SYS设置

在这里插入图片描述

4、GPIO设置

用于两个LED的控制
在这里插入图片描述

5、软件包版本

在这里插入图片描述

二、手动添加代码

1、添加屏蔽器设置代码

static void mx_CAN_Filter_Config(void)
{
	
	CAN_FilterTypeDef CAN1_FilerConf;
		
	CAN1_FilerConf.FilterIdHigh=0X0000;     //32位ID
    CAN1_FilerConf.FilterIdLow=0X0000;
    CAN1_FilerConf.FilterMaskIdHigh=0X0000; //32位MASK
    CAN1_FilerConf.FilterMaskIdLow=0X0000;  
    CAN1_FilerConf.FilterFIFOAssignment=CAN_FILTER_FIFO0;//过滤器0关联到FIFO0
    CAN1_FilerConf.FilterBank=0;          //过滤器0
    CAN1_FilerConf.FilterMode=CAN_FILTERMODE_IDMASK;
    CAN1_FilerConf.FilterScale=CAN_FILTERSCALE_32BIT;
    CAN1_FilerConf.FilterActivation=ENABLE; //激活滤波器0
    CAN1_FilerConf.SlaveStartFilterBank=14;
    if(HAL_CAN_ConfigFilter(&hcan1,&CAN1_FilerConf)!=HAL_OK)//滤波器初始化
	{
        Error_Handler();
    }

#if 0		
		uint32_t FilterIdHigh;          
		uint32_t FilterIdLow;           
		uint32_t FilterMaskIdHigh;      
		uint32_t FilterMaskIdLow;       
		uint32_t FilterFIFOAssignment;  
		uint32_t FilterBank;            
		uint32_t FilterMode;
		uint32_t FilterScale;
		uint32_t FilterActivation;
		uint32_t SlaveStartFilterBank;
#endif	
}

2、添加CAN发送代码

typedef struct CAN_s_Rx_Temp_t
{
	
	CAN_RxHeaderTypeDef can_rx_temp;
	uint8_t can_rx_arry[8];
	
}CAN_s_Rx_Temp;


 
typedef struct CAN_s_Tx_Temp_t
{
	
	CAN_TxHeaderTypeDef can_tx_temp;
	uint8_t can_tx_arry[8];
	uint32_t mailbox;
	
}CAN_s_Tx_Temp;

extern CAN_s_Rx_Temp hcan1_rx_temp;
extern CAN_s_Tx_Temp hcan1_tx_temp;
void CAN1_Send_Msg_Init(uint32_t a_StdId, uint32_t a_ExtId, uint32_t a_IDE, uint32_t a_RTR, uint8_t len)
{			
		hcan1_tx_temp.can_tx_temp.StdId = a_StdId;
		hcan1_tx_temp.can_tx_temp.ExtId = a_ExtId;
		hcan1_tx_temp.can_tx_temp.IDE = a_IDE;//CAN_ID_STD;
		hcan1_tx_temp.can_tx_temp.RTR = a_RTR;//CAN_RTR_DATA;
		hcan1_tx_temp.can_tx_temp.DLC = len;
		hcan1_tx_temp.can_tx_temp.TransmitGlobalTime = DISABLE;
}

void CAN1_Send_Msg(uint32_t a_StdId, uint32_t a_ExtId, uint8_t len)
{	
		uint8_t i=0;
	
		CAN1_Send_Msg_Init(a_StdId, a_ExtId, CAN_ID_STD, CAN_RTR_DATA, len);
		
		for(i=0;i<len;i++)
		{
			hcan1_tx_temp.can_tx_arry[i] = i+2;
		}
		
		if(HAL_CAN_AddTxMessage(&hcan1, &hcan1_tx_temp.can_tx_temp, 
			hcan1_tx_temp.can_tx_arry, &hcan1_tx_temp.mailbox) != HAL_OK)
		{
			Error_Handler();
		}
}

3、添加CAN代码的初始化函数

void can_init_fun(void)
{
	
	MX_CAN1_Init();
  /* USER CODE BEGIN 2 */
	

	
	mx_CAN_Filter_Config();
	

	
	if(HAL_CAN_Start(&hcan1)!=HAL_OK)
	{
		Error_Handler();

	}
	if(HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING)!=HAL_OK)					// 使能CAN接收中断
	{
		Error_Handler();

	}
	
	if(HAL_CAN_ActivateNotification(&hcan1, CAN_IT_TX_MAILBOX_EMPTY)!=HAL_OK)					// 使能CAN发送中断
	{
		Error_Handler();

	}
	
	for(uint8_t i=0;i<8;i++)
	{
		hcan1_tx_temp.can_tx_arry[i] = 0;
	}
}

4、添加CAN接收回调函数与发送回调函数

/*__weak */void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	// CAN数据接收
	if (hcan->Instance == hcan1.Instance)
	{
		if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &hcan1_rx_temp.can_rx_temp, hcan1_rx_temp.can_rx_arry) == HAL_OK)		// 获得接收到的数据头和数据
		{
			if(hcan1_rx_temp.can_rx_temp.StdId == 0x2F1)
			{
				HAL_GPIO_WritePin(LED_DS0_GPIO_Port, LED_DS0_Pin, 0);
			}
			HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING);						// 再次使能FIFO0接收中断
		}
	}
}

CAN接收回调函数功能,在回调函数中,判断接收到的数据中,有ID为2F1的数据时,点亮LED0。

/*__weak */void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan)
{
  /* Prevent unused argument(s) compilation warning */
  //UNUSED(hcan);
	if (hcan->Instance == hcan1.Instance)
	{
		static uint8_t i_index = 0;
		if(i_index < 99)
		{
			i_index++;
			if(i_index >= 99)
			{
				HAL_GPIO_TogglePin(LED_DS1_GPIO_Port, LED_DS1_Pin);
				i_index = 0;
			}
		}
		HAL_CAN_ActivateNotification(&hcan1, CAN_IT_TX_MAILBOX_EMPTY);
	}

  /* NOTE : This function Should not be modified, when the callback is needed,
            the HAL_CAN_TxMailbox0CompleteCallback could be implemented in the
            user file
   */
}

CAN发送回调函数功能,该回调函数是在CAN数据发送完成后进行调用,由于发送函数在100ms TASK中调用,如下:

void Task_For_100ms(void)
{
	CAN1_Send_Msg(0X15F, 0X15F, 8);
}

CAN发送回调函数完成后,每发送完一次后,在回调函数中计数器加1,100*100ms,即10秒翻转一次LED1。

代码记录:
STM32_Deal_A003

以上,仅为本人自用。

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;