当前位置:   article > 正文

FDCAN作为普通CAN使用(基于STM32G4)_stm32 canfd

stm32 canfd

1.FDCAN

        FDCAN为CAN的升级版,它拥有更高的速度由1Mbps上升到5Mbps,每帧数据段最大长度由8字节上升到64字节,同时最重要的是它向下兼容CAN。不过在FDCAN配置普通CAN通信与大家熟知的STMF1、F4等配置CAN不太一样。因此在此记录一下,在STM32CubeMX下配置FDCAN作为普通模式的CAN使用并通信。直接进入正题。

2.STM32CubeMX配置

        基于STM32G431CBT6芯片,具有170MHz的高频,也有FDCAN接口。首先常规配置时钟,达到最高170MHz。

        然后打开FDCAN配置窗口,配置中断和时间报段。选择1/8/8原因是170MHz高频下170MHz/1/(8+8+1),可以达到1Mbps速率。

        主要配置这些部分,Data Sync Jump Width、Data Time Seg1和Data Time Seg2默认不需要配置,因为这是FDCAN特有的功能,我们只使用传统CAN模式。同时记得在NVIC Settings上勾选上中断配置。

 配置完成就生成程序框架,下面我贴上CAN的代码,需要注意生成的代码只是框架,目前FDCAN还不能正常作为CAN使用。需要加入过滤器代码以及CAN发送接收等部分代码才能正常使用

  1. #include "fdcan.h"
  2. /* USER CODE BEGIN 0 */
  3. FDCAN_RxHeaderTypeDef fdcan1_RxHeader;
  4. FDCAN_TxHeaderTypeDef fdcan1_TxHeader;
  5. FDCAN_HandleTypeDef hfdcan1;
  6. /* USER CODE END 0 */
  7. FDCAN_HandleTypeDef hfdcan1;
  8. /* FDCAN1 init function */
  9. void MX_FDCAN1_Init(void)
  10. {
  11. /* USER CODE BEGIN FDCAN1_Init 0 */
  12. FDCAN_FilterTypeDef FDCAN1_RXFilter;
  13. /* USER CODE END FDCAN1_Init 0 */
  14. /* USER CODE BEGIN FDCAN1_Init 1 */
  15. /* USER CODE END FDCAN1_Init 1 */
  16. hfdcan1.Instance = FDCAN1;
  17. hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;
  18. hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
  19. hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
  20. hfdcan1.Init.AutoRetransmission = DISABLE;
  21. hfdcan1.Init.TransmitPause = DISABLE;
  22. hfdcan1.Init.ProtocolException = DISABLE;
  23. hfdcan1.Init.NominalPrescaler = 10;
  24. hfdcan1.Init.NominalSyncJumpWidth = 1;
  25. hfdcan1.Init.NominalTimeSeg1 = 8;
  26. hfdcan1.Init.NominalTimeSeg2 = 8;
  27. hfdcan1.Init.DataPrescaler = 1;
  28. hfdcan1.Init.DataSyncJumpWidth = 1;
  29. hfdcan1.Init.DataTimeSeg1 = 1;
  30. hfdcan1.Init.DataTimeSeg2 = 1;
  31. hfdcan1.Init.StdFiltersNbr = 0;
  32. hfdcan1.Init.ExtFiltersNbr = 0;
  33. hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
  34. if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
  35. {
  36. Error_Handler();
  37. }
  38. /* USER CODE BEGIN FDCAN1_Init 2 */
  39. FDCAN1_RXFilter.IdType=FDCAN_STANDARD_ID; //标准ID
  40. FDCAN1_RXFilter.FilterIndex=0; //滤波器索引
  41. FDCAN1_RXFilter.FilterType=FDCAN_FILTER_RANGE; //滤波器类型
  42. FDCAN1_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0; //过滤器0关联到FIFO0
  43. FDCAN1_RXFilter.FilterID1=0x0000; //32位ID
  44. FDCAN1_RXFilter.FilterID2=0x0000; //如果FDCAN配置为传统模式的话,这里是32位掩码
  45. if(HAL_FDCAN_ConfigFilter(&hfdcan1,&FDCAN1_RXFilter)!=HAL_OK) //滤波器初始化
  46. {
  47. Error_Handler();
  48. }
  49. HAL_FDCAN_Start(&hfdcan1); //开启FDCAN
  50. HAL_FDCAN_ActivateNotification(&hfdcan1,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
  51. /* USER CODE END FDCAN1_Init 2 */
  52. }
  53. void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* fdcanHandle)
  54. {
  55. GPIO_InitTypeDef GPIO_InitStruct = {0};
  56. RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  57. if(fdcanHandle->Instance==FDCAN1)
  58. {
  59. /* USER CODE BEGIN FDCAN1_MspInit 0 */
  60. /* USER CODE END FDCAN1_MspInit 0 */
  61. /** Initializes the peripherals clocks
  62. */
  63. PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
  64. PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1;
  65. if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  66. {
  67. Error_Handler();
  68. }
  69. /* FDCAN1 clock enable */
  70. __HAL_RCC_FDCAN_CLK_ENABLE();
  71. __HAL_RCC_GPIOA_CLK_ENABLE();
  72. /**FDCAN1 GPIO Configuration
  73. PA11 ------> FDCAN1_RX
  74. PA12 ------> FDCAN1_TX
  75. */
  76. GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
  77. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  78. GPIO_InitStruct.Pull = GPIO_NOPULL;
  79. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  80. GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1;
  81. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  82. /* FDCAN1 interrupt Init */
  83. HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 5, 0);
  84. HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
  85. /* USER CODE BEGIN FDCAN1_MspInit 1 */
  86. /* USER CODE END FDCAN1_MspInit 1 */
  87. }
  88. }
  89. void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* fdcanHandle)
  90. {
  91. if(fdcanHandle->Instance==FDCAN1)
  92. {
  93. /* USER CODE BEGIN FDCAN1_MspDeInit 0 */
  94. /* USER CODE END FDCAN1_MspDeInit 0 */
  95. /* Peripheral clock disable */
  96. __HAL_RCC_FDCAN_CLK_DISABLE();
  97. /**FDCAN1 GPIO Configuration
  98. PA11 ------> FDCAN1_RX
  99. PA12 ------> FDCAN1_TX
  100. */
  101. HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);
  102. /* FDCAN1 interrupt Deinit */
  103. HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn);
  104. /* USER CODE BEGIN FDCAN1_MspDeInit 1 */
  105. /* USER CODE END FDCAN1_MspDeInit 1 */
  106. }
  107. }
  108. /* USER CODE BEGIN 1 */
  109. //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)
  110. //len:数据长度(最大为8),可设置为FDCAN_DLC_BYTES_2~FDCAN_DLC_BYTES_8
  111. //msg:数据指针,最大为8个字节.
  112. //返回值:0,成功;
  113. // 其他,失败;
  114. uint8_t FDCAN1_Send_Msg(uint8_t* msg)
  115. {
  116. fdcan1_TxHeader.Identifier = 0x001;
  117. fdcan1_TxHeader.IdType = FDCAN_STANDARD_ID;
  118. fdcan1_TxHeader.TxFrameType = FDCAN_DATA_FRAME;
  119. fdcan1_TxHeader.DataLength = FDCAN_DLC_BYTES_8;
  120. fdcan1_TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
  121. fdcan1_TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
  122. fdcan1_TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
  123. fdcan1_TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
  124. fdcan1_TxHeader.MessageMarker = 0x52; //由于网上借鉴该函数,我也不太明白为什么是0x52,不过我测试改成0好像也没问题
  125. if(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1,&fdcan1_TxHeader,msg)!=HAL_OK) return 1;//发送
  126. return 0;
  127. }
  128. //can口接收数据查询
  129. //buf:数据缓存区;
  130. //返回值:0,无数据被收到;
  131. //其他,接收的数据长度;
  132. uint8_t FDCAN1_Receive_Msg(uint8_t *buf, uint16_t *Identifier,uint16_t *len)
  133. {
  134. if(HAL_FDCAN_GetRxMessage(&hfdcan1,FDCAN_RX_FIFO0,&fdcan1_RxHeader,buf)!=HAL_OK)return 0;//接收数据
  135. *Identifier = fdcan1_RxHeader.Identifier;
  136. *len=fdcan1_RxHeader.DataLength>>16;
  137. return fdcan1_RxHeader.DataLength>>16;
  138. }
  139. /* USER CODE END 1 */

       

  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * @file fdcan.h
  5. * @brief This file contains all the function prototypes for
  6. * the fdcan.c file
  7. ******************************************************************************
  8. * @attention
  9. *
  10. * Copyright (c) 2023 STMicroelectronics.
  11. * All rights reserved.
  12. *
  13. * This software is licensed under terms that can be found in the LICENSE file
  14. * in the root directory of this software component.
  15. * If no LICENSE file comes with this software, it is provided AS-IS.
  16. *
  17. ******************************************************************************
  18. */
  19. /* USER CODE END Header */
  20. /* Define to prevent recursive inclusion -------------------------------------*/
  21. #ifndef __FDCAN_H__
  22. #define __FDCAN_H__
  23. #ifdef __cplusplus
  24. extern "C" {
  25. #endif
  26. /* Includes ------------------------------------------------------------------*/
  27. #include "main.h"
  28. /* USER CODE BEGIN Includes */
  29. /* USER CODE END Includes */
  30. extern FDCAN_HandleTypeDef hfdcan1;
  31. /* USER CODE BEGIN Private defines */
  32. /* USER CODE END Private defines */
  33. void MX_FDCAN1_Init(void);
  34. /* USER CODE BEGIN Prototypes */
  35. uint8_t FDCAN1_Send_Msg(uint8_t* msg);
  36. uint8_t FDCAN1_Receive_Msg(uint8_t *buf, uint16_t *Identifier,uint16_t *len);
  37. /* USER CODE END Prototypes */
  38. #ifdef __cplusplus
  39. }
  40. #endif
  41. #endif /* __FDCAN_H__ */

        从以上代码可以看出FDCAN部分要增加过滤器配置代码,CubeMX并不会帮你自动生成这部分代码,这些发送接收函数都是网上借鉴的,其实都大差不差。需要注意如果想选定只能收到特定ID的信息,那么FDCAN上过滤器的FilterID1和FilterID2要进行更改,而且我印象单单更改这两个值还不可以,还需要配置其他REJET东西,关于这点可以自行网上了解。可以参考这篇文章:(19条消息) STM32H7 FDCAN id过滤问题_fdcan_filter_mask_swheryoo的博客-CSDN博客

        如果想通过FDCAN中断处理,可以在stm32g4xx_it.c文件中找到FDCAN1_IT0_IRQHandler该函数,在里面进行自己想要的中断处理。

  1. void FDCAN1_IT0_IRQHandler(void)
  2. {
  3. /* USER CODE BEGIN FDCAN1_IT0_IRQn 0 */
  4. //自行添加想实现的功能
  5. /* USER CODE END FDCAN1_IT0_IRQn 0 */
  6. HAL_FDCAN_IRQHandler(&hfdcan1);
  7. /* USER CODE BEGIN FDCAN1_IT0_IRQn 1 */
  8. /* USER CODE END FDCAN1_IT0_IRQn 1 */
  9. }

        自此,FDCAN就可以作为传统的CAN进行通信了,亲测有效。 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/144562
推荐阅读
相关标签
  

闽ICP备14008679号