目录

  • 前言
  • Message RAM分配
  • STM32工程搭建
  • 串口配置
  • 100us定时器
  • FDCAN配置
  • Bus-Off处理
  • 新消息接收处理
  • 发送处理
  • 使用Xavier配合测试一下
  • 完整工程下载
  • 关于用作Classic CAN
  • 微信公众号

前言

参考前几篇:

  • Jetson Xavier/XavierNX/TX2 CANFD 配置使用
  • STM32 CANFD 基础知识
  • STM32G474 CANFD 用例详解

STM32H7系列的FDCAN目前最大也支持3路, 如STM32H730/723/725/733/735等, Message RAM也是最大10KB=2560words, RAM资源每路分配可以不一样.

先来回顾下STM32G474的FDCAN在Cube中的配置:

  • 标准帧滤波器最大设置28
  • 扩展帧滤波器最大设置8, PPT中却号称28…
  • RxFIFO元素数量不能设置, 生成代码中默认3, 疑似祖传自bxCAN
  • TxFIFO/Queue元素数量不能设置, 生成代码中默认3, 疑似祖传自bxCAN
  • 3路RAM大小一致, 不能手动设置Message Ram Offset
  • Rx/Tx元素的最大有效字节不能设置, 默认取最高64字节

这明显是虚假的FDCAN, 真实的FDCAN应该更灵活, STM32H7它来了, Cube配置更符合PPT中的参数:

  • 标准帧滤波器数量最大设置128, 所有FDCAN的标准帧滤波器数量之和不超过这个数即可
  • 扩展帧滤波器数量最大设置64, 所有FDCAN的扩展帧滤波器数量之和不超过这个数即可
  • RxFIFO0元素数量最大设置64, 所有FDCAN的RxFIFO0数量之和不超过这个数即可, RxFIFO1也有另外64个
  • RxFIFO0元素Data Field Size可以在[8, 12, 16, 20, 24, 32, 48, 64]中选择, 根据具体使用, 不必非要设置最大64字节
  • TxFIFO/Queue元素数量最大设置32, 所有FDCAN的TxFIFO/Queue数量之和不超过这个数即可
  • TxFIFO元素Data Field Size可以在[8, 12, 16, 20, 24, 32, 48, 64]中选择, 根据具体使用, 不必非要设置最大64字节
  • 可以手动设置Message Ram Offset了, 一般FDCAN1设置为0, FDCAN2根据上面的元素占用大小往后偏移, FDCAN3再递推, 只要所有FDCAN外设的RAM占用总和不超过10KB即可.

本篇用的出名较早的STM32H750VBT6, 最大只支持2路FDCAN, 虽然少, 但每路分到的RAM资源可以多一点. 相比STM32G474, STM32H7在STM32CubeMX中的分配更加灵活了.

依然是:

  • 仲裁段500Kbit/s, 采样点0.8
  • 数据段2Mbit/s, 采样点0.75

STM32H750的FDCAN连到Xavier CAN1上, CAN收发器均选用支持2M及以上CANFD的收发器,各自接上120Ω终端电阻.

USART3到PC用STLINK连接.

可以参考 ST官方的STM32H7-FD-CAN

Message RAM分配

回顾下STM32的CAN Message RAM mappings, 这个是支持的最大的元素数量:

下面会用到的参数总结如下:

  • 1 个 11-bit filter element => 1 words, 所有FDCAN的11-bit filter element数量之和不超过128
  • 1 个 29-bit filter element => 2 words, 所有FDCAN的29-bit filter element数量之和不超过64
  • 1 个 Rx FIFO 0 element => 18 words, 所有FDCAN的Rx FIFO 0 element数量之和不超过64
  • 1 个 Tx Buffer element => 18 words, 所有FDCAN的Tx Buffer element数量之和不超过32

有人说, 简单点, 少点套路多点诚意, 全部启用不好么, 不行, 如果全部元素都启用, 将占用 128 + 128 + 1152 + 1152 + 1152 + 64 + 576 + 128 = 4480 words = 17920 Bytes = 17.5KB, 超过了10KB = 2560 words的最大Ram限制. 所以还是要有所取舍, 用到的分配, 不用的不分配.

接着搞懂这Cube中这两张FDCAN分配图就可以了, 第一张是FDCAN1的, 第二张是FDCAN2的:

这里FDCAN1和FDCAN2资源都是对半分的, 都用了992words, 其实也可以不对半, 比如FDCAN1发送ID很多, FDCAN2只接收不发送, 那完全可以把FDCAN1的Tx Fifo Queue Elmts Nbr设置为32, FDCAN2设置为0. 这样FDCAN1一口气发32帧也不会丢帧. 相应的, FDCAN2的Message Ram Offset做相应更改.

这里FDCAN1, FDCAN2都用了RxFIFO0, 没有用RxFIFO1, 也是可以FDCAN1独占64个RxFIFO0元素, 然后FDCAN2独占64个RxFIFO1元素.

实际的Message Ram分配如图:

FDCAN1 RAM的实际起始地址为 0x4000AC00, FDCAN2 RAM的实际起始地址为 0x4000AC00 + 992 * 4 = 0x4000BB80.

接下来开始干活.

STM32工程搭建

STM32CubeMX配置步骤如下:

  • MCU选择: 打开 STM32CubeMX, 点击 ACCESS TO MCU SELECTOR, 选择 STM32H750VBTx

  • 调试端口配置为SWD: Pinout & Configuration -> Trace and Debug -> DEBUG, Debug 选择 Serial Wire, STM32H系列的Cube Debug位置与其它系列不同.

  • Pinout & Configuration -> System Core -> RCC -> HSE 选择 Crystal/Ceramic Resonator

  • Clock Configuration(我板子上用的外部25M晶振, 主频配置成480MHz, FDCAN主时钟是80MHz):

  • 开启100us定时器中断, 有datasheet的Figure 1. STM32H750xB block diagram可知, TIM6挂载在APB1上, 上面时钟树APB1 Timer Clocks是240MHz: Pinout & Configuration -> Timers -> TIM6 -> 勾选Activated, Prescaler设置为240-1, Counter Period设置为100-1 -> 勾选TIM6中断:

  • USART3配置: Pinout & Configuration -> Connectivity -> USART3 -> Mode选择异步Asynchronous, 关闭 OverrunDMA on RX Error, 波特率配置为2M-8-N-1, 并把IO调整到板子上用的PD8, PD9:

  • FDCAN1配置: Pinout & Configuration -> Connectivity -> FDCAN1, Mode选择FD, Frame Format设置FD mode with BirRate Switshing启用位速率变换, Auto Retransmission设置为Enable开启自动重传, Trasmit Pause设置为Enable开启传输暂停, 速率和采样点设置参考上一篇 STM32 CANFD 基础知识的位时间和采样点小节, Nominal仲裁段设置500Kbit/s(80M/NPre/(1+NTSeg1+NTSeg2) = 80M/2/(1+63+16) = 500Kbit/s), 采样点0.8((1+NTSeg1)/(1+NTSeg1+NTSeg2)=64/80=0.8); Data数据段设置为2Mbit/s((80M/DPre/(1+DTSeg1+DTSeg2) = 80M/2/(1+63+16) = 500Kbit/s)), 采样点0.75((1+DTSeg1)/(1+DTSeg1+DTSeg2)=15/20=0.75), Std Filter Nbr标准帧过滤器数量直接设为最大64, Ext Filters Nbr扩展帧滤波器数量直接设为最大32(虽然后面并没有全用上), Rx Fifo0 Elmts Nbr数量设置为32, Size也设置64 bytes data field, Tx Fifo16,FIFO mode, 64 bytes data field; 勾选FDCAN1 interrupt 0中断, 引脚也从默认调整到板子上用的引脚PD0/PD1; FDCAN2除了Messge Ram Offset外, 其它与FDCAN1一致, 引脚从默认调整到板子上用的引脚PB5/PB6:



  • Project Manager -> Project -> Browse 选择工程位置(Project Location), 填入工程名(Project Name), Toolchain/IDE 选择 MDK-ARM, 把Minimum Heap Size改为0x2000, Minimum Stack Size改为0x2000.

  • Project Manager -> Code Generator -> 勾选Copy only the necessary library files, 还有Generate peripheral initialization as a pair of .c/.h files per periphral

  • 点击右上角 GENERATE CODE 按钮生成代码, 点击Open Project按钮打开工程.

MPU, Dcache, Icache是Cortex-M7新增的东西, 例程一般会打开cache, 在System Core -> CORTEX_M7里面使能两个Cache, 这里不设置暂不影响使用, 我们先不管它.

Keil配置, Keil 点击魔术棒或者Project -> Options for Target ..., 默认配置DebugST-link Debugger, 点击Setting:

  • Flash Download选项卡 -> 勾选Reset and Run, 这样下载后可以自动复位运行.
  • Pack选项卡, 去掉默认的Enable勾选

切换到Target选项卡, 勾选Use MicroLIB, 不晓得为什么H7的Cube每次生成的代码这个都没有勾选, 导致只能仿真运行, 实际却不运行的尴尬局面, 每次得手动勾选上这个才解决.

到此配置结束. 下面是手动添加的代码详解.

串口配置

为 USART3 添加printf支持, 这个与其他系列的MCU稍有不同:

#include <stdio.h>int fputc(int ch,FILE *f)
{HAL_UART_Transmit(&huart3,(uint8_t *)&ch,1,100);     return 0;
}

100us定时器

因为用最大64字节测试的, 实测只发送的情况下, 1s传输最多约2500帧, 再多就丢帧了, 也就是400us/帧, 保守一点, 这里设置500us传一帧, 如果没传出去, 有重传的机会. 为了准确点, 这里取100us:

/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim6);  //Starts the TIM Base generation in interrupt mode.
/* USER CODE END 2 */uint8_t tim6_flag = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM6) {tim6_flag = 1;}
}

FDCAN配置

主要是标准帧滤波器, 扩展帧滤波器设置, 开启新消息接收中断, 开启Bus-Off中断, 设置发送传输延时补偿等.

FDCAN_FilterTypeDef sFilterConfig1;void fdcan1_config(void)
{sFilterConfig1.IdType = FDCAN_STANDARD_ID;sFilterConfig1.FilterIndex = 0;sFilterConfig1.FilterType = FDCAN_FILTER_MASK;sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;sFilterConfig1.FilterID1 = 0;sFilterConfig1.FilterID2 = 0;HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1);sFilterConfig1.IdType = FDCAN_EXTENDED_ID;sFilterConfig1.FilterIndex = 0;sFilterConfig1.FilterType = FDCAN_FILTER_MASK;sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;sFilterConfig1.FilterID1 = 0;sFilterConfig1.FilterID2 = 0;HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1);   /* Configure global filter to reject all non-matching frames */HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE);/* Configure Rx FIFO 0 watermark to 2 *///HAL_FDCAN_ConfigFifoWatermark(&hfdcan1, FDCAN_CFG_RX_FIFO0, 2);/* Activate Rx FIFO 0 new message notification on both FDCAN instances */HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_BUS_OFF, 0);/* Configure and enable Tx Delay Compensation, required for BRS mode.TdcOffset default recommended value: DataTimeSeg1 * DataPrescalerTdcFilter default recommended value: 0 */HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan1, hfdcan1.Init.DataPrescaler * hfdcan1.Init.DataTimeSeg1, 0);HAL_FDCAN_EnableTxDelayCompensation(&hfdcan1);HAL_FDCAN_Start(&hfdcan1);
}

这里设置了用一个标准帧滤波器设置了标准帧的全接收, 用一个扩展帧滤波器设置了扩展帧的全接收, 用的掩码的方式设置全接收.

收到的消息扔到RxFIFO0中, 设置了RxFIFO0的新消息来的中断.

这里程序中滤波器只各用了一个(index = 0), 如果想用更多, 递增index, 最多不超过各自设置的Nbr.

FDCAN2的配置和FDCAN1类似.

Bus-Off处理

如果CANH, CANL短接, 或者和其它节点的传输速率/采样点不一致, 会引发Bus-Off, 上面开启了Bus-Off中断, 发生Bus-Off时, 直接在中断中初始化FDCAN外设:

void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs)
{//__HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_BUS_OFF);if(hfdcan->Instance == FDCAN1) {MX_FDCAN1_Init();fdcan1_config();} else if(hfdcan->Instance == FDCAN2) {MX_FDCAN2_Init();fdcan2_config();} else {}
}

新消息接收处理

直接把接收的消息通过2M波特率的串口打印出来.

FDCAN_RxHeaderTypeDef RxHeader1;uint8_t RxData1[64];
uint8_t RxData2[64];0xF0000 => 64
uint8_t dlc2len[]={0,1,2,3,4,5,6,7,8,12,16,20,24,32,48,64};
uint8_t can_dlc2len(uint32_t RxHeader_DataLength)
{return dlc2len[RxHeader_DataLength>>16];
}uint8_t cnt = 0;
uint8_t brs[] = {'-', 'B'};
uint8_t esi[] = {'-', 'E'};
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != 0) {//memset(&RxHeader1, 0, sizeof(FDCAN_RxHeaderTypeDef));    //if use, lose frameHAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);if (hfdcan->Instance == FDCAN1) {printf("fdcan1, ");} else if (hfdcan->Instance == FDCAN2) { printf("fdcan2, ");} else {}printf("0x%8X, %02d, %c, %c:",RxHeader1.Identifier, can_dlc2len(RxHeader1.DataLength), brs[RxHeader1.BitRateSwitch>>20 & 0x1],esi[RxHeader1.ErrorStateIndicator>>31 & 0x1]);for(cnt = 0; cnt < can_dlc2len(RxHeader1.DataLength); cnt++) {printf(" %02X", RxData1[cnt]);}printf("\n\r");}
}

注意 RxHeader.DataLength => can_dlc 的对应关系.

示例如图:

图中消息来自fdcan1, can_id为0x18FF000x, 64字节数据, 开启了BRS和ESI, :后面是64字节的十六进制数据.

printf还是比较耗时间的, 这里仅做低负载下的演示, 实际使用不建议中断中这么搞.

发送处理

发送开启了BRS和ESI, 如果发送失败, 有重发机会.

#include <string.h>FDCAN_TxHeaderTypeDef TxHeader1;uint8_t TxData1[64];typedef struct {uint8_t flag;uint8_t index;FDCAN_TxHeaderTypeDef TxHeader[16];uint8_t TxData[64*16];
} FDCAN_SendFailTypeDef;FDCAN_SendFailTypeDef fdcan1_send_fail = {0};void fdcan1_transmit(uint32_t can_id, uint32_t DataLength, uint8_t tx_data[])
{TxHeader1.Identifier = can_id;TxHeader1.IdType = FDCAN_EXTENDED_ID;if(can_id < 0x800) {  //exactly not rightTxHeader1.IdType = FDCAN_STANDARD_ID;}TxHeader1.TxFrameType = FDCAN_DATA_FRAME;TxHeader1.DataLength = DataLength;TxHeader1.ErrorStateIndicator = FDCAN_ESI_ACTIVE;TxHeader1.BitRateSwitch = FDCAN_BRS_ON;TxHeader1.FDFormat = FDCAN_FD_CAN;TxHeader1.TxEventFifoControl = FDCAN_NO_TX_EVENTS;TxHeader1.MessageMarker = 0;  //Tx Event FIFO Useif(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader1, tx_data) != HAL_OK) {memcpy(&fdcan1_send_fail.TxHeader[fdcan1_send_fail.index], &TxHeader1, sizeof(FDCAN_TxHeaderTypeDef));memcpy(&fdcan1_send_fail.TxData[64*fdcan1_send_fail.index], tx_data, can_dlc2len(DataLength));fdcan1_send_fail.index = (fdcan1_send_fail.index + 1) & 0x0F;  //0~15fdcan1_send_fail.flag = 1;}
}int main(void)
{.../* USER CODE BEGIN 2 */fdcan1_config();fdcan2_config();for(uint8_t i = 0; i < 64; i++) {TxData1[i] = i;TxData2[i] = i;}HAL_TIM_Base_Start_IT(&htim6);uint32_t count = 0;uint32_t cnt_100us = 0;uint32_t cnt_500us = 0;uint32_t i = 0;/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if(tim6_flag && count < 1000) {tim6_flag = 0;TxData1[0] = count >> 8 & 0xFF;TxData1[1] = count & 0xFF;++cnt_100us;cnt_500us = cnt_100us / 5;if(cnt_500us && (cnt_100us%5==0) ) {switch(cnt_500us) {case 1: fdcan1_transmit(0x108, FDCAN_DLC_BYTES_64, TxData1); fdcan1_transmit(0x101, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x102, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x103, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x104, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x105, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x106, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x107, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x12345678, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x12345671, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x12345672, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x12345673, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x12345674, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x12345675, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x12345676, FDCAN_DLC_BYTES_64, TxData1);fdcan1_transmit(0x12345677, FDCAN_DLC_BYTES_64, TxData1); break;case 17: /* next send */ break;case 18: break;case 19: break;case 20: ++count; cnt_100us = 0; break; //10ms}} else {  //fail retransmission onceif(fdcan1_send_fail.flag && cnt_500us > 16) {  //can't conflict with normal sendfor(i = 0; i < fdcan1_send_fail.index; i++) {fdcan1_transmit(fdcan1_send_fail.TxHeader[i].Identifier, fdcan1_send_fail.TxHeader[i].DataLength,&fdcan1_send_fail.TxData[64*i]);}fdcan1_send_fail.index = 0; fdcan1_send_fail.flag = 0;  //maybe send 4 times or more}if(fdcan2_send_fail.flag && cnt_500us > 16) {for(i = 0; i < fdcan2_send_fail.index; i++) {fdcan2_transmit(fdcan2_send_fail.TxHeader[i].Identifier, fdcan2_send_fail.TxHeader[i].DataLength,&fdcan2_send_fail.TxData[64*i]);}fdcan2_send_fail.index = 0;fdcan2_send_fail.flag = 0;}}}}/* USER CODE END 3 */
}

fdcan2和fdcan1的发送类似, 2个发送函数可以合并成一个, 这里没有合并.

发送函数中的DataLength指的是类似FDCAN_DLC_BYTES_64这种的宏定义, 而不是数字64.

这里用can_id < 0x800只是为了简便, 其实不正确, 这种情况下也有可能是扩展帧, 但通常不会这么用.

因为发送最多可以缓存16帧, 所以可以一口气发送16帧而不会丢帧, 如case 1处, 也可以一帧一帧发送, 如case 2, case 3, case 4… 大概6ms/16帧或者500us/帧.

因为总线中还有其他节点发送之类的, 有可能发送失败, 发送失败后重传的机会, 具体情况根据现场可另行调整.

如果fdcan1, fdcan2没有在一个网络中, 可以一口气 fdcan1发送16帧 + fdcan2发送16帧, 或者把32都给fdcan1的Nbr, 这样可以一口气发32帧不丢帧.

一般车辆总线中发送都是最快10ms内把要发的不同ID的数据一股脑发出去(当然也有20ms, 50ms, 100ms周期的数据这里暂不考虑), 所以这里100us中断计数100次就是10ms.

程序中发送1000*16=16000帧后停止发送, 10ms发16帧, 所以10s后数据就发完了.

使用Xavier配合测试一下

把STM32的FDCAN1连到Xavier的CAN1上, Xavier CAN1设置:

#!/bin/shsudo modprobe can
sudo modprobe can_raw
sudo modprobe mttcansudo ip link set down can0
sudo ip link set can0 type can bitrate 500000 sample-point 0.8 dbitrate 2000000 dsample-point 0.75 fd on restart-ms 100
sudo ip link set up can0
sudo ifconfig can0 txqueuelen 1000sudo ip link set down can1
sudo ip link set can1 type can bitrate 500000 sample-point 0.8 dbitrate 2000000 dsample-point 0.75 fd on restart-ms 100
sudo ip link set up can1
sudo ifconfig can1 txqueuelen 1000

Xavier也是仲裁段500Kbit/s, 采样点0.8, 数据段2Mbit/s, 采样点0.75.

restart-ms 100设置总线Bus-Off时, 100ms后重启.

设置完后查看设置状态 ip -details -statistics link show can1:

$ ip -details -statistics link show can1
6: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 72 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000link/can  promiscuity 0 can <FD> state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 100 bitrate 498701 sample-point 0.792 tq 26 prop-seg 30 phase-seg1 30 phase-seg2 16 sjw 1mttcan: tseg1 2..255 tseg2 0..127 sjw 1..127 brp 1..511 brp-inc 1dbitrate 2021052 dsample-point 0.736 dtq 26 dprop-seg 6 dphase-seg1 7 dphase-seg2 5 dsjw 1mttcan: dtseg1 1..31 dtseg2 0..15 dsjw 1..15 dbrp 1..15 dbrp-inc 1clock 38400000re-started bus-errors arbit-lost error-warn error-pass bus-off0          0          0          13         20         0         numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 RX: bytes  packets  errors  dropped overrun mcast   64578440   1013451  0       0       0       0       TX: bytes  packets  errors  dropped carrier collsns 952448     15914    0       0       0       0

位速率和采样点的些许误差测试并无影响.

使用 candump -ta -x can1 >32.dat, 这里-ta显示绝对时间, 然后下载STM32程序运行, 上面的16000帧数据全部存到32.dat文件中了, 共计16000行这里截取首尾部分显示:

 (1614077476.632584)  can1  RX B -  108  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.632961)  can1  RX B -  101  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.633393)  can1  RX B -  102  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.633754)  can1  RX B -  103  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.634198)  can1  RX B -  104  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.634558)  can1  RX B -  105  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.634952)  can1  RX B -  106  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.635348)  can1  RX B -  107  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.635782)  can1  RX B -  12345678  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.636217)  can1  RX B -  12345671  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.636641)  can1  RX B -  12345672  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.637075)  can1  RX B -  12345673  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.637509)  can1  RX B -  12345674  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.638000)  can1  RX B -  12345675  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.638380)  can1  RX B -  12345676  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.638811)  can1  RX B -  12345677  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077476.642570)  can1  RX B -       108  [64]  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F... (1614077486.617982)  can1  RX B E  12345677  [64]  03 E6 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.622256)  can1  RX B E       108  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.622604)  can1  RX B E       101  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.622959)  can1  RX B E       102  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.623405)  can1  RX B E       103  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.623687)  can1  RX B E       104  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.624052)  can1  RX B E       105  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.624416)  can1  RX B E       106  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.624781)  can1  RX B E       107  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.625178)  can1  RX B E  12345678  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.625578)  can1  RX B E  12345671  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.625982)  can1  RX B E  12345672  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.626377)  can1  RX B E  12345673  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.626777)  can1  RX B E  12345674  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.627177)  can1  RX B E  12345675  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.627579)  can1  RX B E  12345676  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F(1614077486.627977)  can1  RX B E  12345677  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F

可以看到并不是低ID就优先发送, 发送时没有管ID优先级, FIFO是按照先进先出发的.

这里前三行的格式问题, ESI的144行之前是-, 144行及以后是E, 暂时不解. 其它正常, ID顺序和数据都对得上.

Xavier发送脚本, ##后面的3表示开启BRS和ESI:

#!/bin/shwhile true; docansend can1 18FF0001##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16cansend can1 18FF0002##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16cansend can1 18FF0003##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16  cansend can1 18FF0004##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16cansend can1 18FF0005##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16cansend can1 18FF0006##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16  sleep 0.01
done

可以在USART3串口中看到收到的数据, 如上面 新消息接收处理 小节配图.

完整工程下载

https://download.csdn.net/download/weifengdq/15437227

其他例子可以参考STM32Cube中的示例, 针不戳:

  • 直接用FDCAN传图像FDCAN_Image_transmission
  • 用作传统CAN的示例FDCAN_Classic_Frame_Networking
  • 时钟校准FDCAN_Clock_calibration

关于用作Classic CAN

可参考之前的文章 STM32CubeMX_CAN_CAN3_FDCAN.

核心思想是:

  • Mode 设置为Classic Master或者Classic Slave, 而不是FD
  • 仲裁段的通信速率设置为500Kbit/s, 数据段可以不用管, 或者保险点设置为500Kbit/s.

微信公众号

欢迎扫描二维码关注本人微信公众号, 及时获取或者发送给我最新消息:

STM32H750 更好用的CANFD 用例详解相关推荐

  1. 以SIGSEGV为例详解信号处理(与栈回溯)

    以SIGSEGV为例详解信号处理(与栈回溯) 信号是内核提供的向用户态进程发送信息的机制, 常见的有使用SIGUSR1唤醒用户进程执行子程序或发生段错误时使用SIGSEGV保存用户错误现场. 本文以S ...

  2. Python Unittest-根据不同测试环境跳过用例详解

    Python Unittest-根据不同测试环境跳过用例详解 本文章会讲述以下几个内容: 1.Unittest 如何跳过用例 2.如何使用sys.argv 3.自动化测试项目中如何一套代码多套环境运行 ...

  3. Linux用户、权限及改变文件所有者及文件所属组多例详解 附python代码

    https://blog.csdn.net/hanhanwanghaha宝藏女孩 欢迎您的关注! 欢迎关注微信公众号:宝藏女孩的成长日记 如有转载,请注明出处(如不注明,盗者必究) Linux用户.权 ...

  4. 必过SafetyNet!以MIUI开发版系统为例详解Android设备通过SafetyNet校验方法

    必过SafetyNet!以MIUI开发版系统为例详解Android设备通过SafetyNet校验方法 作者 梓沐啊_(KylinDemons) 版权声明 Copyright © 2021 KylinD ...

  5. C/C++趣味编程经典100例详解

    更新记录   2019-08-27 28题 重写     C/C++语言经典.实用.趣味程序设计编程百例精解 1.绘制余弦曲线 在屏幕上用"*"显示0~360度的余弦函数cos(x ...

  6. 一起学DNS系列(十)图、例详解DNS递归和迭代查询原理及过程 (1)

    上节中提到了一些有关递归查询的内容,但说的很少,也很笼统,本节将会从原理和实例两方面入手分析DNS的递归以及迭代查询. 在此之前,我们需要了解一些背景知识,以便于更好的理解今天的主题内容. 在互联网中 ...

  7. 以58同城为例详解如何用爬虫采集二手房房源数据及中介联系方式

    2019独角兽企业重金招聘Python工程师标准>>> 2008年9月4日,英国<自然>杂志刊登了一个名为"Big Data"的专辑,首次提出大数据概 ...

  8. 【算法•日更•第七期】区间动态规划详解+一本通1570能量项链题解

    ▎前置基础 啥也不用说,不会动态规划绝对看不懂,请不会动态规划的同志们先戳这里了解基础动态规划. ▎什么是区间动态规划? 区间动态规划可以理解为用了分治的动态规划. 顾名思义,动态规划中涉及了区间,那 ...

  9. A/B 测试的统计学原理及用例详解

    统计学在 A/B 测试中的作用 A/B 测试是一种对比试验(下文中对比试验特指 AppAdhoc 平台上的 A/B 测试),而试验就是从总体中抽取一些样本进行数据统计,进而得出对总体参数的一个评估.可 ...

最新文章

  1. a.cmd 文件里的内容
  2. Moss/Sharepoint 2010 Form认证(FBA)
  3. 还要我带一个六级辅导班--痛苦!
  4. 树莓派无法安装mariadb_RaspberryPi(树莓派)安装 MariaDB 数据库没有办法远程访问...
  5. 2021十大运动蓝牙耳机品牌推荐,平价真无线蓝牙耳机运动无拘束
  6. leetcode剑指offer合集+题解
  7. Android 非功能性测试(性能测试)
  8. 2021-09-30 cannot locate default realm
  9. Qtum量子链研究院:Qtum Plasma MVP 技术详解
  10. Maui Blazor windows程序无法通过双击 bin 文件夹中的 exe打开程序的解决办法
  11. Android自定义键盘的简单实现
  12. 【python 字符判断】python 判断名字是否含有数字,英文字符和汉字
  13. 用css、html、js模拟操作系统2
  14. 【调剂】云南民族大学2023年硕士研究生招生调剂公告
  15. android源码下编译apk内无so,Android源码编译反思
  16. 关于select 被选中触发事件,onclick事件失效问题
  17. 策略模式和简单工厂+策略模式
  18. MySQL的DDL、DML和DQL的基本语法
  19. 中文文本分类之CharCNN
  20. 基于大数据的用户画像构建(理论篇)

热门文章

  1. 哪个人工智能系统使用了神经网络算法
  2. MFC知识点和常用类控件的使用
  3. scanner.nextInt与scanner.nextLine的使用
  4. 基础知识 十进制转二进制
  5. 安卓手机屏蔽物理按键
  6. Android毕业设计及论文答辩经验分享
  7. 华为eNSP企业综合组网(《路由与交换技术》课程综合实验)
  8. 网络安全等级保护测评高风险判定-安全计算环境-4
  9. UC浏览器怎么将mht转HTML,极速模式下的MHT
  10. 非常经典的JAVA编程题(水仙花数)