【STM32】HAL库CubeMX之CAN通讯

项目场景:

CAN通讯相比较于USART,具有更高的抗干扰性能,并且能并挂多个负载,节约单片机资源

CubeMX关键配置:

在这里插入图片描述

代码修改

can.c文件添加发送函数:

/* USER CODE BEGIN 1 */

CAN_TxHeaderTypeDef TXHeader;
CAN_RxHeaderTypeDef RXHeader;
/*CAN发送数据,入口参数为要发送的数组指针,数据长度,返回0代表发送数据无异常,返回1代表传输异常*/
uint8_t CAN_Send_Msg(uint32_t CAN_TxExtId,uint8_t* msg,uint8_t len)
{	
  uint8_t i=0;
	uint32_t TxMailbox;
	uint8_t message[8];
 
	TXHeader.ExtId=CAN_TxExtId; //扩展标识符(29位)
	TXHeader.IDE=CAN_ID_EXT;    //使用扩展帧
	TXHeader.RTR=CAN_RTR_DATA;  //数据帧
	TXHeader.DLC=len;    
	
  for(i=0;i<len;i++)
  {
		message[i]=msg[i];
	}
	
  if(HAL_CAN_AddTxMessage(&hcan, &TXHeader, message, &TxMailbox) != HAL_OK)//发送
	{
		return 1;
	}
	while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan) != 3) {}
    return 0;

}
/* USER CODE END 1 */

任务函数间断发送:

/*******************************************CAN数据整理打包发送*****************************************************/	
			ContrlToB_Byte_Messagey[0]=(Laser_En_Flag<<2)|Spitfire_En_Flag<<1|Oil_En_Flag;   //发送的是激光 喷火 喷油 (当然喷火的时候一定会喷油)
			ContrlToB_Byte_Messagey[1]=Angle_Rand[1];
			ContrlToB_Byte_Messagey[2]=Angle_Rand[2];
			ContrlToB_Byte_Messagey[3]=0x00;
			ContrlToB_Byte_Messagey[4]=0x00;
			ContrlToB_Byte_Messagey[5]=0x00;
			ContrlToB_Byte_Messagey[6]=0x00;
			ContrlToB_Byte_Messagey[7]=ContrlToB_Byte_Messagey[0]+ContrlToB_Byte_Messagey[1]+ContrlToB_Byte_Messagey[2]+
		  ContrlToB_Byte_Messagey[3]+ContrlToB_Byte_Messagey[4]+ContrlToB_Byte_Messagey[5]+ContrlToB_Byte_Messagey[6];
		
			Can_count1++;
			if(Can_count1>=3)   //90ms发送一次CAN信息给控制板B
			{
			 CAN_Send_Msg(0x00004710,ContrlToB_Byte_Messagey,8);
			}

写到这里还不够,会导致发送卡死
找到can的init函数,在usercode里添加:

  /* USER CODE BEGIN CAN_Init 2 */
   CAN_FilterTypeDef sFilterConfig;
 
	 sFilterConfig.FilterActivation = ENABLE;//打开过滤器
	 sFilterConfig.FilterBank = 0;//过滤器0 这里可设0-13
	 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;//采用掩码模式
	 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;//采用32位掩码模式
	 sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;//采用FIFO0
	 
	 sFilterConfig.FilterIdHigh = 0x0000; //设置过滤器ID高16位
	 sFilterConfig.FilterIdLow = 0x0000;//设置过滤器ID低16位
	 sFilterConfig.FilterMaskIdHigh = 0x0000;//设置过滤器掩码高16位
	 sFilterConfig.FilterMaskIdLow = 0x0000;//设置过滤器掩码低16位
	 if(HAL_CAN_ConfigFilter(&hcan,&sFilterConfig) != HAL_OK)//初始化过滤器
	 {
		Error_Handler();
	 }
	 if(HAL_CAN_Start(&hcan) != HAL_OK)//打开can
	 {
		Error_Handler();
	 }
	 if(HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)//开启接受邮箱0挂起中断
	 {
		Error_Handler();
	 }
  /* USER CODE END CAN_Init 2 */

上位机验证

打开GCANTools软件,找到设备,配置CAN1,波特率选择1000K,观察接受CAN数据是否正常。
在这里插入图片描述

CAN中断接收部分:

需要在CubeMX里开启中断
在这里插入图片描述
程序部分
添加接受邮箱0挂起中断回调函数

uint8_t RXmessage[8];
uint32_t pTxMailbox = 0;

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)//接受邮箱0挂起中断回调函数
{
		if(HAL_CAN_GetRxMessage(hcan,CAN_FILTER_FIFO0,&RXHeader,RXmessage)==HAL_OK)//获取数据
		{
		//接受来自主控制板A的数据
      if (RXHeader.ExtId ==0x00004710) 
				 {					 
					if (RXmessage[7]!=RXmessage[0]+RXmessage[1]+RXmessage[2] +RXmessage[3] +RXmessage[4]+RXmessage[5] +RXmessage[6])  return;    //校验

					//	printf("Can_Recive_Step1:DataCrc16 Passed\r\n"); 
						Oil_En_Flag=(RXmessage[0]&0x01)>>0;    //00000001
						Spitfire_En_Flag=(RXmessage[0]&0x02)>>1;      //00000010
						Laser_En_Flag=(RXmessage[0]&0x04)>>2;
					  Vertical_Angle_Offset=RXmessage[1];     //俯仰角度偏移量  俯仰设置的最大角度是28.65 即0.5弧度
	          Horizontal_Angle_Offset=RXmessage[2];   //水平角度偏移量
							
					if(RXmessage[0]==0x06)   //调试判断返回帧
					{
				   	CAN_Send_Msg(0x00004712,TXmessage3,8);
					}		
//数值接受后处理
	if(Oil_En_Flag==1) 
		{
		  htim3.Instance->CCR3=1850;
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,1);   
		}
     else if(Oil_En_Flag==0)
		 {
			 htim3.Instance->CCR3=1100;
			 HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,1);	
		 }
				if(Spitfire_En_Flag==1)
         {
					 htim3.Instance->CCR3=1850;
				 HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,1);
				 HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,1);
				 }
				 
     else if(Spitfire_En_Flag==0)	
          {
						if(Oil_En_Flag==0)	htim3.Instance->CCR3=1100;
						else if(Oil_En_Flag==1)  htim3.Instance->CCR3=1850;
				
					HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,0);   //GPIO_PIN_14  管理点火
						
					HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,1); 
					}	
	
		 		if(Laser_En_Flag==1) HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,1);
     else if(Laser_En_Flag==0)	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,0);						
				}	 
//接受来自CAN设备2的数据
				 else   if (RXHeader.ExtId ==0x00002014)
				 {	 
					if (RXmessage[7]!=RXmessage[0]+RXmessage[1]+RXmessage[2] +RXmessage[3] +RXmessage[4]+RXmessage[5] +RXmessage[6])  return;    //校验

						printf("Can_Recive_Step1:DataCrc16 Passed\r\n"); 
		//				Oil_En_Flag=(RXmessage[2]&0x01)>>0;           //00000001
		//				Spitfire_En_Flag=(RXmessage[2]&0x02)>>1;      //00000010
		//				Laser_En_Flag=(RXmessage[2]&0x04)>>2;
					if(RXmessage[0]==0x01)
					{
						CAN_Send_Msg(0x00002015,TXmessage3,8);
					}		
				}					
				
	  }
}

判断 if (RXHeader.ExtId ==0x00004710)
这样就可以实现接受不同的扩展帧ID处理不同的数据啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梁山1号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值