canfd基础
Posted 城子特讯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了canfd基础相关的知识,希望对你有一定的参考价值。
目录
哪些STM32有CANFD外设
STM32G0, STM32G4, STM32H7, STM32L5,STM32MP1系列.
参考文档
- AN5348_STM32器件上的FDCAN外设的应用手册: dm00625700-fdcan-peripheral-on-stm32-devices-stmicroelectronics.pdf
- STM32G4-FD-CAN
- AN5405_STM32H7和STM32L5系列微控制器加载程序时使用的FDCAN协议: dm00660346-fdcan-protocol-used-in-the-stm32-bootloader-stmicroelectronics.pdf
CAN-FD特性
CAN-FD协议的主要功能如下:
- 与CAN协议的兼容, CAN-FD节点能够根据 ISO 11898-1 标准发送/接收CAN消息
- 错误检查改进, 最高 21位 CRC 校验
- 消息优先级
- 延迟时间保证
- 配置灵活性
- 具有时间同步的组播接收
- 系统范围内的数据一致性,每条消息最多64字节
- 多主站
- 错误检测和信令
- 临时错误和永久错误之间的区别, 节点故障和缺陷节点的自动关闭
CAN-FD格式
CANFD发送的数据打包成一条消息, 分三个段:
- 第一仲裁段 first arbitration phase, 下图左蓝色部分
- 数据段 data phase, 下图中红色部分
- 第二仲裁段 second arbitration phase, 下图右蓝色部分
上图只是标准帧的CAN-FD格式, 扩展帧是在IDE位后再加入18-bit identifier.
第一仲裁段:
- 1位帧起始SOF
- Arbitration field, 仲裁域, ID号和其他位,指示消息的目的(提供或请求数据)以及速度和格式配置(CAN或CAN-FD). 标准帧是
12-bit = 11-bit ID + 1-bit r1
, 扩展帧是32-bit = 11-bit Base ID + 1-bit r1 + 1-bit IDE + 18-bit Extended-ID + 1-bit r0
, 其中IDE应为identifier extension
, 该位用于区分标准帧和扩展帧.
仲裁段和数据段的分割点在BRS位, BRS: Bit rate switching, 该位用于指示是否变换速率, 如从500K切换到2M, 或者保持500K不变.
数据段:
- 数据长度代码(DLC, Data Length Code), 指示消息包含多少数据字节, 只有4bit共16种, 所以只能[0,8], 12, 16, 20, 24, 32, 48, 64这16种固定的字节数.
- 用户希望发送的数据
- 循环冗余序列校验(CRC), 通过以下方式确保数据传输的完整性:17级多项式用于对16字节内的有效载荷进行CRC校验, 21级多项式用于对16字节与64字节之间的有效载荷进行校验
- 显性位
第二仲裁段:
- 总线上其他节点发送的确认接收器(ACK)(如果至少一个已成功接收到消息)
- 帧结束(EOF), 在IFS期间不发送消息, 目的是将当前帧与下一帧分开
搬来一些其它CAN-FD的图进一步了解:
下图中CAN中标识远程帧的RRS = remote request substitution, CAN-FD不用RRS, SRR = substitute remote request, 区分标准帧和扩展帧的IDE = identifier extension, FDF = flexible data rate format, d = dominant, r = recessive, r0 = reserved
:
下图中 IDE (identifier extension), FDF (flexible data rate format), BRS (bit rate switch; recessive, if alternate bit-rate), ESI (error state indicator; recessive, if error passive)
:
FDCAN的两个变体:
- Long Frame Mode (LFM) 长帧模式, 速率不变, 长度从最大8字节提到最大64字节
- Fast Frame Mode (FFM) 快帧模式, 控制域, 数据域 和 CRC域 传输在更高的速率, STM32最高8Mbit/s, 设置BRS位.
一般将长帧模式和快帧模式联合使用.
CAN 2.0 VS CAN-FD
以标准帧为例:
RTR = Remote transmission request:
- CAN 2.0 中RTR为显性(dominant, 逻辑0)表示数据帧, 为隐性(recessive, 逻辑1)表示远程帧
- CANFD 仅支持数据帧, RTR始终为显性数据帧, 可以理解为保留不用
IDE 位保持不变, 用于区分标准帧还是扩展帧.
CANFD在控制字段中新增了3个位:
- EDL, Extend data length, 扩展数据长度位, 隐性(逻辑1)表示CANFD帧, 显性(逻辑0, R0)表示CAN2.0帧
- BRS, Bit rate switching, 位速率切换, 指示是否切换高速率传输, 如从500K切换到2M
- ESI, Error state indicator, 错误状态指示器, 指示节点处于 error-active模式 还是 error-passive模式
DLC, Data Length Code, 数据长度代码, CAN 2.0和CANFD处于相同位置和同样的4-bit长度, 但8以后的值表示意义不同:
CANFD有效载荷从CAN 2.0的最大8字节提升到最大64字节, 改善网络带宽, 对多包处理需求减少, 因此, 通过为CRC字段添加更多位来增强消息完整性:
- 有效载荷在16字节及以内, CRC以17-bit编码
- 有效载荷在20字节及以上, CRC以21-bit编码
另外, 为了确保CAN-FD帧的鲁棒性,填充位机制支持CRC字段.
可参考 CAN 总线 之六 BOSCH CAN 比特位填充(编码规则)、归零编码(RZ)和不归零编码(NRZ), 在相同极性的 5 个连续位之后使用位填充, 相同极性的六个连续比特被认为是错误, 位填充方案的一个副作用是,接收到的消息中的少量位错误可能会破坏解填充过程(接收器需要去除填充位),从而导致大量错误在解填充消息中传播。这降低了 CRC 针对原始错误提供的保护级别。该协议的不足之处已经在 CAN FD 帧中得到了解决,具体方法是 通过使用固定填充比特和记录插入的填充比特数的计数器的组合。
下图给出对比总结, 主要是 数据有效负载的增加以及CAN-FD中可用的BRS,EDL和ESI位确保的更高速度:
STM32 FDCAN 外设特性
特性:
- 符合CAN 2.0的A,B部分和ISO 11898-1:2015,-4
- 可访问的10 KB RAM内存,因为是32-bit, 1 word = 4 bytes, 最多可分配2560个字, 所有CAN外设共用
- 改进的接收过滤
- 两个可配置的接收FIFO
- 多达64个专用接收缓冲区
- 接收高优先级消息时的单独信令
- 多达32个专用的发送缓冲区
- 可配置的发送FIFO和发送队列
- 可配置的发送事件FIFO
- 时钟校准单元
- 收发器延迟补偿
一个FDCAN外设框图:
注意Shared Memory, 所有的FDCAN外设共用.
STM32G4的3路FDCAN框图:
仲裁段位速率最高1Mbit/s, 数据段位速率最高8Mbit/s.
支持:
- 2 maskable interrupts per controller
- power-down
- CAN error logging
- AUTOSAR 和 J1939
位时间和采样点
同一网络中的所有节点采样点需一致, 一般在75%~80%, 不然发送时, 总线会进入 error passive state, 或者 bus-off.
一般主时钟设为 40MHz(可以分频后实现), 然后再设置其它参数, 如160MHz主时钟的STM32G4:
FDCAN在500K@2M时的配置:
计算公式参考:
/*
* Bit timing & sampling
* Tq = (BRP+1)/Fcan if DIV8 = 0
* Tq = 8*(BRP+1)/Fcan if DIV8 = 1
* TSync = 1.Tq
* TSeg1 = (TSEG1+1)*Tq >= 3Tq
* TSeg2 = (TSEG2+1)*Tq >= 2Tq
* Bit Time = TSync + TSeg1 + TSeg2 >= 8Tq
*
* Resynchronization:
*
* Tsjw = (SJW + 1)*Tq
* TSeg1 >= Tsjw + Tprop
* TSeg2 >= Tsjw
*/
123456789101112131415
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
仲裁段:
- 时钟 = 160M / Nominal Prescaler = 160M / 4 = 40MHz
- 1 CAN bit = (1 + Tseg1 + Tseg2) TQ = 80 TQ (time quanta)
- 通信速率 = 40M / (1 + Tseg1 + Tseg2) = 40M / (63 + 16 + 1) = 500Kbit/s
- 采样点 = (1 + Tseg1) / ((1 + Tseg1 + Tseg2)) = 64 / 80 = 0.8
数据段:
- 时钟 = 160M / Data Prescaler = 160M / 4 = 40MHz
- 1 CAN bit = (1 + DTseg1 + DTseg2) TQ = 20 TQ (time quanta)
- 通信速率 = 40M / (1 + DTseg1 + DTseg2) = 40M / (14 + 5 + 1) = 2Mbit/s
- 采样点 = (1 + DTseg1) / ((1 + DTseg1 + DTseg2)) = 15 / 20 = 0.75
可以通过 KVASER Bit Timing Calculator for CANFD 这个网站在线计算.
时钟源默认40M, 不改变:
位速率设置500K@2M:
仲裁段采样点改为80%:
数据段采样点改为75%:
最后算出Tseg1, Tseg2, SJW的值:
PEAK的Bit Rate Calculation Tool 用着也很不错
当然配置方式不止这几种, 周立功ZCANPRO软件安装目录下的baudcal.exe
也能算:
stm32仲裁段的计算可以参考这个网站 CAN Bit Time Calaulation:
或者 参考 S32K系列学习笔记——FlexCAN 模块介绍与例程建立, 遵循一些算法自己计算:
CAN 波特率周期会被分为 12-20 个时间段
采样点通常选在波特率周期的 75%-80% 段
剩余的 20%-25% 会作为 Phase_Seg2 的值
Phase_Seg1 的值会与 Phase_Seg2 的值相同
Sync_Seg 是 1 个时间段
Resync Jumo Width(RJW+1)= Phase_Seg2(如果 Phase_Seg2<4,(RJW+1)=4)
123456
- 1
- 2
- 3
- 4
- 5
- 6
- 7
Message RAM
所有发送和接收的消息都存储在CAN消息RAM中. 在CAN消息RAM初始化期间,用户必须定义11位过滤器,29位过滤器,接收到的消息以及要传输的消息的存储位置.
CAN消息RAM分为四个不同的部分:
- 过滤(11位过滤器,29位过滤器)
- 接收(Rx FIFO 0,Rx FIFO 1,Rx Buffer)
- 发送(Tx event FIFO,Tx Buffer)
- 触发存储器(Trigger Memory)
如下图所示:
乍一看不得了, 但这只是1路CANFD独享10KB RAM的最大分配量, 如果有多个CANFD外设, 比如STM32G4的3路CANFD一块用, 每路分到的资源就可怜了.
FDCAN外设的所有部分都可以由用户配置。所有部分的所有元素之和不得超过CAN消息RAM的总大小。该RAM通过消除多余部分并为其他部分扩展足够的内存,提供了更高的灵活性和性能。
根据上图所示的顺序,在CAN消息RAM中以动态且连续的方式分配每个部分的已组态元素;但是,为了避免超过RAM的风险以及出于可靠性的原因,没有为每个段分配特定的自己的开始和结束地址。
为了所谓的动态分配, 为了从10KB内存抠出来点给其它外设用, 挺煞费苦心的, 非得个人分配的话也很容易埋坑.
消息的接收和发送意味着在RAM级别存储“元素”(element)。该“元素”仅包含标识符(identifier),DLC,控制位(ESI,XTD,RTR,BRS,FDF),数据字段和用于控制的特定传输/接收位字段。 CAN消息的其余位由硬件自动处理,不会保存在RAM中。
用于控制接收的特定位字段是过滤索引(filter index),接受的不匹配帧和Rx时间戳。
用于传输的特定位字段是消息标记(message marker)和event FIFO控制位.
Tx buffer, Tx FIFO, Tx queue 或 Rx buffer 的 每个element分配word的数量通过以下方式计算:
- Header信息(两个保留的32-bit-words, 相当于8字节)以分配identifier,DLC字段,控制位和特定的发送/接收位字段
- 数据(足够的32-bit-words)包含每个数据字段的字节数
计算公式为: Element size (in words) = Header information (2 words) + Data (data field/4), data field在0~8时Data取2 words
, 如下表:
常说的MTU应该是这个东西, 如 以太网mtu值设定为1500, CAN2.0的mtu为16, CANFD的mtu为72. 一帧CANFD 最大 72 bytes => 18 words => 1 T/R elements, 此时有效利用率 64 / 72 = 88.88%.
element 总结如下:
- 11-bit filter, 标准帧滤波器, 因为滤波器ID设置0~0x7FF, 共两个, 通常如掩码模式下一个设置为CAN_ID, 一个设置为掩码, 占用2*2=4个字节, 1标准帧滤波器element = 4 bytes = 1 word
- 29-bit filter, 扩展帧滤波器, 因为滤波器ID设置0~0x1FFFFFFF, 共两个, 通常如掩码模式下一个设置为CAN_ID, 一个设置为掩码, 占用2*4=8个字节, 1扩展帧滤波器element = 8 bytes = 2 words
- 发送接收不仅要接收有效数据(最大64字节), 也要包括数据链路层的东西(BRS等), 有可能收标准CAN, 也有可能收CANFD, 有可能标准帧, 也有可以能扩展帧, 按最大算, CANFD MTU固定为72, 所以 1 Rx element = 72 bytes = 18 words, 64 * 18 = 1152
下图是10KB RAM分给2路FDCAN的示例:
可以看到分配还是很自由的.
如果实在讨厌这些东西, 不看也行, STM32CubeMX生成的代码初始化部分会自动调用分配RAM的函数, 截取STM32G474使用3路CANFD部分自动生成的相关代码如下:
#define PERIPH_BASE (0x40000000UL) /*!< Peripheral base address */
#define APB1PERIPH_BASE PERIPH_BASE
#define SRAMCAN_BASE (APB1PERIPH_BASE + 0xA400UL)
#define SRAMCAN_FLS_NBR (28U) /* Max. Filter List Standard Number /
#define SRAMCAN_FLE_NBR ( 8U) / Max. Filter List Extended Number /
#define SRAMCAN_RF0_NBR ( 3U) / RX FIFO 0 Elements Number /
#define SRAMCAN_RF1_NBR ( 3U) / RX FIFO 1 Elements Number /
#define SRAMCAN_TEF_NBR ( 3U) / TX Event FIFO Elements Number /
#define SRAMCAN_TFQ_NBR ( 3U) / TX FIFO/Queue Elements Number */
#define SRAMCAN_FLS_SIZE ( 1U 4U) / Filter Standard Element Size in bytes /
#define SRAMCAN_FLE_SIZE ( 2U 4U) /* Filter Extended Element Size in bytes /
#define SRAMCAN_RF0_SIZE (18U 4U) /* RX FIFO 0 Elements Size in bytes /
#define SRAMCAN_RF1_SIZE (18U 4U) /* RX FIFO 1 Elements Size in bytes /
#define SRAMCAN_TEF_SIZE ( 2U 4U) /* TX Event FIFO Elements Size in bytes /
#define SRAMCAN_TFQ_SIZE (18U 4U) /* TX FIFO/Queue Elements Size in bytes */
#define SRAMCAN_FLSSA ((uint32_t)0) /* Filter List Standard Start
Address /
#define SRAMCAN_FLESA ((uint32_t)(SRAMCAN_FLSSA + (SRAMCAN_FLS_NBR SRAMCAN_FLS_SIZE))) /* Filter List Extended Start
Address /
#define SRAMCAN_RF0SA ((uint32_t)(SRAMCAN_FLESA + (SRAMCAN_FLE_NBR SRAMCAN_FLE_SIZE))) /* Rx FIFO 0 Start Address /
#define SRAMCAN_RF1SA ((uint32_t)(SRAMCAN_RF0SA + (SRAMCAN_RF0_NBR SRAMCAN_RF0_SIZE))) /* Rx FIFO 1 Start Address /
#define SRAMCAN_TEFSA ((uint32_t)(SRAMCAN_RF1SA + (SRAMCAN_RF1_NBR SRAMCAN_RF1_SIZE))) /* Tx Event FIFO Start
Address /
#define SRAMCAN_TFQSA ((uint32_t)(SRAMCAN_TEFSA + (SRAMCAN_TEF_NBR SRAMCAN_TEF_SIZE))) /* Tx FIFO/Queue Start
Address /
#define SRAMCAN_SIZE ((uint32_t)(SRAMCAN_TFQSA + (SRAMCAN_TFQ_NBR SRAMCAN_TFQ_SIZE))) /* Message RAM size */
/**
- @brief Calculate each RAM block start address and size
- @param hfdcan pointer to an FDCAN_HandleTypeDef structure that contains
-
the configuration information for the specified FDCAN.
- @retval none
/
static void FDCAN_CalcultateRamBlockAddresses(FDCAN_HandleTypeDef hfdcan)
uint32_t RAMcounter;
uint32_t SramCanInstanceBase = SRAMCAN_BASE;
#if defined(FDCAN2)
if (hfdcan->Instance FDCAN2)
SramCanInstanceBase += SRAMCAN_SIZE;
#endif /* FDCAN2 */
#if defined(FDCAN3)
if (hfdcan->Instance FDCAN3)
SramCanInstanceBase += SRAMCAN_SIZE 2U;
#endif / FDCAN3 */
/* Standard filter list start address */
hfdcan->msgRam.StandardFilterSA = SramCanInstanceBase + SRAMCAN_FLSSA;
/* Standard filter elements number */
MODIFY_REG(hfdcan->Instance->RXGFC, FDCAN_RXGFC_LSS, (hfdcan->Init.StdFiltersNbr << FDCAN_RXGFC_LSS_Pos));
/* Extended filter list start address */
hfdcan->msgRam.ExtendedFilterSA = SramCanInstanceBase + SRAMCAN_FLESA;
/* Extended filter elements number */
MODIFY_REG(hfdcan->Instance->RXGFC, FDCAN_RXGFC_LSE, (hfdcan->Init.ExtFiltersNbr << FDCAN_RXGFC_LSE_Pos));
/* Rx FIFO 0 start address */
hfdcan->msgRam.RxFIFO0SA = SramCanInstanceBase + SRAMCAN_RF0SA;
/* Rx FIFO 1 start address */
hfdcan->msgRam.RxFIFO1SA = SramCanInstanceBase + SRAMCAN_RF1SA;
/* Tx event FIFO start address */
hfdcan->msgRam.TxEventFIFOSA = SramCanInstanceBase + SRAMCAN_TEFSA;
/* Tx FIFO/queue start address */
hfdcan->msgRam.TxFIFOQSA = SramCanInstanceBase + SRAMCAN_TFQSA;
/* Flush the allocated Message RAM area /
for (RAMcounter = SramCanInstanceBase; RAMcounter < (SramCanInstanceBase + SRAMCAN_SIZE); RAMcounter += 4U)
(uint32_t *)(RAMcounter) = 0x00000000U;
HAL_StatusTypeDef HAL_FDCAN_Init(FDCAN_HandleTypeDef *hfdcan)
...
FDCAN_CalcultateRamBlockAddresses(hfdcan);
...
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
折算一下(如有错误, 请指正):
//11-bit filter 基地址相对偏移, 上面定义1路CANFD最多28个标准帧滤波器
SRAMCAN_FLSSA = 0;
//29-bit fliter 基地址相对偏移, 上面定义1路CANFD最多8个扩展帧滤波器
SRAMCAN_FLESA = SRAMCAN_FLSSA + (SRAMCAN_FLS_NBR * SRAMCAN_FLS_SIZE) = 0 + 28 * 4 = 112;
//Rx FIFO 0 基地址相对偏移, Rx FIFO 0 的深度也就3, 最多可扔进去3个CANFD帧, 可怜弱小无助...
SRAMCAN_RF0SA = SRAMCAN_FLESA + (SRAMCAN_FLE_NBR * SRAMCAN_FLE_SIZE) = 112 + 8 * 2 * 4 = 176;
//Rx FIFO 1 基地址相对偏移, Rx FIFO 1 的深度也是3
SRAMCAN_RF1SA = SRAMCAN_RF0SA + (SRAMCAN_RF0_NBR * SRAMCAN_RF0_SIZE) = 176 + 3 * 18 * 4 = 392;
//Tx event FIFO 基地址相对偏移, 可以存3个Tx event
SRAMCAN_TEFSA = SRAMCAN_RF1SA + (SRAMCAN_RF1_NBR * SRAMCAN_RF1_SIZE) = 392 + 3 * 18 * 4 = 608;
//Tx buffers 基地址相对偏移, Tx buffers 也就 3帧 CANFD...
SRAMCAN_TFQSA = SRAMCAN_TEFSA + (SRAMCAN_TEF_NBR * SRAMCAN_TEF_SIZE) = 608 + 3 * 2 * 4 = 632;
// Message RAM Size
SRAMCAN_SIZE = SRAMCAN_TFQSA + (SRAMCAN_TFQ_NBR * SRAMCAN_TFQ_SIZE) = 632 + 3 * 18 * 4 = 848 = 0x350;
FDCAN1 基地址 = SRAMCAN_BASE = 0x40000000 + 0xA400 = 0x4000 A400;
FDCAN2 基地址 = SRAMCAN_BASE + SRAMCAN_SIZE = 0x4000 A400 + 0x350 = 0x4000 A750;
FDCAN3 基地址 = SRAMCAN_BASE + SRAMCAN_SIZE 2 = 0x4000 A400 + 0x350 2 = 0x4000 AAA0;
123456789101112131415161718
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
上面的代码中总结一下, STM32G474一共3个CANFD外设, 其中每个CANFD外设:
- 最多28个标准帧滤波器(Cube软件中能设置的最大值)
- 最多8个扩展帧滤波器(Cube软件中设置的最大值)
- Rx FIFO 0 能缓存 3 帧 CANFD
- Rx FIFO 1 能缓存 3 帧 CANFD
- Tx buffer 能缓存 3 帧 CANFD
- 3个CANFD外设共用 848 * 3 = 2544 bytes的空间, 没有超过 10 Kbytes = 10240 / 4 =2560words 空间的限制
滤波器设置
STM32所有的CANFD外设合计最多可以同时设置 128x 11-bit filter + 64x 29-bit filter, 但具体到各个型号又有不同, 如STM32G4号称每路 Each set has 28 entries : 28x 11-bit filter entries+ 28x 29-bit filter entries
, 但Cube里面配置每路最多 28x 11-bit filter entries + 8x 29-bit filter
, 可以试试手动更改生成代码中宏定义SRAMCAN_FLE_NBR
的值.
可以将这些过滤器分配给Rx FIFO 0/1或专用的Rx缓冲区。当FDCAN执行验收过滤时,它总是从过滤器元素#0开始,并遍历过滤器列表以查找匹配元素。接受过滤在该消息的第一个匹配元素处停止,随后的过滤元素被注释。因此,配置的过滤器元素的顺序对过滤过程的性能有重大影响。用户选择启用或禁用每个过滤器元素,并可以将每个元素配置为接受或拒绝过滤。每个过滤器元素可以配置为:
- Range filter, 范围过滤器:该过滤器与标识符在两个ID定义的范围内的所有邮件匹配。
- Filter for one or two dedicated IDs, 专用ID过滤器:可以配置为与一个或两个特定标识符匹配。
- Classic bit mask filter, 经典位掩码过滤器:通过对接收到的标识符的位进行掩码来匹配标识符组。配置的第一个ID用作消息ID过滤器,第二个ID用作过滤器掩码。过滤器上的每个零位都会掩盖已配置的ID过滤器的相应位位置。注意:如果所有位均等于1,则仅当接收到的消息ID和消息ID过滤器相同时才会匹配。如果所有掩码位都等于0,则所有消息ID都匹配。
当收到高优先级消息时,FDCAN可以通知用户。此通知可用于监视传入的高优先级消息的状态并启用对这些元素的快速访问。FDCAN在消息过滤器的帮助下检测到高优先级消息。过滤器元素提供与高优先级消息相关的以下设置:
- 设置优先级并在过滤器匹配的情况下存储在FIFO 0/1中:如果此消息过滤器匹配,则FDCAN通知高优先级消息到达并将其存储在Rx FIFO 0/1中.
- 如果过滤器匹配,则设置优先级:如果此消息过滤器匹配,则FDCAN通知高优先级消息到达,但不存储该元素。
如设置全接收的一段代码:
void fdcan2_filter_config(void) sFilterConfig2.IdType = FDCAN_STANDARD_ID; sFilterConfig2.FilterIndex = 0; sFilterConfig2.FilterType = FDCAN_FILTER_MASK; sFilterConfig2.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; sFilterConfig2.FilterID1 = 0; sFilterConfig2.FilterID2 = 0; if (HAL_FDCAN_ConfigFilter(&hfdcan2, &sFilterConfig2) != HAL_OK) Error_Handler();
sFilterConfig2<span class="token punctuation">.</span>IdType <span class="token operator">=</span> FDCAN_EXTENDED_ID<span class="token punctuation">;</span> sFilterConfig2<span class="token punctuation">.</span>FilterIndex <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> sFilterConfig2<span class="token punctuation">.</span>FilterType <span class="token operator">=</span> FDCAN_FILTER_MASK<span class="token punctuation">;</span> sFilterConfig2<span class="token punctuation">.</span>FilterConfig <span class="token operator">=</span> FDCAN_FILTER_TO_RXFIFO0<span class="token punctuation">;</span> sFilterConfig2<span class="token punctuation">.</span>FilterID1 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> sFilterConfig2<span class="token punctuation">.</span>FilterID2 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">HAL_FDCAN_ConfigFilter</span><span class="token punctuation">(</span><span class="token operator">&</span>hfdcan2<span class="token punctuation">,</span> <span class="token operator">&</span>sFilterConfig2<span class="token punctuation">)</span> <span class="token operator">!=</span> HAL_OK<span class="token punctuation">)</span> <span class="token punctuation"><!-- --></span> <span class="token function">Error_Handler</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation"></span> <span class="token comment">/* Configure global filter on both FDCAN instances: Filter all remote frames with STD and EXT ID Reject non matching frames with STD ID and EXT ID */</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">HAL_FDCAN_ConfigGlobalFilter</span><span class="token punctuation">(</span><span class="token operator">&</span>hfdcan2<span class="token punctuation">,</span> FDCAN_REJECT<span class="token punctuation">,</span> FDCAN_REJECT<span class="token punctuation">,</span> FDCAN_FILTER_REMOTE<span class="token punctuation">,</span> FDCAN_FILTER_REMOTE<span class="token punctuation">)</span> <span class="token operator">!=</span> HAL_OK<span class="token punctuation">)</span> <span class="token punctuation"><!-- --></span> <span class="token function">Error_Handler</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation"></span> <span class="token comment">/* Activate Rx FIFO 0 new message notification on both FDCAN instances */</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">HAL_FDCAN_ActivateNotification</span><span class="token punctuation">(</span><span class="token operator">&</span>hfdcan2<span class="token punctuation">,</span> FDCAN_IT_RX_FIFO0_NEW_MESSAGE<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">!=</span> HAL_OK<span class="token punctuation">)</span> <span class="token punctuation"><!-- --></span> <span class="token function">Error_Handler</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation"></span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">HAL_FDCAN_ActivateNotification</span><span class="token punctuation">(</span><span class="token operator">&</span>hfdcan2<span class="token punctuation">,</span> FDCAN_IT_BUS_OFF<span class=&
以上是关于canfd基础的主要内容,如果未能解决你的问题,请参考以下文章
《Entity Framework 6 Recipes》翻译系列 -----第二章 实体数据建模基础之有载荷和无载荷的多对多关系建模 (转)
BSP视频教程BSP视频教程第26期:CAN/CANFD/CANopen专题,CANFD整个运行机制精讲,图文并茂,配合综合实战演练(2023-05-15)