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型號和封裝:

配置一下外部晶振和調試下載方式

配置一下APB1 外設時鐘,CAN使用的是這個外設時鐘。

STM32 使用的是BxCAN,支持CAN2.0 A和 CAN2.0 B(也就是標準幀和拓展幀都支持),HAL庫主要需要配置的是CAN的位特性(包括CAN速率和CAN採樣點,在Cube配置)和CAN硬件過濾組(在工程中自行配置)兩個。

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

這裏我配置的是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。

使能並配置CAN接收中斷(這裏只提供一種接收方法)。

修改並配置CAN的引腳位置至你需要的引腳(不贅述)。

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

2. 工程內配置

這裏主要配置的是 CAN的硬件過濾器 和 中斷接收函數 。本例中使用的是單CAN的芯片,若是雙CAN 稍作修改即可。

每一份HAL的庫都自帶使用說明,位於對應 .C 文件頭部,建議開發前詳細閱讀,這是通用的不管HAL怎麼都可以按圖索驥。

初始化

在系統的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的屏蔽模式設置。過濾器可以使用列表模式和屏蔽模式,相應的可以自己查一下概念資料和手冊。

接收數據

接下來是回調函數的處理,上面註冊了 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標準和芯片手冊等資料。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章