你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32C0评测】7、CAN回环测试

[复制链接]
qintian0303 发布时间:2025-5-4 00:05
      控制器局域网总线(CAN,Controller Area Network)作为一种专为实时应用设计的串行通讯协议总线,在工业及自动化领域占据着举足轻重的地位。它凭借简单的双绞线即可实现信号的高效传输,凭借出色的性能与广泛的适用性,已然成为世界上应用最为普遍的现场总线之一。实际上在我的应用场景并没有实际使用过这种借口,接下来我们也是主要学习一下STM32这方面的的具体使用方法。
      本次测试的C092是支持FDCAN的,CAN FD(CAN with Flexible Data rate),即“可变速率的 CAN”,可视为传统 CAN 协议的升级版。值得注意的是,此次升级主要聚焦于协议层面,物理层并未发生改变。CAN 与 CAN FD 在多个关键方面存在显著差异:
      传输速率不同:传统 CAN 的传输速率相对固定,而 CAN FD 引入了可变速率机制,能够根据实际需求灵活调整传输速率。在数据量较大或对实时性要求较高的场景下,CAN FD 可以提高传输速率,从而更快地完成数据传输任务;
      数据域长度不同:传统 CAN 的数据域长度有限,限制了每次传输的数据量。而 CAN FD 扩展了数据域的长度,使得在一次通信中可以传输更多的数据,减少了通信次数,提高了通信效率;
      帧格式不同:为了适应可变速率和数据域长度的变化,CAN FD 对帧格式进行了相应的优化和改进。新的帧格式能够更好地支持可变速率传输和大数据量传输,同时保持了与传统 CAN 协议的兼容性;
      ID 长度不同:CAN FD 不仅在数据域长度上进行了扩展,还对标识符(ID)的长度进行了调整。更长的 ID 长度提供了更多的寻址空间,使得系统能够支持更多的节点,进一步增强了系统的扩展性和灵活性。
      我们看一下班次开发板的原理图:
1.png

      实物接口如下:
2.png

      可以看到就在常用的USB接口旁边,也就是说基本上对于C0系列来说,USB和FDCAN只能二选一了。
      那么如何实现FDCAN的配置呢?
      先看一下时钟配置,因为C092支持最大的是48MHz,到FDCAN最大也是48MHz:
3.png

      启动FDCAN:

4.png

      这里没有过多的模式和配置,直接启用就好;
      注意修改默认引脚:
5.png

      下面就是具体参数的设置,我们本次主要进行一下回环测试,所以要进行如下配置:
            
基本参数
Clock Divider
时钟分频
Frame Format
CANFD模式
Mode
正常工作模式
Auto Retransmission
自动重传
Transmit Pause
传输暂停
Protocol Exception
协议异常处理
Nominal Sync Jump Width
裁决段同步跳转段宽度
Data Prescaler
数据段分频系数
Data Sync Jump Width
数据段同步跳转段宽度
Data Time Seg1
数据段时间段1
Data Time Seg2
数据段时间段2
Std Filters Nbr
标准滤波器数量
Ext Filters Nbr
拓展滤波器数量
Tx Fifo Queue Mode
发送模式
              我们按照例程中的配置参数进行一下配置:
6.png

      接下来进行比特率的配置,如下图:
7.png

      上图的选项最小数值是1,比特率=CAN时钟/时钟分频/预分频/(Seg1+Seg2+1),所以就算是最小配置参数,得到的最大比特率是16M,不过我们还是不要设置那么大,就和SPI的配置一样,太大不一定通信稳定。
      依然是回环测试,我们将CAN接头短接:
8.png

      这里我们主要配置过滤ID,前面各开启了一个标准滤波器和一个扩展滤波器:
  1. /* Configure standard ID reception filter to Rx FIFO 0. Only accept ID = FilterID1 */
  2.   FDCAN_FilterTypeDef        sFilterConfig;
  3.   sFilterConfig.IdType       = FDCAN_STANDARD_ID;
  4.   sFilterConfig.FilterIndex  = 0U;
  5.   sFilterConfig.FilterType   = FDCAN_FILTER_DUAL;
  6.   sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
  7.   sFilterConfig.FilterID1    = 0x444;
  8.   sFilterConfig.FilterID2    = 0x444; /* For acceptance, MessageID and FilterID1 must match exactly */
  9.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
  10.   {
  11.     Error_Handler();
  12.   }

  13.   /* Configure extended ID reception filter to Rx FIFO 1. Only accept ID between FilterID1 and FilterID2. */
  14.   sFilterConfig.IdType       = FDCAN_EXTENDED_ID;
  15.   sFilterConfig.FilterIndex  = 0U;
  16.   sFilterConfig.FilterType   = FDCAN_FILTER_RANGE_NO_EIDM;
  17.   sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
  18.   sFilterConfig.FilterID1    = 0x1111111;
  19.   sFilterConfig.FilterID2    = 0x2222222;
  20.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
  21.   {
  22.     Error_Handler();
  23.   }
复制代码
然后是进行数据的发送和接受,这里都是通过FIFO的模式进行缓存的,并在接收节点进行接收数据打印:
  1. FDCAN_TxHeaderTypeDef        txHeader;

  2.   /* Add message to Tx FIFO */
  3.   txHeader.Identifier          = 0x444;
  4.   txHeader.IdType              = FDCAN_STANDARD_ID;
  5.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;
  6.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;
  7.   txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
  8.   txHeader.BitRateSwitch       = FDCAN_BRS_ON;
  9.   txHeader.FDFormat            = FDCAN_FD_CAN;
  10.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;
  11.   txHeader.MessageMarker       = 0x52U;
  12.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData0) != HAL_OK)
  13.   {
  14.     Error_Handler();
  15.   }

  16.   /* Add second message to Tx FIFO */
  17.   txHeader.Identifier          = 0x1111112;
  18.   txHeader.IdType              = FDCAN_EXTENDED_ID;
  19.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;
  20.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;
  21.   txHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
  22.   txHeader.BitRateSwitch       = FDCAN_BRS_ON;
  23.   txHeader.FDFormat            = FDCAN_FD_CAN;
  24.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;
  25.   txHeader.MessageMarker       = 0xCCU;
  26.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData1) != HAL_OK)
  27.   {
  28.     Error_Handler();
  29.   }

  30.   /* Add third message to Tx FIFO */
  31.   txHeader.Identifier          = 0x1111113;
  32.   txHeader.IdType              = FDCAN_EXTENDED_ID;
  33.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;
  34.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;
  35.   txHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
  36.   txHeader.BitRateSwitch       = FDCAN_BRS_OFF;
  37.   txHeader.FDFormat            = FDCAN_FD_CAN;
  38.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;
  39.   txHeader.MessageMarker       = 0**U;
  40.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData2) != HAL_OK)
  41.   {
  42.     Error_Handler();
  43.   }
  44.    
  45.     /* Get tick */
  46.   uint32_t tickstart = HAL_GetTick();

  47.   /* Wait transmission complete */
  48.   while (HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) != NB_RX_FIFO)
  49.   {
  50.     /* Timeout handling */
  51.     if ((HAL_GetTick() - tickstart) > TX_TIMEOUT)
  52.     {
  53.       Error_Handler();
  54.     }
  55.   }
  56.    
  57.     /*##-4 Receive messages ###################################################*/

  58.   /* Check one message is received in Rx FIFO 0 */
  59.   if (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO0) != 1U)
  60.   {
  61.     Error_Handler();
  62.   }

  63.   /* Retrieve message from Rx FIFO 0 */
  64.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &rxHeader, rxData) != HAL_OK)
  65.   {
  66.     Error_Handler();
  67.   }

  68.   /* Compare received RX message to expected data */
  69.   if ((rxHeader.Identifier != 0x444) ||
  70.       (rxHeader.IdType     != FDCAN_STANDARD_ID) ||
  71.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
  72.       (BufferCmp8b(txData0, rxData, COUNTOF(rxData)) != 0U))
  73.   {
  74.     Error_Handler();
  75.   }
  76.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);
  77.   /* Check two messages are received in Rx FIFO 1 */
  78.   if (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO1) != 2U)
  79.   {
  80.     Error_Handler();
  81.   }

  82.   /* Retrieve message from Rx FIFO 1 */
  83.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &rxHeader, rxData) != HAL_OK)
  84.   {
  85.     Error_Handler();
  86.   }

  87.   /* Compare received RX message to expected data */
  88.   if ((rxHeader.Identifier != 0x1111112) ||
  89.       (rxHeader.IdType     != FDCAN_EXTENDED_ID) ||
  90.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
  91.       (BufferCmp8b(txData1, rxData, COUNTOF(rxData)) != 0U))
  92.   {
  93.     Error_Handler();
  94.   }
  95.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);

  96.   /* Retrieve next message from Rx FIFO 1 */
  97.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &rxHeader, rxData) != HAL_OK)
  98.   {
  99.     Error_Handler();
  100.   }

  101.   /* Compare received RX message to expected data */
  102.   if ((rxHeader.Identifier != 0x1111113) ||
  103.       (rxHeader.IdType     != FDCAN_EXTENDED_ID) ||
  104.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
  105.       (BufferCmp8b(txData2, rxData, COUNTOF(rxData)) != 0U))
  106.   {
  107.     Error_Handler();
  108.   }
  109.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);
复制代码
     最后在通过在FIFO中查询的数据进行打印,与发送的数据一致:
9.png

      这里多了一个C8,应该是串口出现的问题。













收藏 评论0 发布时间:2025-5-4 00:05

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版