STM32+Cube mx hal库实现CAN通信收发实验

      关于CAN通信的入门教程和基本原理在其他博主发的文章里面都有介绍,笔者只是简单记录下学习过程,文章用到的是正点原子的阿波罗F429开发板,另一个设备是中盛科技的继电器模块(CAN版)。

      实现之前看一下继电器模块相关信息

STM32+Cube mx hal库实现CAN通信收发实验_第1张图片

 STM32+Cube mx hal库实现CAN通信收发实验_第2张图片

       发送数据的格式官方文档已经给与说明,帧ID的格式就是功能码+地址码,地址码默认是0x01,例如想让继电器由闭合转为断开状态,只需要向继电器模块发送0x0101(写继电器状态功能码+默认地址码) 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00即可。

       然后打开Cube开始简单配置

1.CAN功能引脚选择PA11,PA12(对照开发板原理图),因为继电器模块默认波特率是250kbps,所以配置的一定要把波特率配好。时钟配置就默认流程

STM32+Cube mx hal库实现CAN通信收发实验_第3张图片

 

STM32+Cube mx hal库实现CAN通信收发实验_第4张图片

       另外配置了按键和LED作为提示

      代码部分:

can.c

void MX_CAN1_Init(void)
{

  /* USER CODE BEGIN CAN1_Init 0 */

  /* USER CODE END CAN1_Init 0 */

  /* USER CODE BEGIN CAN1_Init 1 */

  /* USER CODE END CAN1_Init 1 */
  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 36;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_3TQ;
  hcan1.Init.TimeSeg2 = CAN_BS2_1TQ;
  hcan1.Init.TimeTriggeredMode = DISABLE;
  hcan1.Init.AutoBusOff = DISABLE;
  hcan1.Init.AutoWakeUp = DISABLE;
  hcan1.Init.AutoRetransmission = DISABLE;
  hcan1.Init.ReceiveFifoLocked = DISABLE;
  hcan1.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CAN1_Init 2 */
	CAN_FilterTypeDef CAN_FilterInitStructure;
	
	CAN_FilterInitStructure.FilterBank = 0;
	CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK;
	CAN_FilterInitStructure.FilterScale = CAN_FILTERSCALE_32BIT;
	CAN_FilterInitStructure.FilterIdHigh = 0x0000;
	CAN_FilterInitStructure.FilterIdLow = 0x0000;
	CAN_FilterInitStructure.FilterMaskIdHigh = 0x0000;
	CAN_FilterInitStructure.FilterMaskIdLow = 0x0000;
	
	CAN_FilterInitStructure.FilterFIFOAssignment = CAN_FilterFIFO0;
	CAN_FilterInitStructure.FilterActivation = ENABLE;
	
	HAL_CAN_ConfigFilter(&hcan1,&CAN_FilterInitStructure);
	HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
  /* USER CODE END CAN1_Init 2 */

}

      因为Cube并不会帮我们生成筛选器配置的相关代码,所以我们要在初始化-用户代码区域自己添加代码

main.c

/*CAN发送*/
void CAN_SEND(void)
{

	CAN_TxHeaderTypeDef CAN_TX;
	uint32_t TX_MAILBOX;
	uint8_t TX_DATA[8] = {0x03,0x00,0x00,0x00,0x00,0xf0,0x00,0x00};//继电器模块
    //手册有说明,该段表示1-2号继电器得电,45-48号继电器得电。
	
	
	
	CAN_TX.DLC = 8;
	CAN_TX.ExtId = 0x0000;
	CAN_TX.StdId = 0x0101;//标准帧ID
	CAN_TX.IDE = CAN_ID_STD;//标准帧
	CAN_TX.RTR = CAN_RTR_DATA;//数据帧
	CAN_TX.TransmitGlobalTime = DISABLE;
	
	HAL_CAN_AddTxMessage(&hcan1,&CAN_TX,TX_DATA,&TX_MAILBOX);
}

/*CAN接收*/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan1)
{	

   CAN_RxHeaderTypeDef  RxMessage;
   uint8_t Data[2];
	
   RxMessage.DLC = 2;
   RxMessage.StdId = 0x00;
   RxMessage.ExtId = 0x0000;
   RxMessage.IDE=CAN_ID_EXT;
   RxMessage.RTR=CAN_RTR_DATA;
	 if (HAL_CAN_GetState(hcan1)!= RESET)
	 {
		 HAL_CAN_GetRxMessage(hcan1, CAN_RX_FIFO0, &RxMessage, Data);    			
		 
		 if (Data[0] == 0x99) 
		 {
			 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
            //第一位数据是0x99,LED灭
		 }
		 if(Data[1] == 0x99)
		 {
			 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
            //第二位数据是0x99,LED亮
		 }
		 
   }
 
}

      不需要写在大循环里,每次发送按下复位就行。

STM32+Cube mx hal库实现CAN通信收发实验_第5张图片

因为只需要控制继电器模块,所以按照使用手册来修改或添加发送的数据就行了。

本文只用于记录,工程文档不一定具有参考意义。

你可能感兴趣的:(stm32,单片机,嵌入式硬件)