【通讯协议备忘录】stm32的CAN外设

文章目录

  • 帧结构
  • 测试模式(静默/换回/环回静默):
    • 环回测试配置
  • 过滤器的使用
  • 测试参考用例
    • 过滤器的初始化
    • 发送和接收
  • 中断

帧结构

  • CAN的报文结构:
    【通讯协议备忘录】stm32的CAN外设_第1张图片

测试模式(静默/换回/环回静默):

  • 静默模式:
    【通讯协议备忘录】stm32的CAN外设_第2张图片
  • 环回模式:
    在这里插入图片描述
    【通讯协议备忘录】stm32的CAN外设_第3张图片
  • 环回静默模式:
    【通讯协议备忘录】stm32的CAN外设_第4张图片

环回测试配置

  • 选好对应GPIO即可,APB1 36 Mhz, 500kbps:
    【通讯协议备忘录】stm32的CAN外设_第5张图片

过滤器的使用

  • 不配置过滤器亦可使用
  • 根据不同位长模式,每个过滤器组,32位模式可以配置一个屏蔽掩码或两个白名单列表,16位模式翻倍
  • 标准帧和扩展帧的ID长度分别为11比特和29比特,通过移位操作对齐其对应的高低位
    【通讯协议备忘录】stm32的CAN外设_第6张图片

测试参考用例

过滤器的初始化

  • cube不能配置过滤器,需要手动配置,直接添加到生成代码的自定义区即可
  • 初始化后需要手动打开CAN外设
  • 单机测试使用了环回模式
static void MX_CAN_Init(void)
{

  /* USER CODE BEGIN CAN_Init 0 */

  /* USER CODE END CAN_Init 0 */

  /* USER CODE BEGIN CAN_Init 1 */

  /* USER CODE END CAN_Init 1 */
  hcan.Instance = CAN1;
  hcan.Init.Prescaler = 4;
  hcan.Init.Mode = CAN_MODE_LOOPBACK;
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan.Init.TimeSeg1 = CAN_BS1_9TQ;
  hcan.Init.TimeSeg2 = CAN_BS2_8TQ;
  hcan.Init.TimeTriggeredMode = DISABLE;
  hcan.Init.AutoBusOff = DISABLE;
  hcan.Init.AutoWakeUp = DISABLE;
  hcan.Init.AutoRetransmission = DISABLE;
  hcan.Init.ReceiveFifoLocked = DISABLE;
  hcan.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CAN_Init 2 */
  //接收所有
	CAN_FilterTypeDef can_filterconfig;
	can_filterconfig.FilterMode = CAN_FILTERMODE_IDMASK;
	can_filterconfig.FilterScale = CAN_FILTERSCALE_32BIT;
	can_filterconfig.FilterIdHigh = 0;
	can_filterconfig.FilterIdLow = 0;
	can_filterconfig.FilterMaskIdHigh = 0;
	can_filterconfig.FilterMaskIdLow = 0;
	can_filterconfig.FilterBank = 0;
	can_filterconfig.FilterFIFOAssignment = CAN_FilterFIFO0;
	can_filterconfig.FilterActivation = CAN_FILTER_ENABLE;
	can_filterconfig.SlaveStartFilterBank = 14;
	HAL_CAN_ConfigFilter(&hcan, &can_filterconfig);
	
	HAL_CAN_Start(&hcan);
  /* USER CODE END CAN_Init 2 */
}

发送和接收

uint8_t can_send_message(CAN_TxHeaderTypeDef TxHeader,uint32_t std_id, uint8_t aData[],uint16_t lengh)
{
  uint32_t TxMailBox = CAN_TX_MAILBOX0;
  uint8_t FreeTxMailBoxNum = 0;
 
  TxHeader.StdId = std_id; 			//id由IDE决定类型
  TxHeader.ExtId = 0; 				
  TxHeader.DLC = lengh;  			//数据长度
  TxHeader.IDE = CAN_ID_STD;   		//标准帧/扩展帧
  TxHeader.RTR = CAN_RTR_DATA; 		//数据帧
  TxHeader.TransmitGlobalTime = DISABLE;
 
  while(0 == FreeTxMailBoxNum)
  {
   FreeTxMailBoxNum = HAL_CAN_GetTxMailboxesFreeLevel(&hcan);
  }
 
  if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, aData, &TxMailBox) != HAL_OK)
  {
    /* Transmission request Error */
    Error_Handler();
  }
 return 1;
}

uint8_t can_receive_message(uint8_t *buf)
{
	if(HAL_CAN_GetRxFifoFillLevel(&hcan,CAN_RX_FIFO0) == 0)
		return 0;
	
	HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &canRxType, buf);
	return canRxType.DLC;
}

中断

【通讯协议备忘录】stm32的CAN外设_第7张图片
四个中断源分别对应cube的四个选项:
【通讯协议备忘录】stm32的CAN外设_第8张图片
手动中断开启函数:

	HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING);

中断回调函数:

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan->Instance == CAN1)
	{
		HAL_CAN_GetRxMessage(&hcan, CAN_FILTER_FIFO0,&canRxType,canRxbuf);
	}
}

你可能感兴趣的:(单片机,stm32,CAN)