STM32 CAN/CANFD软件快速配置(HAL库版本)

这篇具有很好参考价值的文章主要介绍了STM32 CAN/CANFD软件快速配置(HAL库版本)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

STM32 CAN/CANFD软件快速配置(HAL库版本)

前言

控制器局域网总线(CAN,Controller Area Network)是一种用于实时应用的串行通讯协议总线,它可以使用双绞线来传输信号,是世界上应用最广泛的现场总线之一。CAN协议用于汽车中各种不同元件之间的通信,以此取代昂贵而笨重的配电线束。该协议的健壮性使其用途延伸到其他自动化和工业应用。CAN协议的特性包括完整性的串行数据通讯、提供实时支持、传输速率高达1Mb/s、同时具有11位的寻址以及检错能力。

特别说明:关于CAN总线协议和硬件电路,CANFD和CAN的区别等问题,这里不做介绍,网上的资料非常多,不懂的同学请自行查阅。

1 软件编程

1.1 建立工程

要建立一个HAL库版本的工程可以直接使用其他项目的HAL工程,也可以通过移植HAL固件库或者用STM32CubeMX生成。

我这里以STM32G0为例讲解一下如何用STM32CubeMX生成一个工程。
特别说明:如果不使用STM32CubeMX工具,可以跳过以下步骤,直接从1.2开始,把CANFD相关代码加入其他HAL工程即可。

1、配置时钟
我这里使用外部晶振时钟(HSE),8M晶振倍频到64M时钟。

STM32 CAN/CANFD软件快速配置(HAL库版本),单片机相关,经验分享,stm32,CANFD,CAN
STM32 CAN/CANFD软件快速配置(HAL库版本),单片机相关,经验分享,stm32,CANFD,CAN

2、配置引脚
选择自己实际使用的引脚作为CAN_TX和CAN_RX。

STM32 CAN/CANFD软件快速配置(HAL库版本),单片机相关,经验分享,stm32,CANFD,CAN

3、配置CAN参数
我这里用CAN1作为CANFD,CAN2作为普通CAN。

CAN1配置参考如下:
特别说明:以下数据仅供参考,请根据实际情况配置。
STM32 CAN/CANFD软件快速配置(HAL库版本),单片机相关,经验分享,stm32,CANFD,CAN

CAN2配置参考如下:
特别说明:以下数据仅供参考,请根据实际情况配置。
STM32 CAN/CANFD软件快速配置(HAL库版本),单片机相关,经验分享,stm32,CANFD,CAN

最后使能中断(注:CAN1和CAN2可以共用一个中断接口)。
STM32 CAN/CANFD软件快速配置(HAL库版本),单片机相关,经验分享,stm32,CANFD,CAN

4、生成工程
STM32 CAN/CANFD软件快速配置(HAL库版本),单片机相关,经验分享,stm32,CANFD,CAN

1.2 初始化

初始化主要分成三部分:引脚设置,CAN参数设置和CAN滤波器设置。

1.2.1 引脚设置

把CAN_H和CAN_L两个引脚配置成复用功能即可。
注:如果CAN控制芯片的S引脚连接到STM32的话,还得初始化这个引脚,S引脚可以配置成高速模式或静音模式。

参考代码:
注:该代码可以通过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基本参数设置

HAL库的CAN初始化有几个重要参数,都存放在几个结构体里面(如:CAN_HandleTypeDef,CAN_InitTypeDef),具体的结构体定义可以在HAL库查看。
说明:CAN参数需要根据自己实际的需求来配。

我这里着重讲解一下CAN波特率的配置。

CAN波特率 = CAN时钟频率 / 时钟分频 / 预分频系数 / (TimeSeg1 + TimeSeg2 + 1)。

其中,CAN时钟频率不是固定不变的,它取决于CAN所挂载的总线时钟。
比如STM32F1,系统时钟最大72M,APB1的总线时钟最大36M,而CAN控制器的时钟是挂在APB1的,所以CAN的时钟频率也等于APB1的时钟。
如果换作其他型号的MCU,CAN外设不一定是挂载到APB1上面的,时钟也不一定是36M,比如F4系列,APB1的时钟是可以配成42M的,因此,这个要根据实际情况来配置。

本例用的是STM32G0,CAN时钟频率配置为64MHz。
参考代码:
注:该代码可以通过STM32CubeMX生成

FDCAN_HandleTypeDef hfdcan1;
FDCAN_HandleTypeDef hfdcan2;

/* FDCAN1 init function */
void MX_FDCAN1_Init(void)
{
  /* USER CODE END FDCAN1_Init 1 */
  // CAN波特率 = 时钟频率 / 时钟分频  / 预分频系数 / (1 + TSG1 + TSG2) 
  // 仲裁段波特率 = 64M / 1 / 8 / (1 + 10 + 5) = 500k
  // 数据段波特率 = 64M / 1 / 2 / (1 + 10 + 5) = 2M
  hfdcan1.Instance = FDCAN1;                               // FDCAN1
  hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;            // 时钟分频               
  hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS;           // 配置为CANFD         
  hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;                   // 正常工作状态       
  hfdcan1.Init.AutoRetransmission = DISABLE;               // 关闭自动重传, 传统模式下需关闭           
  hfdcan1.Init.TransmitPause = DISABLE;                    // 关闭传输暂停      
  hfdcan1.Init.ProtocolException = DISABLE;                // 关闭协议异常处理          
  hfdcan1.Init.NominalPrescaler = 8;                       // 仲裁段时钟分频,传统CAN模式时只设置这一段即可   
  hfdcan1.Init.NominalSyncJumpWidth = 1;                   // 仲裁段同步跳转段的宽度                      
  hfdcan1.Init.NominalTimeSeg1 = 10;                       // 仲裁段时间段1                      
  hfdcan1.Init.NominalTimeSeg2 = 5;                        // 仲裁段时间段2                     
  hfdcan1.Init.DataPrescaler = 2;                          // 数据段时钟分频,若工作于传统模式,不需要设置数据段参数
  hfdcan1.Init.DataSyncJumpWidth = 1;                      // 数据段同步跳转段的宽度   
  hfdcan1.Init.DataTimeSeg1 = 10;                          // 数据段时间段1           
  hfdcan1.Init.DataTimeSeg2 = 5;                           // 数据段时间段2           
  hfdcan1.Init.StdFiltersNbr = 28;                         // 标准帧滤波器数量 
  hfdcan1.Init.ExtFiltersNbr = 8;                          // 扩展帧滤波器数量 
  hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;  // 发送模式:先入先出   
  if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
  {
    Error_Handler();
  }
}
/* FDCAN2 init function */
void MX_FDCAN2_Init(void)
{
  /* USER CODE END FDCAN2_Init 1 */
  // CAN波特率 = 时钟频率 / 时钟分频 / 预分频系数 / (1 + TSG1 + TSG2) = 64M / 1 / 8 / (1 + 10 + 5) = 500k
  hfdcan2.Instance = FDCAN2;                               // FDCAN2
  hfdcan2.Init.ClockDivider = FDCAN_CLOCK_DIV1;            // 时钟分频 
  hfdcan2.Init.FrameFormat = FDCAN_FRAME_CLASSIC;          // 配置为传统模式    
  hfdcan2.Init.Mode = FDCAN_MODE_NORMAL;                   // 正常工作状态
  hfdcan2.Init.AutoRetransmission = DISABLE;               // 关闭自动重传, 传统模式下需关闭
  hfdcan2.Init.TransmitPause = DISABLE;                    // 关闭传输暂停
  hfdcan2.Init.ProtocolException = DISABLE;                // 关闭协议异常处理
  hfdcan2.Init.NominalPrescaler = 8;                       // 仲裁段时钟分频,传统CAN模式时只设置这一段即可
  hfdcan2.Init.NominalSyncJumpWidth = 1;                   // 仲裁段同步跳转段的宽度               
  hfdcan2.Init.NominalTimeSeg1 = 10;                       // 仲裁段时间段1                   
  hfdcan2.Init.NominalTimeSeg2 = 5;                        // 仲裁段时间段2                   
  hfdcan2.Init.DataPrescaler = 8;                          // 数据段时钟分频,若工作于传统模式,不需要设置数据段参数
  hfdcan2.Init.DataSyncJumpWidth = 1;                      // 数据段同步跳转段的宽度
  hfdcan2.Init.DataTimeSeg1 = 10;                          // 数据段时间段1           
  hfdcan2.Init.DataTimeSeg2 = 5;                           // 数据段时间段2           
  hfdcan2.Init.StdFiltersNbr = 28;                         // 标准帧滤波器数量
  hfdcan2.Init.ExtFiltersNbr = 8;                          // 扩展帧滤波器数量
  hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;  // 发送模式:先入先出                  
  if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK)
  {
    Error_Handler();
  }
}
1.2.3 CAN收发初始化设置

CAN接收需要设置CAN滤波器,它的主要作用是筛选CAN接收的数据,只有满足设定规则的数据才会被接收,否则会被过滤掉。
而CAN发送则需要在发送一条数据前,先配置好这条数据的信息,如CANID,发送长度,数据类型(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;               // 标准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;               // 标准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 中断设置

如果使用CAN接收,需要配置中断服务函数。

参考代码:

/**
  * @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发送

CAN发送需要先配置发送参数,我这里为了方便测试,直接固定发送标准帧,ID也是固定的。
实际使用时可以把CANID,数据长度等参数作为函数入参,这样会更灵活一点。

参考代码:

void canfd_tx_test(void)
{
  TxHeader1.Identifier = 0x123;                 // CAN ID
  TxHeader1.IdType = FDCAN_STANDARD_ID;         // 标准ID
  TxHeader1.TxFrameType = FDCAN_DATA_FRAME;           
  TxHeader1.DataLength = FDCAN_DLC_BYTES_8;     // 发送长度: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接收

接收部分只要开启了Rx中断,在CAN控制器收到消息时会调用RxFifo的回调函数,此时在这里读取数据并根据实际情况做相应的处理即可。我这里把收到的数据又发回去了,这样可以同时验证接收和发送。

参考代码:

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();
      }
      /* 把接收到的数据以CANFD发送回去 */
      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();
      }
      /* 把接收到的数据以CAN发送回去 */
      TxHeader2.DataLength = RxHeader2.DataLength;
      TxHeader2.Identifier = RxHeader2.Identifier;
      if(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan2, &TxHeader2, can2_rxbuf) != HAL_OK)
      {
        Error_Handler();
      }
    }
  }
}

2 运行测试

使用USB-CAN工具测试。

CAN1使用CANFD(仲裁域波特率500k,数据域波特率2M),上位机每发送一条数据,STM32收到后同样回一条一样的数据,CANID、数据长度和数据都是一致,说明STM32收到的数据没有问题。
STM32 CAN/CANFD软件快速配置(HAL库版本),单片机相关,经验分享,stm32,CANFD,CAN

CAN2使用普通CAN(仲裁域和数据域波特率均为500k),上位机每发送一条数据,STM32收到后同样回一条一样的数据,CANID、数据长度和数据都是一致,说明STM32收到的数据没有问题。
STM32 CAN/CANFD软件快速配置(HAL库版本),单片机相关,经验分享,stm32,CANFD,CAN

还有一些其他测试,比如切换扩展帧,远程帧等等,这里就不展示了,感兴趣的同学可以自己改参数试试。

结论:CAN收发正常。

结束语

好了,关于如何通过STM32如何配置和使用CANFD就讲到这里,如果你有什么问题或者有更好的方法,欢迎在评论区留言。

需要源码工程的同学可以自行下载:点击跳转下载链接文章来源地址https://www.toymoban.com/news/detail-704085.html

到了这里,关于STM32 CAN/CANFD软件快速配置(HAL库版本)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STM32】标准库与HAL库对照学习教程十四--CAN总线

    STM32全部教程 :【STM32】标准库与HAL库对照学习系列教程大全 本篇介绍如何使用STM32的标准库与HAL库对CAN总线的使用,由于我那块普中的STM32F103ZET6开发板送人了,因此我这边用STM32F103C8最小系统板,进行简单的演示一下功能,最主要的还是需要理解CAN总线的原理,在本篇中,

    2024年02月15日
    浏览(29)
  • STM32 HAL库 CAN双机通信接收无法进入中断、中断没有反应的解决方法

    在调试HAL库下的CAN双机(双F103ZET6)通信时,阻塞轮询接收完全正常,但是中断接收没有反应。翻看了GL的烧脑之路总结(一):Cubemx创建CAN通信工程,无法进入CAN中断的原因这篇文章以后,核实自己的硬件电路没有问题,于是对自己的工程文件进行整理,把 ①HAL_CAN_ConfigFi

    2024年02月04日
    浏览(47)
  • stm32f407单片机上通过HAL库实现can总线数据的收发

      最近在使用can总线,由于这个以前接触的比较少,所以调试代码的时候直接是下载的正点原子的例程,在这个基础上修改调试的。现在将调试中遇到的问题,总结一下,避免以后踩坑。目前写了一个查询方式的,一个中断方式的。项目代码下载地址: https://download.csdn.n

    2024年02月09日
    浏览(38)
  • 【HAL库】HAL库STM32cubemx快速使用

    软件:keil5、STM32Cubemx 硬件:淘宝的STM32F103C8T6最小系统 1 新建工程 2 配置RCC 选择外部时钟源。 设置外部晶振输入值,我这块板子是8M。 然后手动输入最大时钟频率,然后回车让他自动配置时钟树。我这块板子是72M。 3 配置SYS 我的下载器是SWD两根线的,所以我选这个。(一定

    2023年04月20日
    浏览(36)
  • STM32单片机CAN通讯连续发送多包数据,发生丢包现象

    使用例程连续发送两三包数据时没有问题,发送多包数据时,发现丢包现象; 例程代码如下: CAN_TxStatus_Failed :状态标志位,不足以判断发送完成,当发送多个数据包时,就会产生问题,修改代码如下: 改成 CAN_TxStatus_Ok 发送成功标志位后,可以连续发送多包数据

    2024年02月16日
    浏览(29)
  • 【STM32】STM32 CANFD外设的几种消息接收过滤模式

    在控制器区域网络(CAN)系统中,正确配置消息过滤器对于有效管理网络通信至关重要。特别是在使用Flexible Data-rate Controller Area Network(FDCAN)时,选择合适的过滤器类型可以大大提高网络效率和消息处理速度。 STM32G47x芯片的CAN外设有如下几种接收消息过滤方法: 这是一种范

    2024年01月18日
    浏览(27)
  • STM32(HAL库)软件IIC驱动OLED

    目录 1、简介 2、CubeMX初始化配置 2.1 基础配置 2.1.1 SYS配置  2.1.2 RCC配置 2.2 软件IIC引脚配置 2.3 项目生成  3、KEIL端程序整合 3.1 OLED驱动添加 3.3 主函数代 3.4 效果展示 本文通过STM32F103C8T6单片机(HAL库)通过软件IIC方式对OLED进行驱动。 2.1.1 SYS配置  2.1.2 RCC配置 首先在建立Ha

    2024年02月14日
    浏览(40)
  • 单片机:STM32F4x HAL库软硬SPI驱动ST7735s 1.8寸LCD屏幕

    说明:此篇为学习记录。可能存在错误或者不足。如有问题请指出。 主控芯片:STM32F411CEU6 主控开发板:WeAct STM32F411CEU6最小系统板 TFT-LCD屏幕:合宙1.8寸TFT-LCD,驱动为ST7735s MDK版本:5,32 HAL库版本:1.27.1 STM32CubeMX版本:6.7.0 ST7735s支持8080并口,3线和4线串行接口,模块的驱动方

    2024年02月03日
    浏览(49)
  • 2018年电赛A题 软件部分 STM32 FFT 时域到频域 STM32cubeMX HAL

    题目要求:任意波信号发生器输出非正弦信号时,基波频率范围为50Hz~200Hz,测量电流信号基波频率,频率测量精度优于1%;测量基波及各次谐波分量的幅度(振幅值),电流谐波测量频率不超过1kHz,测量精度优于5% 。 实现方式:利用STM32单片机内置ADC对待测信号进行采集,

    2024年02月15日
    浏览(70)
  • HAL库配置STM32串口

    总结使用HAL库的方法,以供自己后续回顾,如有错误,欢迎指正。 首先,使用STM32CubeMax配置串口,记得打开中断。 然后,在串口初始化函数void  MX_USART1_UART_Init(void)中加入 使能接收中断函数,没有这一步,将无法接收数据。  HAL_UART_Receive_IT(huart1,Buffer,1)这个函数在每次进入

    2024年02月02日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包