CAN与上位机通信详细教程

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 本文使用32版HAL库与上位机进行通信,使用按键按一次则发送一次数据给上位机,上位机发送一次数据给32板则使用串口打印出来



文章目录

  • CAN与上位机通信详细教程

  • 一、HAL库配置
  • 二、CAN—发送内容
  • 1.定义发送结构体
  • 2.定义发送函数(记得在can.h头文件也定义一下、在CAN.c里面)
  • 3.man函数设置一下
  • 二、CAN—接收函数
  • 1.定义接收滤波(在can.c里面)
  • 2.设置中断函数(写在main.c的int main前面)
  • 3.main函数中配置
  • 实现结果



提示:本文借鉴多个博文大佬的参考 1.对于can过滤器配置请大家参考这位博主的,写的非常通俗易懂。
2.对于CSDN上很多作者的通信都是32发一个数据,则上位机把这个数据传输并打印出来,对于我做的一个项目感觉不太相似,就直接捣鼓出来发送、接收数据不一样的形式。好了,下面开始正文。


一、HAL库配置

1.我使用的是正点原子精英板(板子不一样也没关系)原理图

上位机和MES通讯 上位机can通讯_上位机


2.开始CubeMX配置

1.GPIO(按键和LED的配置)

上位机和MES通讯 上位机can通讯_上位机_02


2.RCC配置

上位机和MES通讯 上位机can通讯_嵌入式硬件_03

上位机和MES通讯 上位机can通讯_上位机_04

3.can配置

上位机和MES通讯 上位机can通讯_stm32_05


波特率:36MHZ/(9+5+2)=500

配置中断:

上位机和MES通讯 上位机can通讯_嵌入式硬件_06


3.串口

上位机和MES通讯 上位机can通讯_嵌入式硬件_07

二、CAN—发送内容

1.定义发送结构体

上位机和MES通讯 上位机can通讯_嵌入式硬件_08

2.定义发送函数(记得在can.h头文件也定义一下、在CAN.c里面)

CAN_TxHeaderTypeDef CAN_TX;
void CAN_Send(void)
{
	uint32_t TxMailbox;
	uint8_t Tdata[8]={0x00,0x04,0x93,0xE0,0x00,0x00,0x27,0x10};
	CAN_TX.StdId=0x123;
	CAN_TX.ExtId=0x028900F0;
	CAN_TX.IDE=CAN_ID_EXT;
	CAN_TX.RTR=CAN_RTR_DATA;
	CAN_TX.TransmitGlobalTime=DISABLE;
	CAN_TX.DLC=8;
	
	if(HAL_CAN_AddTxMessage(&hcan,&CAN_TX,Tdata,&TxMailbox)!=HAL_OK)
	{
		Error_Handler();
	}
}

3.man函数设置一下

下面代码放在main.c文件的while(1)里面

/* USER CODE END WHILE */
		if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0)//当按键按下
		{
			while(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0)
			{
				HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,0);//LED灯亮
				
				CAN_Send();//数据发送
				HAL_Delay(1000);
				HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,1);//LED灯灭
				HAL_Delay(500);
			}
			
		}

二、CAN—接收函数

1.定义接收滤波(在can.c里面)

void CAN_Filter_Config(void)
{
	uint32_t EXRID=0x029BF03F;
	CAN_FilterTypeDef CAN_FilterInitStructure;
	CAN_FilterInitStructure.FilterBank=0;//使用那个筛选器
	CAN_FilterInitStructure.FilterMode=CAN_FILTERMODE_IDMASK;//设置掩码模式
	CAN_FilterInitStructure.FilterScale=CAN_FILTERSCALE_32BIT;//筛选器32位宽
	CAN_FilterInitStructure.FilterIdHigh=((EXRID<<3)&0xFFFF0000)>>16;//(((((uint32_t )0X1314)<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16;//筛选高id高位
	CAN_FilterInitStructure.FilterIdLow=((EXRID<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;//((((uint32_t )0X1314)<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000;//筛选高id高位
	CAN_FilterInitStructure.FilterMaskIdHigh=0xFF00;
	CAN_FilterInitStructure.FilterMaskIdLow=0x0000;//设置筛选器每一位匹配
	
	CAN_FilterInitStructure.FilterFIFOAssignment=CAN_FilterFIFO0;//关联到f0
	CAN_FilterInitStructure.FilterActivation=ENABLE;//使能筛选器
	
	HAL_CAN_ConfigFilter(&hcan,&CAN_FilterInitStructure);
	
	
}

2.设置中断函数(写在main.c的int main前面)

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	CAN_RxHeaderTypeDef CAN_RX;
	uint8_t aData[8]; 
	if(hcan->Instance ==CAN1)
	{
		HAL_CAN_GetRxMessage(hcan,CAN_FilterFIFO0,&CAN_RX,aData);//从上位机获取数据
		HAL_UART_Transmit(&huart1,aData,CAN_RX.DLC,HAL_MAX_DELAY);//把获取的数据通过串口打印出来
		
	}

}

3.main函数中配置

下面代码放在int main(void)里面,放在while(1)上面

HAL_CAN_Start(&hcan);
	CAN_Filter_Config();
	HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING);//fifo0中断

实现结果

1.发送结果

上位机和MES通讯 上位机can通讯_stm32_09


2.接收结果

上位机和MES通讯 上位机can通讯_stm32_10


以上程序是完全可以实现的,当然如果还想要文件的我后续把文件上传一下。还要不了解的可以私信我,我看到会回复。

有需要下载项目程序的小伙伴可以点这个链接下载一下