加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

STM32 CAN/CANFD軟件快速配置(HAL庫(kù)版本)

04/02 08:04
1.4萬(wàn)
閱讀需 38 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

控制器局域網(wǎng)總線(CAN,Controller Area Network)是一種用于實(shí)時(shí)應(yīng)用的串行通訊協(xié)議總線,它可以使用雙絞線來(lái)傳輸信號(hào),是世界上應(yīng)用最廣泛的現(xiàn)場(chǎng)總線之一。CAN協(xié)議用于汽車中各種不同元件之間的通信,以此取代昂貴而笨重的配電線束。該協(xié)議的健壯性使其用途延伸到其他自動(dòng)化和工業(yè)應(yīng)用。CAN協(xié)議的特性包括完整性的串行數(shù)據(jù)通訊、提供實(shí)時(shí)支持、傳輸速率高達(dá)1Mb/s、同時(shí)具有11位的尋址以及檢錯(cuò)能力。

特別說(shuō)明:關(guān)于CAN總線協(xié)議和硬件電路,CANFD和CAN的區(qū)別等問(wèn)題,這里不做介紹,網(wǎng)上的資料非常多,不懂的同學(xué)請(qǐng)自行查閱。

1 軟件編程

1.1 建立工程

要建立一個(gè)HAL庫(kù)版本的工程可以直接使用其他項(xiàng)目的HAL工程,也可以通過(guò)移植HAL固件庫(kù)或者用STM32CubeMX生成。

我這里以STM32G0為例講解一下如何用STM32CubeMX生成一個(gè)工程。

特別說(shuō)明:如果不使用STM32CubeMX工具,可以跳過(guò)以下步驟,直接從1.2開(kāi)始,把CANFD相關(guān)代碼加入其他HAL工程即可。

1、配置時(shí)鐘

我這里使用外部晶振時(shí)鐘(HSE),8M晶振倍頻到64M時(shí)鐘。

在這里插入圖片描述
在這里插入圖片描述

2、配置引腳

選擇自己實(shí)際使用的引腳作為CAN_TX和CAN_RX。

在這里插入圖片描述

3、配置CAN參數(shù)

我這里用CAN1作為CANFD,CAN2作為普通CAN。

CAN1配置參考如下:

特別說(shuō)明:以下數(shù)據(jù)僅供參考,請(qǐng)根據(jù)實(shí)際情況配置。

在這里插入圖片描述

CAN2配置參考如下:

特別說(shuō)明:以下數(shù)據(jù)僅供參考,請(qǐng)根據(jù)實(shí)際情況配置。

在這里插入圖片描述

最后使能中斷(注:CAN1和CAN2可以共用一個(gè)中斷接口)。

在這里插入圖片描述

4、生成工程

請(qǐng)?zhí)砑訄D片描述

1.2 初始化

初始化主要分成三部分:引腳設(shè)置,CAN參數(shù)設(shè)置和CAN濾波器設(shè)置。

1.2.1 引腳設(shè)置

把CAN_H和CAN_L兩個(gè)引腳配置成復(fù)用功能即可。

注:如果CAN控制芯片的S引腳連接到STM32的話,還得初始化這個(gè)引腳,S引腳可以配置成高速模式或靜音模式。

參考代碼:

注:該代碼可以通過(guò)STM32CubeMX生成

static uint32_t HAL_RCC_FDCAN_CLK_ENABLED=0;

void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* fdcanHandle)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  if(fdcanHandle->Instance==FDCAN1)
  {
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
    PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1;

    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

    /* FDCAN1 clock enable */
    HAL_RCC_FDCAN_CLK_ENABLED++;
    if(HAL_RCC_FDCAN_CLK_ENABLED==1){
      __HAL_RCC_FDCAN_CLK_ENABLE();
    }

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**FDCAN1 GPIO Configuration
    PB8     ------> FDCAN1_RX
    PB9     ------> FDCAN1_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* FDCAN1 interrupt Init */
    HAL_NVIC_SetPriority(TIM16_FDCAN_IT0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM16_FDCAN_IT0_IRQn);
  }
  else if(fdcanHandle->Instance==FDCAN2)
  {
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
    PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1;

    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

    /* FDCAN2 clock enable */
    HAL_RCC_FDCAN_CLK_ENABLED++;
    if(HAL_RCC_FDCAN_CLK_ENABLED==1){
      __HAL_RCC_FDCAN_CLK_ENABLE();
    }

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**FDCAN2 GPIO Configuration
    PB5     ------> FDCAN2_RX
    PB6     ------> FDCAN2_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* FDCAN2 interrupt Init */
    HAL_NVIC_SetPriority(TIM16_FDCAN_IT0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM16_FDCAN_IT0_IRQn);
  }
}
1.2.2 CAN基本參數(shù)設(shè)置

HAL庫(kù)的CAN初始化有幾個(gè)重要參數(shù),都存放在幾個(gè)結(jié)構(gòu)體里面(如:CAN_HandleTypeDef,CAN_InitTypeDef),具體的結(jié)構(gòu)體定義可以在HAL庫(kù)查看。

說(shuō)明:CAN參數(shù)需要根據(jù)自己實(shí)際的需求來(lái)配。

我這里著重講解一下CAN波特率的配置。

CAN波特率 = CAN時(shí)鐘頻率 / 時(shí)鐘分頻 / 預(yù)分頻系數(shù) / (TimeSeg1 + TimeSeg2 + 1)。

其中,CAN時(shí)鐘頻率不是固定不變的,它取決于CAN所掛載的總線時(shí)鐘。

比如STM32F1,系統(tǒng)時(shí)鐘最大72M,APB1的總線時(shí)鐘最大36M,而CAN控制器的時(shí)鐘是掛在APB1的,所以CAN的時(shí)鐘頻率也等于APB1的時(shí)鐘。

如果換作其他型號(hào)的MCU,CAN外設(shè)不一定是掛載到APB1上面的,時(shí)鐘也不一定是36M,比如F4系列,APB1的時(shí)鐘是可以配成42M的,因此,這個(gè)要根據(jù)實(shí)際情況來(lái)配置。

本例用的是STM32G0,CAN時(shí)鐘頻率配置為64MHz。

參考代碼:

注:該代碼可以通過(guò)STM32CubeMX生成

FDCAN_HandleTypeDef hfdcan1;
FDCAN_HandleTypeDef hfdcan2;

/* FDCAN1 init function */
void MX_FDCAN1_Init(void)
{
  /* USER CODE END FDCAN1_Init 1 */
  // CAN波特率 = 時(shí)鐘頻率 / 時(shí)鐘分頻  / 預(yù)分頻系數(shù) / (1 + TSG1 + TSG2) 
  // 仲裁段波特率 = 64M / 1 / 8 / (1 + 10 + 5) = 500k
  // 數(shù)據(jù)段波特率 = 64M / 1 / 2 / (1 + 10 + 5) = 2M
  hfdcan1.Instance = FDCAN1;                               // FDCAN1
  hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;            // 時(shí)鐘分頻               
  hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS;           // 配置為CANFD         
  hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;                   // 正常工作狀態(tài)       
  hfdcan1.Init.AutoRetransmission = DISABLE;               // 關(guān)閉自動(dòng)重傳, 傳統(tǒng)模式下需關(guān)閉           
  hfdcan1.Init.TransmitPause = DISABLE;                    // 關(guān)閉傳輸暫停      
  hfdcan1.Init.ProtocolException = DISABLE;                // 關(guān)閉協(xié)議異常處理          
  hfdcan1.Init.NominalPrescaler = 8;                       // 仲裁段時(shí)鐘分頻,傳統(tǒng)CAN模式時(shí)只設(shè)置這一段即可   
  hfdcan1.Init.NominalSyncJumpWidth = 1;                   // 仲裁段同步跳轉(zhuǎn)段的寬度                      
  hfdcan1.Init.NominalTimeSeg1 = 10;                       // 仲裁段時(shí)間段1                      
  hfdcan1.Init.NominalTimeSeg2 = 5;                        // 仲裁段時(shí)間段2                     
  hfdcan1.Init.DataPrescaler = 2;                          // 數(shù)據(jù)段時(shí)鐘分頻,若工作于傳統(tǒng)模式,不需要設(shè)置數(shù)據(jù)段參數(shù)
  hfdcan1.Init.DataSyncJumpWidth = 1;                      // 數(shù)據(jù)段同步跳轉(zhuǎn)段的寬度   
  hfdcan1.Init.DataTimeSeg1 = 10;                          // 數(shù)據(jù)段時(shí)間段1           
  hfdcan1.Init.DataTimeSeg2 = 5;                           // 數(shù)據(jù)段時(shí)間段2           
  hfdcan1.Init.StdFiltersNbr = 28;                         // 標(biāo)準(zhǔn)幀濾波器數(shù)量 
  hfdcan1.Init.ExtFiltersNbr = 8;                          // 擴(kuò)展幀濾波器數(shù)量 
  hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;  // 發(fā)送模式:先入先出   
  if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
  {
    Error_Handler();
  }
}
/* FDCAN2 init function */
void MX_FDCAN2_Init(void)
{
  /* USER CODE END FDCAN2_Init 1 */
  // CAN波特率 = 時(shí)鐘頻率 / 時(shí)鐘分頻 / 預(yù)分頻系數(shù) / (1 + TSG1 + TSG2) = 64M / 1 / 8 / (1 + 10 + 5) = 500k
  hfdcan2.Instance = FDCAN2;                               // FDCAN2
  hfdcan2.Init.ClockDivider = FDCAN_CLOCK_DIV1;            // 時(shí)鐘分頻 
  hfdcan2.Init.FrameFormat = FDCAN_FRAME_CLASSIC;          // 配置為傳統(tǒng)模式    
  hfdcan2.Init.Mode = FDCAN_MODE_NORMAL;                   // 正常工作狀態(tài)
  hfdcan2.Init.AutoRetransmission = DISABLE;               // 關(guān)閉自動(dòng)重傳, 傳統(tǒng)模式下需關(guān)閉
  hfdcan2.Init.TransmitPause = DISABLE;                    // 關(guān)閉傳輸暫停
  hfdcan2.Init.ProtocolException = DISABLE;                // 關(guān)閉協(xié)議異常處理
  hfdcan2.Init.NominalPrescaler = 8;                       // 仲裁段時(shí)鐘分頻,傳統(tǒng)CAN模式時(shí)只設(shè)置這一段即可
  hfdcan2.Init.NominalSyncJumpWidth = 1;                   // 仲裁段同步跳轉(zhuǎn)段的寬度               
  hfdcan2.Init.NominalTimeSeg1 = 10;                       // 仲裁段時(shí)間段1                   
  hfdcan2.Init.NominalTimeSeg2 = 5;                        // 仲裁段時(shí)間段2                   
  hfdcan2.Init.DataPrescaler = 8;                          // 數(shù)據(jù)段時(shí)鐘分頻,若工作于傳統(tǒng)模式,不需要設(shè)置數(shù)據(jù)段參數(shù)
  hfdcan2.Init.DataSyncJumpWidth = 1;                      // 數(shù)據(jù)段同步跳轉(zhuǎn)段的寬度
  hfdcan2.Init.DataTimeSeg1 = 10;                          // 數(shù)據(jù)段時(shí)間段1           
  hfdcan2.Init.DataTimeSeg2 = 5;                           // 數(shù)據(jù)段時(shí)間段2           
  hfdcan2.Init.StdFiltersNbr = 28;                         // 標(biāo)準(zhǔn)幀濾波器數(shù)量
  hfdcan2.Init.ExtFiltersNbr = 8;                          // 擴(kuò)展幀濾波器數(shù)量
  hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;  // 發(fā)送模式:先入先出                  
  if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK)
  {
    Error_Handler();
  }
}
1.2.3 CAN收發(fā)初始化設(shè)置

CAN接收需要設(shè)置CAN濾波器,它的主要作用是篩選CAN接收的數(shù)據(jù),只有滿足設(shè)定規(guī)則的數(shù)據(jù)才會(huì)被接收,否則會(huì)被過(guò)濾掉。

而CAN發(fā)送則需要在發(fā)送一條數(shù)據(jù)前,先配置好這條數(shù)據(jù)的信息,如CANID,發(fā)送長(zhǎng)度,數(shù)據(jù)類型(CAN/CANFD)等等。

參考代碼:

FDCAN_TxHeaderTypeDef TxHeader1;
FDCAN_RxHeaderTypeDef RxHeader1;
FDCAN_TxHeaderTypeDef TxHeader2;
FDCAN_RxHeaderTypeDef RxHeader2;
void FDCAN1_Config(void)
{
  FDCAN_FilterTypeDef sFilterConfig;
  /* Configure Rx filter */
  sFilterConfig.IdType = FDCAN_STANDARD_ID;
  sFilterConfig.FilterIndex = 1;
  sFilterConfig.FilterType = FDCAN_FILTER_RANGE;
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
  sFilterConfig.FilterID1 = 0x00000000;
  sFilterConfig.FilterID2 = 0x000007FF;
  if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }

  sFilterConfig.IdType = FDCAN_EXTENDED_ID;
  sFilterConfig.FilterIndex = 0;
  sFilterConfig.FilterType = FDCAN_FILTER_RANGE;
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
  sFilterConfig.FilterID1 = 0x00000000;
  sFilterConfig.FilterID2 = 0x1FFFFFFF;
  if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /* Configure global filter:
     Filter all remote frames with STD and EXT ID
     Reject non matching frames with STD ID and EXT ID */
  if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
  {
    Error_Handler();
  }

  /* Activate Rx FIFO 0 new message notification on both FDCAN instances */
  if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
  {
    Error_Handler();
  }

  // if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_BUS_OFF, 0) != HAL_OK)
  // {
  //   Error_Handler();
  // }

  /* Tx Config*/
  TxHeader1.Identifier = 0x000000000;                 // CAN ID
  TxHeader1.IdType = FDCAN_STANDARD_ID;               // 標(biāo)準(zhǔn)ID
  TxHeader1.TxFrameType = FDCAN_DATA_FRAME;           
  TxHeader1.DataLength = FDCAN_DLC_BYTES_8;
  TxHeader1.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
  TxHeader1.BitRateSwitch = FDCAN_BRS_OFF;
  TxHeader1.FDFormat = FDCAN_FD_CAN;                  // CANFD
  TxHeader1.TxEventFifoControl = FDCAN_NO_TX_EVENTS;  
  TxHeader1.MessageMarker = 0;

  /* Configure and enable Tx Delay Compensation, required for BRS mode.
        TdcOffset default recommended value: DataTimeSeg1 * DataPrescaler
        TdcFilter default recommended value: 0 */
  HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan1, hfdcan1.Init.DataPrescaler * hfdcan1.Init.DataTimeSeg1, 0);
  HAL_FDCAN_EnableTxDelayCompensation(&hfdcan1);
  
  /* Start the FDCAN module */
  if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
  {
    Error_Handler();
  }
}

void FDCAN2_Config(void)
{
  FDCAN_FilterTypeDef sFilterConfig;
  /* Configure Rx filter */
  sFilterConfig.IdType = FDCAN_STANDARD_ID;
  sFilterConfig.FilterIndex = 1;
  sFilterConfig.FilterType = FDCAN_FILTER_RANGE;
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
  sFilterConfig.FilterID1 = 0x00000000;
  sFilterConfig.FilterID2 = 0x000007FF;
  if (HAL_FDCAN_ConfigFilter(&hfdcan2, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }

  sFilterConfig.IdType = FDCAN_EXTENDED_ID;
  sFilterConfig.FilterIndex = 0;
  sFilterConfig.FilterType = FDCAN_FILTER_RANGE;
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
  sFilterConfig.FilterID1 = 0x00000000;
  sFilterConfig.FilterID2 = 0x1FFFFFFF;
  if (HAL_FDCAN_ConfigFilter(&hfdcan2, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /* Configure global filter:
     Filter all remote frames with STD and EXT ID
     Reject non matching frames with STD ID and EXT ID */
  if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan2, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
  {
    Error_Handler();
  }

  /* Activate Rx FIFO 0 new message notification on both FDCAN instances */
  if (HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
  {
    Error_Handler();
  }

  // if (HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_BUS_OFF, 0) != HAL_OK)
  // {
  //   Error_Handler();
  // }

  /* Tx Config*/
  TxHeader2.Identifier = 0x000000000;                 // CAN ID
  TxHeader2.IdType = FDCAN_STANDARD_ID;               // 標(biāo)準(zhǔn)ID
  TxHeader2.TxFrameType = FDCAN_DATA_FRAME;           
  TxHeader2.DataLength = FDCAN_DLC_BYTES_8;
  TxHeader2.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
  TxHeader2.BitRateSwitch = FDCAN_BRS_OFF;
  TxHeader2.FDFormat = FDCAN_CLASSIC_CAN;             // CAN
  TxHeader2.TxEventFifoControl = FDCAN_NO_TX_EVENTS;  
  TxHeader2.MessageMarker = 0;

  /* Configure and enable Tx Delay Compensation, required for BRS mode.
        TdcOffset default recommended value: DataTimeSeg1 * DataPrescaler
        TdcFilter default recommended value: 0 */
  HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan2, hfdcan2.Init.DataPrescaler * hfdcan2.Init.DataTimeSeg1, 0);
  HAL_FDCAN_EnableTxDelayCompensation(&hfdcan2);

  /* Start the FDCAN module */
  if (HAL_FDCAN_Start(&hfdcan2) != HAL_OK)
  {
    Error_Handler();
  }
}

1.2.4 中斷設(shè)置

如果使用CAN接收,需要配置中斷服務(wù)函數(shù)。

參考代碼:

/**
  * @brief This function handles TIM16, FDCAN1_IT0 and FDCAN2_IT0 Interrupt.
  */
void TIM16_FDCAN_IT0_IRQHandler(void)
{
  HAL_FDCAN_IRQHandler(&hfdcan1);
  HAL_FDCAN_IRQHandler(&hfdcan2);
}

1.3 CAN發(fā)送

CAN發(fā)送需要先配置發(fā)送參數(shù),我這里為了方便測(cè)試,直接固定發(fā)送標(biāo)準(zhǔn)幀,ID也是固定的。

實(shí)際使用時(shí)可以把CANID,數(shù)據(jù)長(zhǎng)度等參數(shù)作為函數(shù)入?yún)?,這樣會(huì)更靈活一點(diǎn)。

參考代碼:

void canfd_tx_test(void)
{
  TxHeader1.Identifier = 0x123;                 // CAN ID
  TxHeader1.IdType = FDCAN_STANDARD_ID;         // 標(biāo)準(zhǔn)ID
  TxHeader1.TxFrameType = FDCAN_DATA_FRAME;           
  TxHeader1.DataLength = FDCAN_DLC_BYTES_8;     // 發(fā)送長(zhǎng)度:8byte
  TxHeader1.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
  TxHeader1.BitRateSwitch = FDCAN_BRS_OFF;
  TxHeader1.FDFormat = FDCAN_FD_CAN;            // CANFD
  TxHeader1.TxEventFifoControl = FDCAN_NO_TX_EVENTS;  
  TxHeader1.MessageMarker = 0;

  if(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader1, can1_txbuf) != HAL_OK)
  {
    Error_Handler();
  }
}

1.4 CAN接收

接收部分只要開(kāi)啟了Rx中斷,在CAN控制器收到消息時(shí)會(huì)調(diào)用RxFifo的回調(diào)函數(shù),此時(shí)在這里讀取數(shù)據(jù)并根據(jù)實(shí)際情況做相應(yīng)的處理即可。我這里把收到的數(shù)據(jù)又發(fā)回去了,這樣可以同時(shí)驗(yàn)證接收和發(fā)送。

參考代碼:

void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
  if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
  {
    if(hfdcan->Instance == FDCAN1)
    {
      /* Retrieve Rx messages from RX FIFO0 */
      if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, can1_rxbuf) != HAL_OK)
      {
        Error_Handler();
      }
      /* 把接收到的數(shù)據(jù)以CANFD發(fā)送回去 */
      TxHeader1.DataLength = RxHeader1.DataLength;
      TxHeader1.Identifier = RxHeader1.Identifier;
      if(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader1, can1_rxbuf) != HAL_OK)
      {
        Error_Handler();
      }
    }

    if(hfdcan->Instance == FDCAN2)
    {
      /* Retrieve Rx messages from RX FIFO0 */
      if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, can2_rxbuf) != HAL_OK)
      {
        Error_Handler();
      }
      /* 把接收到的數(shù)據(jù)以CAN發(fā)送回去 */
      TxHeader2.DataLength = RxHeader2.DataLength;
      TxHeader2.Identifier = RxHeader2.Identifier;
      if(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan2, &TxHeader2, can2_rxbuf) != HAL_OK)
      {
        Error_Handler();
      }
    }
  }
}

2 運(yùn)行測(cè)試

使用USB-CAN工具測(cè)試。

CAN1使用CANFD(仲裁域波特率500k,數(shù)據(jù)域波特率2M),上位機(jī)每發(fā)送一條數(shù)據(jù),STM32收到后同樣回一條一樣的數(shù)據(jù),CANID、數(shù)據(jù)長(zhǎng)度和數(shù)據(jù)都是一致,說(shuō)明STM32收到的數(shù)據(jù)沒(méi)有問(wèn)題。

在這里插入圖片描述

CAN2使用普通CAN(仲裁域和數(shù)據(jù)域波特率均為500k),上位機(jī)每發(fā)送一條數(shù)據(jù),STM32收到后同樣回一條一樣的數(shù)據(jù),CANID、數(shù)據(jù)長(zhǎng)度和數(shù)據(jù)都是一致,說(shuō)明STM32收到的數(shù)據(jù)沒(méi)有問(wèn)題。

在這里插入圖片描述

還有一些其他測(cè)試,比如切換擴(kuò)展幀,遠(yuǎn)程幀等等,這里就不展示了,感興趣的同學(xué)可以自己改參數(shù)試試。

結(jié)論:CAN收發(fā)正常。

結(jié)束語(yǔ)

好了,關(guān)于如何通過(guò)STM32如何配置和使用CANFD就講到這里,如果你有什么問(wèn)題或者有更好的方法,歡迎在評(píng)論區(qū)留言。

需要源碼工程的同學(xué)可以自行下載:點(diǎn)擊跳轉(zhuǎn)下載鏈接

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
MOCD207R2M 1 Fairchild Semiconductor Corporation Transistor Output Optocoupler, 2-Element, 2500V Isolation, LEAD FREE, PLASTIC, SOIC-8
$1.16 查看
DS24B33S+T&R 1 Maxim Integrated Products EEPROM, 4KX1, Serial, CMOS, PDSO8, 0.208 INCH, ROHS COMPLIANT, SOP-8
$2.75 查看
AFBR-5715APZ 1 Broadcom Limited Transceiver, 830nm Min, 860nm Max, 1250Mbps(Tx), LC Connector, Panel Mount, ROHS COMPLIANT
暫無(wú)數(shù)據(jù) 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜