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

STM32G474_FDCAN的普通CAN模式使用(寄存器开发)

[复制链接]
STMCU小助手 发布时间:2022-10-12 22:59
FDCAN 与 经典CAN 的最直观差别就是数据帧部分,FDCAN的数据帧波特率可变,并且数据大小不局限于 8 Bytes ,最高支持 64 Bytes 的数据传输。详细差别见 传送门: CAN FD 与 CAN协议区别–简单易懂协议详解 。

1. FDCAN的框图

20210706100113799.png

根据上图可以看到,FDCAN 有两个时钟域,APB总线接口和CAN内核时钟。FDCAN的波特率取决于内核时钟;寄存器的配置、消息RAM等,走的是APB时钟。FDCAN的APB时钟在RCC_APB寄存器中配置,内核时钟在RCC_CCIPR寄存器中配置(下一章)。
FDCAN有两个中断线,这两个中断线可以单独的打开或关闭,在FDCAN_ILE寄存器中配置。
其他具体介绍参考DM00355726_ENV4手册的1947页(RM0440手册官方下载传送门)。

2. FDCAN的时钟与波特率
2.1 fdcan_clk

几乎所有通信都可在RCC中配置时钟选择,FDCAN的时钟(fdcan_clk)可在RCC_CCIPR寄存器中进行配置。

20210706100630241.png

FDCAN1/2/3 的内核时钟是通用的,可以在配置FDCAN1的时候,配置 CKDIV 寄存器进行进一步的分频(INIT标志位置位才可配置该寄存器),这里配置的CKDIV影响到 FDCAN2 和 FDCAN3。

2.2 fdcan_tq_ck
根据系统框图可看到,系统输入的时钟可通过 fdcan_clk 分频得到 fdcan_tq_ck ,在 FDCAN_CKDIV 寄存器中配置分频系数。

851b07dba3404c21bcd98f7a4590dabd.png

可以认为FDCAN内核用的时钟都是fdcan_tq_ck ,只不过 fdcan_tq_ck 为1分频时候认为是fdcan_clk 。

2.3 波特率
FDCAN模块的bit采样分三段:

2021070610242646.png


波特率公式如下:
Z)68{@VPG1Y@2)]D{AJ)%RC.png
注意:
1、由于 FDCAN 与 经典CAN 的帧格式有点差异,其数据帧波特率可变,因此在这里分出普通CAN和数据bit时间
2、数据 和 普通 bit 时间寄存器名称不一样,数据波特率寄存器 FDCAN_DBTP ,一般帧波特率寄存器为 FDCAN_NBTP 。当使用经典模式CAN时, FDCAN_DBTP 配置被忽略

3. FDCAN的地址分布
3.1 总体分布


a125c76d6e79479b84bd735716bd3974.png

由于头文件中没有该寄存器的宏定义,因此需要自己建立宏定义。
G474的FDCAN外设一共有3组(FDCAN1,FDCAN2,FDCAN3),寄存器配置分为3个,消息RAM也分为3组。

3.2 Message RAM

20210707172812455.png

1个 信息RAM 有 212 words 的大小,即 212 × 4 = 848 Bytes 。

根据3.1和3.2可以先把 消息RAM 的宏定义写好

  1. #define FDCANs_MESSAGE_RAM_BASE                                        0x4000A400
  2. #define FDCAN1_RAM_BASE                                                        (FDCANs_MESSAGE_RAM_BASE)
  3. #define FDCAN2_RAM_BASE                                                        (FDCAN1_RAM_BASE + 0x00000350)
  4. #define FDCAN3_RAM_BASE                                                        (FDCAN2_RAM_BASE + 0x00000350)

  5. typedef struct
  6. {
  7.         uint32_t FILTER_11BIT[28];                //0x4000A400 ~ 0x4000A470
  8.         uint32_t FILTER_29BIT[8][2];        //0x4000A470 ~ 0x4000A4B0
  9.         uint32_t Rx_FIFO_0[3][18];                //0x4000A4B0 ~ 0x4000A588
  10.         uint32_t Rx_FIFO_1[3][18];                //0x4000A588 ~ 0x4000A660
  11.         uint32_t Tx_FIFO[6];                        //0x4000A660 ~ 0x4000A678
  12.         uint32_t Tx_BUFFER[3][18];                //0x4000A678 ~ 0x4000A750
  13. }FDCAN_RAM_Struct;

  14. #define FDCAN1_RAM                                                                ((FDCAN_RAM_Struct *)FDCAN1_RAM_BASE)
  15. #define FDCAN2_RAM                                                                ((FDCAN_RAM_Struct *)FDCAN2_RAM_BASE)
  16. #define FDCAN3_RAM                                                                ((FDCAN_RAM_Struct *)FDCAN3_RAM_BASE)
复制代码

注意!!! 上面的代码第1行的宏定义部分,偏移为 0x350 而不是 0x400。
曾经我根据 3.1里面的图片进行配置(0x400也就是1KB),结果只有FDCAN1好用,FDCAN2和FDCAN3都不能使用,困扰了我一天来找这个问题,后来使用 0x350 就可以了,可能是手册写错了,也可能是我的理解与有误。
这里是个坑,希望大家能够规避一下。

4. FDCAN中断配置
4.1 中断寄存器

FDCAN中断配置中,涉及的寄存器为
FDCAN_IE 与其他外设的IE一样,中断使能寄存器,在这里选择使用的中断,在代码中会注释
FDCAN_ILE 中断总线使能。FDCAN中将中断分为了两个分支,即有两个中断函数
FDCAN_ILS 中断总线选择。在这个寄存器中配置哪个中断归属于哪个中断分支,默认都为分支0.

888efdd828cb4f43985aa1eff03a45b1.png

5. FDCAN的筛选器
5.1 筛选器的特征

每个筛选器可配置为
• 范围筛选
• 指定ID筛选
• 屏蔽典型bit筛选
每个过滤器元件可配置为接受或拒绝过滤
每个过滤器元素可以单独启用/禁用
过滤器是按顺序检查的,执行在第一个匹配的过滤器元素时停止
相关的寄存器:全局筛选配置(RXGFC)、拓展ID和掩码(XIDAM)

如果需要接收数据,一定要配置筛选器,否则会什么也接受不到。

5.2 11-bit 筛选器的格式

20210708133142322.png

这里根据手册的翻译进行配置就好,29-bit 的筛选器也是如此,手册里全有,我就不放图片了,太占地方。

通过配置筛选器,可以使FDCAN外设接收其他模块发来的信息,在筛选器中配置接收消息的FIFO或者拒收消息。配置筛选器是FDCAN接收的关键。
筛选器的配置不受 INIT 和 CCE 标志位的限制,可随时配置。

6. FIFO模式与Queue模式
FIFO模式与队列模式的区别为:

队列模式的优先级遵循邮箱0优先级最高,其次是1,最后是2,如果当前3个邮箱全有数据,优先发送邮箱0的数据
FIFO模式的优先级是遵循哪个数据先进入的邮箱,与其所在的索引地址无关,即:如果当前3个邮箱全有数据,邮箱2被最先写入,则优先发送邮箱2的数据。

6.1 TX FIFO 的寄存器格式

546b2acad34a46fc924461372beca1a4.png
具体说明见手册1969页,我就不复制了,翻一下就能懂每个BIT代表的意思。
根据上表,我们就可以写出对应各个标志位的结构体,方便后期指针使用。
由于其buffer支持 11-bit ID 和 29-bit ID

7. FDCAN的初始化
IO口配置我就不介绍了,想必大家都会配置IO。
1.首先在RCC->APB1RSTR1寄存器中使能RCC_APB1ENR1_FDCANEN,这样FDCAN的寄存器就可以配置了。
2.然后选择FDCAN内核时钟的时钟源,在RCC->CCIPR寄存器的RCC_CCIPR_FDCANSEL中配置。
3.置位INIT标志位,开始配置寄存器(只有INIT标志位置位,才可置位CCE标志位)
4.等待INIT标志位置位
5.置位CCE标志位,解锁受保护的寄存器
6.等待CCE标志位置位
7.配置时钟分频 (FDCAN_CKDIV 寄存器)
8.配置波特率
9.配置中断
10.使能筛选器
11.配置筛选器
清除INIT标志位
到此,FDCAN就配置完了,具体操作见代码
初始化代码见

8. 发送操作
8.1 FDCAN帧模式

FDCAN帧模式由下表各个标志位配置:

2021070611243928.png

根据上表所示,可以通过 CCCR寄存器 和 Tx Buffer 内部的标志位 配合,实现不同模式的CAN。
由于鄙人只想使用 经典CAN,因此将 CCCR寄存器 中的 FDOE 配置为 0,其他标志位我就不管了。

8.2 发送步骤
读取 FDCAN1->TXFQS 是否有可用信箱( FDCAN_TXFQS_TFQF 是否置位)
如果没置位邮箱满标志,则查询 FDCAN_TXFQS_TFQPI 索引,获得的索引就是可以写入的邮箱
将要发送的数据写入刚才读取的索引的 Tx Buffer 中(在这里可以配置发送长度、ID等信息)
置位发送请求
等待发送完成(可以不等待,配置发送完成中断使能后,在中断中置位发送完成标志来判断是否发送完毕)
示例代码见
附录2 发送函数
代码中的部分宏定义是根据手册定义的,由于太长就不放在这里了,完整代码在 代码下载

9. 接收操作
首先配置筛选器来选择接收的消息和接收后存放的FIFO。

接收分为 覆盖模式 和 阻塞模式 。
覆盖模式 顾名思义,就是当FIFO满了以后,接收到新消息后覆盖老消息。
阻塞模式 就是当FIFO满了之后,忽略新消息,保留老消息。

当 Rx FIFO 0 接收到消息后,将会在 FDCAN_RXF0S 寄存器中 F0GI 标志位指示新消息存储索引,当 CPU 读取这些消息后,务必将最后 F0GI 的值写入到 FDCAN_RXF0A 的 F0AI 标志位,来确认来读取完毕,这会将 FDCAN_RXF0S寄存器中的索引标志位 F0GI 设置为 F0AI + 1 并更新 FIFO 0 的存储计数 (FDCAN_RXF0S 寄存器中 F0FL 标志位,范围0~3),如果不确认读取完毕,将会导致指示索引 F0GI 失效。

接收操作可以在中断中进行,通过配置 FDCAN_IE 寄存器中的相应 中断使能标志位 来开启中断,具体示例见初始化代码。如:使能 FIFO0 接收新消息中断就置位 FDCAN_IE_RF0NE 标志位。

因此,接收操作的步骤为:
1.读取接收的数据
2.确认读取完毕

10. 故障
故障处理这里就不介绍了,值得注意的是:
当CAN两个总线短接,超过一定时间后,FDCAN会因为不能检测到有效电平而置位故障标志,同时置位初始化 INIT 标志,导致CAN关闭,排除硬件故障后可直接复位 INIT 标志来恢复故障前的运行状态(也就是说可以正常收发数据了)。

11. 参考资料传送门
11.1 代码下载(0积分)

代码下载(0积分)

11.2 其他 CAN 知识了解
其他 CAN 知识了解

附录1. FDCAN寄存器配置
返回第7章 FDCAN的初始化
返回第9章 接收操作

  1. /**
  2. * @description: FDCAN1 初始化
  3. * @param {*}
  4. * @return {*}
  5. * @author: XL
  6. */
  7. void FDCAN1_Function_Init(void)
  8. {
  9.         //在RCC_CCIPR寄存器中选择FDCAN时钟为HSE,即8MHz
  10.         //
  11.         FDCAN1->CCCR |= FDCAN_CCCR_INIT;                                //步骤3 置位INIT标志,开始配置寄存器(只有INIT标志位置位,才可置位CCE标志位)
  12.         while (!(FDCAN1->CCCR & FDCAN_CCCR_INIT));                //步骤4 等待INIT标志位置位
  13.         FDCAN1->CCCR |= FDCAN_CCCR_CCE;                                        //步骤5 置位CCE标志位,解锁受保护的寄存器
  14.         while (!(FDCAN1->CCCR & FDCAN_CCCR_CCE));                //步骤6 等待CCE标志位置位
  15.         FDCAN_CONFIG->CKDIV = 0x0;                                                //步骤7 配置时钟分频
  16.                                                                                                 //只允许在FDCAN1初始化中配置
  17.                                                                                                 //fdcan_clk = 168 / 1 = 168 MHz,影响到FDCAN2、3(FDCAN_CONFIG地址上来说,还是属于FDCAN1)
  18.         FDCAN1->CCCR |= 0
  19.                                         // |FDCAN_CCCR_NISO                                //bit15: 【0|ISO11898-1】【1|CANFD v1.0】
  20.                                         // |FDCAN_CCCR_TXP                                        //bit14: 【1|在下上一个成功帧后暂停两个bit再起始】
  21.                                         // |FDCAN_CCCR_EFBI                                //bit13: 【1|同步检测边沿需要两个显性tq】
  22.                                         // |FDCAN_CCCR_PXHD                                //bit12: 【0|启动协议异常处理】【1|禁用协议异常处理】
  23.                                         // |FDCAN_CCCR_BRSE                                //bit09: 【1|启用波特率切换】
  24.                                         // |FDCAN_CCCR_FDOE                                //bit08: 【0|FD操作禁止】【1|FD操作使能】
  25.                                         // |FDCAN_CCCR_TEST                                //bit07: 【1|测试模式使能】
  26.                                         |FDCAN_CCCR_DAR                                        //bit06: 【0|启用发送失败后自动重传】【1|禁止自动重传】
  27.                                         // |FDCAN_CCCR_MON                                        //bit05: 【0|总线监控模式禁止】【1|总线监控模式使能】
  28.                                         // |FDCAN_CCCR_CSR                                        //bit04: 【0|无时钟停止请求】【1|时钟停止请求,当时钟停止请求发生,先置位INIT在置位CSA在所有传输请求完成并且CAN总线空闲】
  29.                                         // |FDCAN_CCCR_CSA                                        //bit03: 【0|没有时钟停止】【1|FDCAN可通过停止APB时钟和内核时钟来进行掉电】
  30.                                         // |FDCAN_CCCR_ASM                                        //bit02: 【1|启用限制模式,限制模式下不会主动发送数据】
  31.                                         // |FDCAN_CCCR_CCE                                        //bit01: 【1|允许配置受保护的寄存器,INIT标志位必须置位】
  32.                                         // |FDCAN_CCCR_INIT                                //bit00: 【1|初始化开始】
  33.                                         ;
  34.         // FDCAN1->DBTP = 0                                                                //数据帧的波特率(FDCAN模式需要配置,经典CAN不需要配置)
  35.         //                                 |FDCAN_DBTP_TDC                                        //bit23: 【1|收发延时补偿使能】
  36.         //                                 |(0 << FDCAN_DBTP_DBRP_Pos)                //bit[20:16]: tq = (BRP + 1)*fdcan_clk
  37.         //                                 |(22 << FDCAN_DBTP_DTSEG1_Pos)        //bit[12:08]: 一阶段采样                        8000000
  38.         //                                 |(7 << FDCAN_DBTP_DTSEG2_Pos)        //bit[07:04]: 二阶段采样 波特率 = 8000000/(3+DTSEG1+DTSEG2) = 8000000/32 = 250k
  39.         //                                 |(4 << FDCAN_DBTP_DSJW_Pos)                //bit[03:00]: 同步脉宽
  40.         //                                 ;
  41.         FDCAN1->NBTP = 0                                                                        //步骤8 配置波特率
  42.                                         |(4 << FDCAN_NBTP_NSJW_Pos)                //bit[31:25]: 同步脉宽 必须小于SEG2
  43.                                         |(0 << FDCAN_NBTP_NBRP_Pos)                //bit[24:16]: BRP   tq = (BRP + 1)*fdcan_clk
  44.                                         |(22 << FDCAN_NBTP_NTSEG1_Pos)        //bit[15:08]: 一阶段采样
  45.                                         |(7 << FDCAN_NBTP_NTSEG2_Pos)        //bit[06:00]: 二阶段采样 波特率 = 8000000/(3+DTSEG1+DTSEG2) = 8000000/32 = 250k
  46.                                         ;
  47.         //步骤9 配置中断
  48.         FDCAN1->IE |= 0
  49.                                         // |FDCAN_IE_ARAE                                        //bit23: 访问保留地址使能
  50.                                         // |FDCAN_IE_PEDE                                        //bit22: 数据阶段协议错误
  51.                                         // |FDCAN_IE_PEAE                                        //bit21: 仲裁阶段协议错误
  52.                                         // |FDCAN_IE_WDIE                                        //bit20: 看门狗使能
  53.                                         // |FDCAN_IE_BOE                                        //bit19: 总线关闭使能
  54.                                         // |FDCAN_IE_EWE                                        //bit18: 警告状态中断使能
  55.                                         // |FDCAN_IE_EPE                                        //bit17: 错误被动中断使能
  56.                                         // |FDCAN_IE_ELOE                                        //bit16: 错误记录语出中断使能
  57.                                         // |FDCAN_IE_TOOE                                        //bit15: 超时中断使能
  58.                                         // |FDCAN_IE_MRAFE                                        //bit14: 信息RAM访问失败中断使能
  59.                                         // |FDCAN_IE_TSWE                                        //bit13: 时间戳重复中断使能
  60.                                         // |FDCAN_IE_TEFLE                                        //bit12: TX事件FIFO元素丢失中断使能
  61.                                         // |FDCAN_IE_TEFFE                                        //bit11: TX时间FIFO满中断使能
  62.                                         // |FDCAN_IE_TEFNE                                        //bit10: TX事件FIFO新元素进入中断使能
  63.                                         // |FDCAN_IE_TFEE                                        //bit09: TXFIFO空中断使能
  64.                                         // |FDCAN_IE_TCFE                                        //bit08: 发送取消完成中断使能
  65.                                         // |FDCAN_IE_TCE                                        //bit07: 传输完成中断使能
  66.                                         // |FDCAN_IE_HPME                                        //bit06: 高优先级消息中断使能
  67.                                         // |FDCAN_IE_RF1LE                                        //bit05: RXFIFO1报文丢失中断使能
  68.                                         // |FDCAN_IE_RF1FE                                        //bit04: RXFIFO1消息满中断使能
  69.                                         |FDCAN_IE_RF1NE                                        //bit03: RXFIFO1新消息中断使能
  70.                                         // |FDCAN_IE_RF0LE                                        //bit02: RXFIFO0报文丢失中断使能
  71.                                         // |FDCAN_IE_RF0FE                                        //bit01: RXFIFO0消息满中断使能
  72.                                         |FDCAN_IE_RF0NE                                        //bit00: RXFIFO0新消息中断使能
  73.                                         ;
  74.         FDCAN1->ILE = 0x00000000
  75.                                         |FDCAN_ILE_EINT1                                        //bit01: 中断总线 fdcan_intr1_it 使能
  76.                                         |FDCAN_ILE_EINT0                                        //bit00: 中断总线 fdcan_intr0_it 使能
  77.                                         ;
  78.         FDCAN1->ILS = 0x00000000                                                //中断总线选择
  79.                                         // |FDCAN_ILS_PERR                                //bit06:
  80.                                                                                                                 // ARAL: Access to reserved address line
  81.                                                                                                                 // PEDL: Protocol error in data phase line
  82.                                                                                                                 // PEAL: Protocol error in arbitration phase line
  83.                                                                                                                 // WDIL: Watchdog interrupt line
  84.                                                                                                                 // BOL: Bus_Off status
  85.                                                                                                                 // EWL: Warning status interrupt line
  86.                                         // |FDCAN_ILS_BERR                                //bit05:
  87.                                                                                                                 // ELOL: Error logging overflow interrupt line
  88.                                         // |FDCAN_ILS_MISC                                //bit04:
  89.                                                                                                                 // TOOL: Timeout occurred interrupt line
  90.                                                                                                                 // MRAFL: Message RAM access failure interrupt line
  91.                                                                                                                 // TSWL: Timestamp wraparound interrupt line
  92.                                         // |FDCAN_ILS_TFERR                                //bit03:
  93.                                                                                                                 // TEFLL: Tx event FIFO element lost interrupt line
  94.                                                                                                                 // TEFFL: Tx event FIFO full interrupt line
  95.                                                                                                                 // TEFNL: Tx event FIFO new entry interrupt line
  96.                                                                                                                 // TFEL: Tx FIFO empty interrupt line
  97.                                         // |FDCAN_ILS_SMSG                                //bit02:
  98.                                                                                                                 // TCFL: Transmission cancellation finished interrupt line
  99.                                                                                                                 // TCL: Transmission completed interrupt line
  100.                                                                                                                 // HPML: High-priority message interrupt line
  101.                                         |FDCAN_ILS_RXFIFO1                                //bit01:当邮箱1的事件在 fdcan1_intr1_it 中断分支中处理
  102.                                                                                                                 // RF1LL: Rx FIFO 1 message lost interrupt line
  103.                                                                                                                 // RF1FL: Rx FIFO 1 full Interrupt line
  104.                                                                                                                 // RF1NL: Rx FIFO 1 new message interrupt line
  105.                                         // |FDCAN_ILS_RXFIFO0                        //bit00:当邮箱0的事件在 fdcan1_intr0_it 中断分支中处理
  106.                                                                                                                 // RF0LL: Rx FIFO 0 message lost interrupt line
  107.                                                                                                                 // RF0FL: Rx FIFO 0 full interrupt line
  108.                                                                                                                 // RF0NL: Rx FIFO 0 new message interrupt line
  109.                                         ;
  110.         //步骤9 结束

  111.         //步骤10 使能筛选器
  112.         FDCAN1->RXGFC |= 0
  113.                                         |(1 << FDCAN_RXGFC_LSE_Pos)                //bit[27:24]: 列表信息拓展【0|无拓展消息过滤】【1|1~8拓展消息】【>8|被解释为8】
  114.                                         |(2 << FDCAN_RXGFC_LSS_Pos)                //bit[20:16]: 【0|无标准消息ID过滤】【1~28|标准消息ID元素过滤数量】【>28|被解释为28】
  115.                                         // |FDCAN_RXGFC_F0OM                                //bit09: FIFO0模式:覆盖或者堵塞【0|阻塞模式】【1|覆盖模式】
  116.                                         // |FDCAN_RXGFC_F1OM                                //bit08: FIFO1模式:覆盖或者堵塞【0|阻塞模式】【1|覆盖模式】
  117.                                         |(2 << FDCAN_RXGFC_ANFS_Pos)        //bit[05:04]: 定义如何处理接收到的id为11位且与筛选器列表中的任何元素不匹配的消息。【0|在FIFO0中接收】【1|在FIFO1中接收】【2~3|拒绝】
  118.                                         |(2 << FDCAN_RXGFC_ANFE_Pos)        //bit[03:02]: 定义如何处理接收到的id为29位且与筛选器列表中的任何元素不匹配的消息。【0|在FIFO0中接收】【1|在FIFO1中接收】【2~3|拒绝】
  119.                                         |FDCAN_RXGFC_RRFS                                //bit01: 【1|拒绝所有11位ID远程标准帧】
  120.                                         |FDCAN_RXGFC_RRFE                                //bit00: 【1|拒绝所有29位ID远程标准帧】
  121.                                         ;
  122.         // FDCAN1->XIDAM = 0x1FFFFFFF;                                                //FDCAN 扩展 ID 和屏蔽寄存器
  123.         // FDCAN1->TXBTIE = 0
  124.         //                                 // |0x00000004                                                //bit02: TxBuffer【1|发送中断使能】
  125.         //                                 // |0x00000002                                                //bit01: TxBuffer【1|发送中断使能】
  126.         //                                  |0x00000001                                                //bit00: TxBuffer【1|发送中断使能】
  127.         //                                 ;
  128.         // FDCAN1->TXBCIE = 0
  129.         //                                 // |0x00000004                                                //bit02: TxBuffer【1|取消中断使能】
  130.         //                                 // |0x00000002                                                //bit01: TxBuffer【1|取消中断使能】
  131.         //                                 // |0x00000001                                                //bit00: TxBuffer【1|取消中断使能】
  132.         //                                 ;
  133.         //步骤11 配置筛选器
  134.         FDCAN1_RAM->FILTER_11BIT[0] = 0x00000000
  135.                                                                 |(1 << FDCANx_RAM_FILTER11_S0_SFT_Pos)                                //【0|范围过滤,从SFID1~SFID2】【1|单独滤波SFID1和SFID2】【2|经典滤波】【3|禁用过滤】
  136.                                                                 |(1 << FDCANx_RAM_FILTER11_S0_SFEC_Pos)                                //【0|禁用过滤元件】【1|匹配存储在FIFO0】【2|匹配存储在FIFO1】【3|匹配存就拒绝】【4|匹配设置优先级】【5|匹配设置优先级并存储到FIFO0中】【6|匹配设置优先级并存储到FIFO1中】【7|保留】
  137.                                                                 |(0x600 << FDCANx_RAM_FILTER11_S0_SFID1_Pos)                //【SFID1】
  138.                                                                 |(0x609 << FDCANx_RAM_FILTER11_S0_SFID2_Pos)                //【SFID2】
  139.                                                                 ;//列表滤波,只接收 ID为0x600和0x609 的数据,并且这两个ID放入FIFO0中
  140.         FDCAN1_RAM->FILTER_11BIT[1] = 0x00000000
  141.                                                                 |(1 << FDCANx_RAM_FILTER11_S0_SFT_Pos)                                //【0|范围过滤,从SFID1~SFID2】【1|单独滤波SFID1和SFID2】【2|经典滤波】【3|禁用过滤】
  142.                                                                 |(2 << FDCANx_RAM_FILTER11_S0_SFEC_Pos)                                //【0|禁用过滤元件】【1|匹配存储在FIFO0】【2|匹配存储在FIFO1】【3|匹配存就拒绝】【4|匹配设置优先级】【5|匹配设置优先级并存储到FIFO0中】【6|匹配设置优先级并存储到FIFO1中】【7|保留】
  143.                                                                 |(0x209 << FDCANx_RAM_FILTER11_S0_SFID1_Pos)                //【SFID1】
  144.                                                                 |(0x209 << FDCANx_RAM_FILTER11_S0_SFID2_Pos)                //【SFID2】
  145.                                                                 ;//列表滤波,只接收 ID为0x209 的数据,并且这个ID放入FIFO1中

  146.         FDCAN1_RAM->FILTER_29BIT[0][0] = 0x00000000
  147.                                                                         |(1 << FDCANx_RAM_FILTER29_F0_EFEC_Pos)                                //【0|禁止滤波】【1|匹配就保存FIFO1中】【2|匹配就保存FIFO2中】【3|拒绝匹配ID】【4|如果过滤器匹配,则设置优先级】【5|如果过滤器匹配,则设置优先级并存储在 FIFO 0 中】【6|如果过滤器匹配,则设置优先级并存储在 FIFO 1 中】【7|Reserve】
  148.                                                                         |(0x0CCCCCCC << FDCANx_RAM_FILTER29_F0_EFID1_Pos)        //【EFID1】
  149.                                                                         ;
  150.         // FDCAN1_RAM->FILTER_29BIT[0][1] = 0x00000000
  151.         //                                                                 |(1 << FDCANx_RAM_FILTER29_F1_EFTI_Pos)                                //【0|EFID1到EFID2(EFID2>=EFID1)】【1|单独SFID1或者SFID2】【2|经典滤波】【3|EFID1到EFID2(EFID2>=EFID1),未使用XIDAM寄存器的掩码】
  152.         //                                                                 |(0x00000000 << FDCANx_RAM_FILTER29_F1_EFID2_Pos)        //【EFID2】
  153.         //                                                                 ;
  154.         // FDCAN1_RAM->FILTER_29BIT[1][0] = 0x00000000
  155.         //                                                                 |(1 << FDCANx_RAM_FILTER29_F0_EFEC_Pos)                                //【0|禁止滤波】【1|匹配就保存FIFO1中】【2|匹配就保存FIFO2中】【3|拒绝匹配ID】【4|如果过滤器匹配,则设置优先级】【5|如果过滤器匹配,则设置优先级并存储在 FIFO 0 中】【6|如果过滤器匹配,则设置优先级并存储在 FIFO 1 中】【7|Reserve】
  156.         //                                                                 |(0x00000000 << FDCANx_RAM_FILTER29_F0_EFID1_Pos)        //【EFID1】
  157.         //                                                                 ;
  158.         // FDCAN1_RAM->FILTER_29BIT[1][1] = 0x00000000
  159.         //                                                                 |(1 << FDCANx_RAM_FILTER29_F1_EFTI_Pos)                                //【0|EFID1到EFID2(EFID2>=EFID1)】【1|单独SFID1或者SFID2】【2|经典滤波】【3|EFID1到EFID2(EFID2>=EFID1),未使用XIDAM寄存器的掩码】
  160.         //                                                                 |(0x00000000 << FDCANx_RAM_FILTER29_F1_EFID2_Pos)        //【EFID2】
  161.         //                                                                 ;
  162.         // FDCAN1_RAM->FILTER_29BIT[2][0] = 0x00000000
  163.         //                                                                 |(1 << FDCANx_RAM_FILTER29_F0_EFEC_Pos)                                //【0|禁止滤波】【1|匹配就保存FIFO1中】【2|匹配就保存FIFO2中】【3|拒绝匹配ID】【4|如果过滤器匹配,则设置优先级】【5|如果过滤器匹配,则设置优先级并存储在 FIFO 0 中】【6|如果过滤器匹配,则设置优先级并存储在 FIFO 1 中】【7|Reserve】
  164.         //                                                                 |(0x00000000 << FDCANx_RAM_FILTER29_F0_EFID1_Pos)        //【EFID1】
  165.         //                                                                 ;
  166.         // FDCAN1_RAM->FILTER_29BIT[2][1] = 0x00000000
  167.         //                                                                 |(1 << FDCANx_RAM_FILTER29_F1_EFTI_Pos)                                //【0|EFID1到EFID2(EFID2>=EFID1)】【1|单独SFID1或者SFID2】【2|经典滤波】【3|EFID1到EFID2(EFID2>=EFID1),未使用XIDAM寄存器的掩码】
  168.         //                                                                 |(0x00000000 << FDCANx_RAM_FILTER29_F1_EFID2_Pos)        //【EFID2】
  169.         //                                                                 ;

  170.         // FDCAN1_RAM->FILTER_29BIT[3][0] = 0x00000000
  171.         //                                                                 |(2 << FDCANx_RAM_FILTER29_F0_EFEC_Pos)                                //【0|禁止滤波】【1|匹配就保存FIFO1中】【2|匹配就保存FIFO2中】【3|拒绝匹配ID】【4|如果过滤器匹配,则设置优先级】【5|如果过滤器匹配,则设置优先级并存储在 FIFO 0 中】【6|如果过滤器匹配,则设置优先级并存储在 FIFO 1 中】【7|Reserve】
  172.         //                                                                 |(0x00000000 << FDCANx_RAM_FILTER29_F0_EFID1_Pos)        //【EFID1】
  173.         //                                                                 ;
  174.         // FDCAN1_RAM->FILTER_29BIT[3][1] = 0x00000000
  175.         //                                                                 |(1 << FDCANx_RAM_FILTER29_F1_EFTI_Pos)                                //【0|EFID1到EFID2(EFID2>=EFID1)】【1|单独SFID1或者SFID2】【2|经典滤波】【3|EFID1到EFID2(EFID2>=EFID1),未使用XIDAM寄存器的掩码】
  176.         //                                                                 |(0x00000000 << FDCANx_RAM_FILTER29_F1_EFID2_Pos)        //【EFID2】
  177.         //                                                                 ;
  178.         // FDCAN1_RAM->FILTER_29BIT[4][0] = 0x00000000
  179.         //                                                                 |(2 << FDCANx_RAM_FILTER29_F0_EFEC_Pos)                                //【0|禁止滤波】【1|匹配就保存FIFO1中】【2|匹配就保存FIFO2中】【3|拒绝匹配ID】【4|如果过滤器匹配,则设置优先级】【5|如果过滤器匹配,则设置优先级并存储在 FIFO 0 中】【6|如果过滤器匹配,则设置优先级并存储在 FIFO 1 中】【7|Reserve】
  180.         //                                                                 |(0x00000000 << FDCANx_RAM_FILTER29_F0_EFID1_Pos)        //【EFID1】
  181.         //                                                                 ;
  182.         // FDCAN1_RAM->FILTER_29BIT[4][1] = 0x00000000
  183.         //                                                                 |(1 << FDCANx_RAM_FILTER29_F1_EFTI_Pos)                                //【0|EFID1到EFID2(EFID2>=EFID1)】【1|单独SFID1或者SFID2】【2|经典滤波】【3|EFID1到EFID2(EFID2>=EFID1),未使用XIDAM寄存器的掩码】
  184.         //                                                                 |(0x00000000 << FDCANx_RAM_FILTER29_F1_EFID2_Pos)        //【EFID2】
  185.         //                                                                 ;

  186.         //步骤12 清除INIT标志位
  187.         FDCAN1->CCCR &= ~FDCAN_CCCR_INIT;//退出初始化模式,CCE会自动清除
  188.         while (FDCAN1->CCCR & FDCAN_CCCR_INIT);//等待退出
  189. }
复制代码

附录2 发送函数
返回第8章 发送操作

  1. /**
  2. * @description: 发送11位地址的报文
  3. * @param {uint8_t} FDCAN_Index                FDCANx 1~3 FDCAN外设索引使用FDCAN1/2/3
  4. * @param {uint16_t} ID                                11位ID发送
  5. * @param {uint8_t} RTR                                0-数据帧        1-远程帧
  6. * @param {uint8_t} DLC                                数据长度 0~8
  7. * @param {Buffer_72Byte_Struct}         *buffer 发送数组地址
  8. * @return {uint8_t}                                SUCCEED/FAILED/ERROR
  9. * @author: XL
  10. */
  11. uint8_t FDCAN_11ID_SendData(uint8_t FDCAN_Index, uint16_t ID,uint8_t RTR,uint8_t DLC,Buffer_72Byte_Struct *buffer)
  12. {
  13.         uint8_t Free_Mailbox;//空闲邮箱索引
  14.         FDCAN_RAM_Struct* FDCAN_RAM;//FDCANx_RAM指针
  15.         FDCAN_GlobalTypeDef* FDCAN;//FDCANx指针
  16.         switch (FDCAN_Index)//根据索引确定使用FDCANx
  17.         {
  18.         case 1:
  19.                 FDCAN_RAM = FDCAN1_RAM;
  20.                 FDCAN = FDCAN1;
  21.                 break;
  22.         case 2:
  23.                 FDCAN_RAM = FDCAN2_RAM;
  24.                 FDCAN = FDCAN2;
  25.                 break;
  26.         case 3:
  27.                 FDCAN_RAM = FDCAN3_RAM;
  28.                 FDCAN = FDCAN3;
  29.                 break;
  30.         default:
  31.                 return ERROR;//输入索引错误,无效
  32.                 break;
  33.         }
  34.         if(FDCAN->TXFQS & FDCAN_TXFQS_TFQF)
  35.         {                                                                                        //CanBus判断是否有空闲的发送寄存器,然后发送,否则等待
  36.                 return FAILED;//没有空闲邮箱
  37.         }
  38.         else
  39.         {                                                                                        //只要第一个邮箱空闲,始终先使用第一个,然后是第二个,第三个邮箱
  40.                 Free_Mailbox = ((uint8_t)(FDCAN->TXFQS >> 16)) & 0x03;//获取空闲邮箱
  41.                 FDCAN_RAM->Tx_BUFFER[Free_Mailbox][0] = ((uint32_t)ID << FDCANx_RAM_TxBuffer_T0_11ID_Pos);//写入地址
  42.                 FDCAN_RAM->Tx_BUFFER[Free_Mailbox][1] = (DLC << FDCANx_RAM_TxBuffer_T1_DLC_Pos);//发送长度
  43.                 FDCAN_RAM->Tx_BUFFER[Free_Mailbox][2] = buffer->DataWord[0];//发送的数据
  44.                 FDCAN_RAM->Tx_BUFFER[Free_Mailbox][3] = buffer->DataWord[1];//发送的数据
  45.                 FDCAN->TXBAR |= (0x0001 << Free_Mailbox);//置位发送请求
  46.                 return SUCCEED;//返回成功
  47.         }
  48. }
复制代码

附录3 接收中断程序

  1. /**
  2. * @description: fdcan1_intr0_it 中断分支
  3. * @param {*}
  4. * @return {*}
  5. * @author: XL
  6. */
  7. void FDCAN1_IT0_IRQHandler(void)
  8. {
  9.         if(FDCAN1->IR & FDCAN_IR_RF0N)//邮箱0有新消息
  10.         {
  11.                 FDCAN1->IR |= FDCAN_IR_RF0N;//清除新消息状态标志
  12.                 switch((FDCAN1->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos)//获取索引
  13.                 {
  14.                         case 0:
  15.                                 FDCAN1_Rxbuffer0.DataWord[0] = FDCAN1_RAM->Rx_FIFO_0[0][0];//获取数据
  16.                                 FDCAN1_Rxbuffer0.DataWord[1] = FDCAN1_RAM->Rx_FIFO_0[0][1];//获取数据
  17.                                 FDCAN1_Rxbuffer0.DataWord[2] = FDCAN1_RAM->Rx_FIFO_0[0][2];//获取数据
  18.                                 FDCAN1_Rxbuffer0.DataWord[3] = FDCAN1_RAM->Rx_FIFO_0[0][3];//获取数据
  19.                                 FDCAN1->RXF0A = 0;//确认接收完毕
  20.                                 break;
  21.                         case 1:
  22.                                 FDCAN1_Rxbuffer0.DataWord[0] = FDCAN1_RAM->Rx_FIFO_0[1][0];
  23.                                 FDCAN1_Rxbuffer0.DataWord[1] = FDCAN1_RAM->Rx_FIFO_0[1][1];
  24.                                 FDCAN1_Rxbuffer0.DataWord[2] = FDCAN1_RAM->Rx_FIFO_0[1][2];
  25.                                 FDCAN1_Rxbuffer0.DataWord[3] = FDCAN1_RAM->Rx_FIFO_0[1][3];
  26.                                 FDCAN1->RXF0A = 1;
  27.                                 break;
  28.                         case 2:
  29.                                 FDCAN1_Rxbuffer0.DataWord[0] = FDCAN1_RAM->Rx_FIFO_0[2][0];
  30.                                 FDCAN1_Rxbuffer0.DataWord[1] = FDCAN1_RAM->Rx_FIFO_0[2][1];
  31.                                 FDCAN1_Rxbuffer0.DataWord[2] = FDCAN1_RAM->Rx_FIFO_0[2][2];
  32.                                 FDCAN1_Rxbuffer0.DataWord[3] = FDCAN1_RAM->Rx_FIFO_0[2][3];
  33.                                 FDCAN1->RXF0A = 2;
  34.                                 break;
  35.                         default:break;
  36.                 }
  37.         }
  38. }

  39. /**
  40. * @description: fdcan1_intr1_it 中断分支
  41. * @param {*}
  42. * @return {*}
  43. * @author: XL
  44. */
  45. void FDCAN1_IT1_IRQHandler(void)
  46. {
  47.         if(FDCAN1->IR & FDCAN_IR_RF1N)//邮箱1有新消息
  48.         {
  49.                 FDCAN1->IR |= FDCAN_IR_RF1N;//清除新消息状态标志
  50.                 switch((FDCAN1->RXF1S & FDCAN_RXF1S_F1GI) >> FDCAN_RXF1S_F1GI_Pos)//获取索引
  51.                 {
  52.                         case 0:
  53.                                 FDCAN1_Rxbuffer1.DataWord[0] = FDCAN1_RAM->Rx_FIFO_1[0][0];//获取数据
  54.                                 FDCAN1_Rxbuffer1.DataWord[1] = FDCAN1_RAM->Rx_FIFO_1[0][1];//获取数据
  55.                                 FDCAN1_Rxbuffer1.DataWord[2] = FDCAN1_RAM->Rx_FIFO_1[0][2];//获取数据
  56.                                 FDCAN1_Rxbuffer1.DataWord[3] = FDCAN1_RAM->Rx_FIFO_1[0][3];//获取数据
  57.                                 FDCAN1->RXF1A = 0;//确认接收完毕
  58.                                 break;
  59.                         case 1:
  60.                                 FDCAN1_Rxbuffer1.DataWord[0] = FDCAN1_RAM->Rx_FIFO_1[1][0];
  61.                                 FDCAN1_Rxbuffer1.DataWord[1] = FDCAN1_RAM->Rx_FIFO_1[1][1];
  62.                                 FDCAN1_Rxbuffer1.DataWord[2] = FDCAN1_RAM->Rx_FIFO_1[1][2];
  63.                                 FDCAN1_Rxbuffer1.DataWord[3] = FDCAN1_RAM->Rx_FIFO_1[1][3];
  64.                                 FDCAN1->RXF1A = 1;
  65.                                 break;
  66.                         case 2:
  67.                                 FDCAN1_Rxbuffer1.DataWord[0] = FDCAN1_RAM->Rx_FIFO_1[2][0];
  68.                                 FDCAN1_Rxbuffer1.DataWord[1] = FDCAN1_RAM->Rx_FIFO_1[2][1];
  69.                                 FDCAN1_Rxbuffer1.DataWord[2] = FDCAN1_RAM->Rx_FIFO_1[2][2];
  70.                                 FDCAN1_Rxbuffer1.DataWord[3] = FDCAN1_RAM->Rx_FIFO_1[2][3];
  71.                                 FDCAN1->RXF1A = 2;
  72.                                 break;
  73.                         default:break;
  74.                 }
  75.         }
  76. }
复制代码


————————————————
版权声明:Vice Versa XL


收藏 评论0 发布时间:2022-10-12 22:59

举报

0个回答

所属标签

相似分享

官网相关资源

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