STM32 HAL CAN应用

本文使用的STMCube库为STM32Cube FW_F1 V1.8.0版本。不同版本的HAL库使用上有一些的差异。

具体的CAN物理层和通讯协议等建议先找资料了解一下(ISO 11898),这里只讲快速应用。

网上关于协议讲解的很多,例如:https://www.cnblogs.com/pejoicen/p/3986587.html

1. STM32 CubeMX 配置

首先安装STM32CubeMX,然后选择你使用的MCU型号和封装:

配置一下外部晶振和调试下载方式

STM32 HAL CAN应用_第1张图片

STM32 HAL CAN应用_第2张图片

配置一下APB1 外设时钟,CAN使用的是这个外设时钟。

STM32 HAL CAN应用_第3张图片

STM32 使用的是BxCAN,支持CAN2.0 A和 CAN2.0 B(也就是标准帧和拓展帧都支持),HAL库主要需要配置的是CAN的位特性(包括CAN速率和CAN采样点,在Cube配置)和CAN硬件过滤组(在工程中自行配置)两个。

下图是Cube配置 CAN的位特性:

STM32 HAL CAN应用_第4张图片

这里我配置的是500Kbps的速率,其他默认即可(默认模式为正常模式)。配置速率的计算方式为 :

CANbps = APB / ( Prescaler * ( Segment1 + Segment2 + JumpWith))

APB1时钟记为APB,本例中为36MHz->36 000 000,

Prescaler 为时钟分频 这里设为 8,

剩下三个参数遵循 Segment1 ≈ Segment2 > JumpWith, 一般 JumpWith取1即可,

例子中算式为  36 000 000 / ( 8 * ( 4 + 4 +1 )) = 500 000 bps -> 500K bps。

STM32 HAL CAN应用_第5张图片

使能并配置CAN接收中断(这里只提供一种接收方法)。

修改并配置CAN的引脚位置至你需要的引脚(不赘述)。

最后在project manager里面生成你想要的工程即可。

2. 工程内配置

这里主要配置的是 CAN的硬件过滤器 和 中断接收函数 。本例中使用的是单CAN的芯片,若是双CAN 稍作修改即可。

每一份HAL的库都自带使用说明,位于对应 .C 文件头部,建议开发前详细阅读,这是通用的不管HAL怎么都可以按图索骥。

STM32 HAL CAN应用_第6张图片

初始化

在系统的CAN初始化好了之后  添加硬件过滤器和激活CAN接收中断回调函数即可使用。

//CAN filter and RX_IT init
void CAN_User_Init(CAN_HandleTypeDef *h_can) 
{
  CAN_FilterTypeDef sFilterConfig;
  HAL_StatusTypeDef HAL_Status;

  TxMeg.IDE = CAN_ID_STD; 
  TxMeg.RTR = CAN_RTR_DATA;
  sFilterConfig.FilterBank = 0;   //chenal 0
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;   //mask mode
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x0000; 
  sFilterConfig.FilterIdLow = 0x0000;
  //MASK bit 0 means don't care,bit 0 means match 
  sFilterConfig.FilterMaskIdHigh = 0x0000;
  sFilterConfig.FilterMaskIdLow = 0x0000;    
  sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; 
  sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;   //enable filter
  sFilterConfig.SlaveStartFilterBank = 14;    //single CAN meaningless para
  HAL_Status = HAL_CAN_ConfigFilter(h_can, &sFilterConfig);
  if (HAL_Status != HAL_OK)
  {
    printf("Filter init failed\r\n");
  }
  HAL_Status = HAL_CAN_Start(h_can); //start CAN
  if (HAL_Status != HAL_OK)
  {
    printf("CAN init failed\r\n");
  }
  //regist RX_IT
  HAL_Status = HAL_CAN_ActivateNotification(h_can, CAN_IT_RX_FIFO0_MSG_PENDING);
  if (HAL_Status != HAL_OK)
  {
    printf("CAN activate failed\r\n");
  }
}

上图设置的是CAN 接收全部ID信息 的硬件过滤器通道0的屏蔽模式设置。过滤器可以使用列表模式和屏蔽模式,相应的可以自己查一下概念资料和手册。

STM32 HAL CAN应用_第7张图片

接收数据

接下来是回调函数的处理,上面注册了 CAN_IT_RX_FIFO0_MSG_PENDING 对应的回调函数原型是 void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *h_can);

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *h_can)
{
  uint8_t Data[9]={0};

  HAL_StatusTypeDef HAL_RetVal;
  if (h_can == &hcan)
  {
    //retrive data by calling HAL_CAN_GetRxMessage
    HAL_RetVal = HAL_CAN_GetRxMessage(&hcan, CAN1FIFO, &RxMeg, Data);
  }
  
}

在回调函数中调用 HAL_CAN_GetRxMessage 即可获取接收到的CAN数据。

发送数据

发送数据前要先查询 BxCAN的发送邮箱是否有位置。 调用 HAL_CAN_GetTxMailboxesFreeLevel(&hcan); 即可返回。

确认有空邮箱之后,调用HAL_CAN_AddTxMessage HAL库会自动帮你发送信息。

uint32_t TxBox = CAN_TX_MAILBOX0;
HAL_RetVal = HAL_CAN_AddTxMessage(&hcan, &TxMeg, pData + SendCNT, (uint32_t *)&TxBox);

结束

硬件相关:CAN要在通讯的两线之间加终端电阻,即便是一对一通讯也要加120Ω,否则通讯会有问题。

至此你就可以测试CAN的收发。

本文只是快速应用,具体深入了解还需要阅读CAN标准和芯片手册等资料。

你可能感兴趣的:(其他)