STM32F103ZET6+TJA1050 HAL CAN通讯笔记

CAN Rx中断在这里插入图片描述

CAN波特率参数设置
500KCAN_Prescaler=12;
CAN_SJW=CAN_SJW_1tq;
CAN_BS1=CAN_BS1_3tq;
CAN_BS2=CAN_BS2_2tq;

由于CubeMX不会初始化过滤器,因此需要自己在can.c完成过滤器的配置,并在can.h中声明,然后在main函数中引用:

void CAN1_Config(void)
{
	CAN_FilterTypeDef CAN_FilterType;
	CAN_FilterType.FilterBank=0;
	CAN_FilterType.FilterIdHigh=0x0000;
	CAN_FilterType.FilterIdLow=0x0000;
	CAN_FilterType.FilterMaskIdHigh=0x0000;
	CAN_FilterType.FilterMaskIdLow=0x0000;
	CAN_FilterType.FilterFIFOAssignment=CAN_RX_FIFO0;
	CAN_FilterType.FilterMode=CAN_FILTERMODE_IDMASK;
	CAN_FilterType.FilterScale=CAN_FILTERSCALE_32BIT;
	CAN_FilterType.FilterActivation=ENABLE;
	CAN_FilterType.SlaveStartFilterBank=14;
	if(HAL_CAN_ConfigFilter(&hcan,&CAN_FilterType)!=HAL_OK)//过滤器初始化
	{
		Error_Handler();
	}
	if(HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING)!=HAL_OK)//使能中断
	{
		Error_Handler();
	}
	if(HAL_CAN_Start(&hcan)!=HAL_OK)//启动CAN1
	{
		Error_Handler();
	}
}

如果需要发送CAN数据,则需要在can.c中定义发送数据函数,并在can.h中进行声明,然后在需要引用的地方对其进行引用(见例1):

/***********************************************
函数功能:向CAN总线发送数据
入口参数:
	IDE:	0:标准帧  , 1:扩展帧
	CANID:	帧ID
	LEN:	数据长度
	data:	数据
返回值:0:成功。1:失败
************************************************/
uint8_t Can_TxMessage(uint8_t IDE,uint32_t CANID,uint8_t LEN,uint8_t *data)
{
	uint32_t   TxMailbox;
	CAN_TxHeaderTypeDef CAN_TxHeader;
	HAL_StatusTypeDef   HAL_RetVal; 
	uint16_t i=0;
	if(IDE == 0)
	{
		CAN_TxHeader.IDE = CAN_ID_STD;	//标准帧
		CAN_TxHeader.StdId = CANID;
	}
	else 
	{
		CAN_TxHeader.IDE = CAN_ID_EXT;			//扩展帧
		CAN_TxHeader.ExtId = CANID;
	}
	CAN_TxHeader.DLC = LEN;
	CAN_TxHeader.RTR = CAN_RTR_DATA;//数据帧,CAN_RTR_REMOTE遥控帧
	CAN_TxHeader.TransmitGlobalTime = DISABLE;
	while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan) == 0)//等待可用的发送邮箱
	{
		i++;
		if(i>0xfffe)
			return 1;
	}
	HAL_RetVal = HAL_CAN_AddTxMessage(&hcan,&CAN_TxHeader,data,&TxMailbox);//向发送邮箱添加需要发送的数据
	if(HAL_RetVal != HAL_OK)
		return 1;
	return 0;
}

如果需要接收来自CAN总线的信号,则需要在can.c中进行中断回调函数定义,同步在can.c中声明
uint8_t CAN_RxData[8]; CAN_RxHeaderTypeDef CAN_RxHeader;
在can.h中定义extern uint8_t CAN_RxData[8]; extern CAN_RxHeaderTypeDef CAN_RxHeader;

//CAN Rx中断回调函数,函数名称为系统默认名称"不可更改"
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	HAL_StatusTypeDef HAL_Retval;
	if(hcan->Instance==CAN1)
	{
		HAL_Retval=HAL_CAN_GetRxMessage(hcan,CAN_FILTER_FIFO0,&CAN_RxHeader,CAN_RxData);//获取CAN总线数据
		if(HAL_Retval == HAL_OK)
		{
			if(CAN_RxHeader.StdId==0x7E0) Can_TxMessage(0,0x7E8,8,CAN_RxData);//如果接收到CANID=7E0的信号则直接转发出来
		}
	}
}

例1,在main函数中的while循环中发送CAN消息

/* USER CODE BEGIN WHILE */
CAN1_Config(void);
uint8_t data[8]={0x22,0x02,0x03,0x04,0x00,0x00,0x00,0x00};//定义发送数组
uint8_t CANID=0x001;
uint8_t DLC=8;数据长度=8
uint8_t CANID_Type=0;//标准帧
while (1)
{
	Can_TxMessage(CANID_Type,CANID,DLC,data);//发送想要发送的报文数据
	HAL_Delay(10-1);    //延时10ms
}

版权声明:本文为qqwertccc原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。