文章目录[隐藏]
由于鄙人比较懒,因此本文章只是对 FDCAN 的 经典模式 的简单使用介绍。对于我不需要使用的功能 我就没有深入研究,因此本文只是 CAN 的常用方式的笔记,深入研究的话可以详细阅读手册,本文章没有介绍。
如果有介绍错误的地方,希望各位大佬指正,鄙人一定修改,必要时删除本文章,防止误导他人。欢迎讨论!
FDCAN 与 经典CAN 的最直观差别就是数据帧部分,FDCAN的数据帧波特率可变,并且数据大小不局限于 8 Bytes ,最高支持 64 Bytes 的数据传输。详细差别见 传送门: CAN FD 与 CAN协议区别–简单易懂协议详解 。
1. FDCAN的框图
根据上图可以看到,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寄存器中进行配置。
2.2 fdcan_tq_ck
根据系统框图可看到,系统输入的时钟可通过 fdcan_clk 分频得到 fdcan_tq_ck ,在 FDCAN_CKDIV 寄存器中配置分频系数。
2.3 波特率
FDCAN模块的bit采样分三段:
波特率公式如下:
波
特
率
=
1
t
q
+
t
B
S
1
+
t
B
S
2
波特率 = \frac{1}{t_q + t_{BS1} + t_{BS2}}
波特率=tq+tBS1+tBS21
t
q
=
(
B
R
P
+
1
)
∗
f
d
c
a
n
_
c
l
k
t_q = (BRP + 1)*fdcan\_clk
tq=(BRP+1)∗fdcan_clk
注意:
1、由于 FDCAN 与 经典CAN 的帧格式有点差异,其数据帧波特率可变,因此在这里分出普通CAN和数据bit时间
2、数据 和 普通 bit 时间寄存器名称不一样,数据波特率寄存器 FDCAN_DBTP ,一般帧波特率寄存器为 FDCAN_NBTP 。当使用经典模式CAN时, FDCAN_DBTP 配置被忽略
3. FDCAN的地址分布
3.1 总体分布
由于头文件中没有该寄存器的宏定义,因此需要自己建立宏定义。
G474的FDCAN外设一共有3组(FDCAN1,FDCAN2,FDCAN3),寄存器配置分为3个,消息RAM也分为3组。
这里可以先把 消息RAM 的宏定义写好
#define FDCANs_MESSAGE_RAM_BASE 0x4000A400
#define FDCAN1_RAM_BASE (FDCANs_MESSAGE_RAM_BASE)
#define FDCAN2_RAM_BASE (FDCAN1_RAM_BASE + 0x00000400)
#define FDCAN3_RAM_BASE (FDCAN2_RAM_BASE + 0x00000400)
3.2 Message RAM
1个 信息RAM 有 212 words 的大小,即 212 × 4 = 848 Bytes 。
根据该图,可以创建一个对应上述地址的结构体,方便后期地址的管理:
typedef struct
{
uint32_t FILTER_11BIT[28];
uint32_t FILTER_29BIT[16];
uint32_t Rx_FIFO_0[54];
uint32_t Rx_FIFO_1[54];
uint32_t Tx_FIFO[6];
uint32_t Tx_BUFFER[54];
}FDCAN_RAM_Struct;
4. FDCAN的筛选器
4.1 筛选器的特征
- 每个筛选器可配置为
• 范围筛选
• 指定ID筛选
• 屏蔽典型bit筛选- 每个过滤器元件可配置为接受或拒绝过滤
- 每个过滤器元素可以单独启用/禁用
- 过滤器是按顺序检查的,执行在第一个匹配的过滤器元素时停止
相关的寄存器:全局筛选配置(RXGFC)、拓展ID和掩码(XIDAM)
如果需要接收数据,一定要配置筛选器,否则会什么也接受不到。
4.2 11-bit 筛选器的格式
这里根据手册的翻译进行配置就好,29-bit 的筛选器也是如此,手册里全有,我就不放图片了,太占地方。
对于筛选器的掩码模式,可通过传送门了解到:CAN通讯难点———验收筛选器
通过配置筛选器,可以使FDCAN外设接收其他模块发来的信息,在筛选器中配置接收消息的FIFO或者拒收消息。配置筛选器是FDCAN接收的关键。
筛选器的配置不受 INIT 和 CCE 标志位的限制,可随时配置。
5. FIFO模式与Queue模式
FIFO模式与队列模式的区别为:
- 队列模式的优先级遵循邮箱0优先级最高,其次是1,最后是2,如果当前3个邮箱全有数据,优先发送邮箱0的数据
- FIFO模式的优先级是遵循哪个数据先进入的邮箱,与其所在的索引地址无关,即:如果当前3个邮箱全有数据,邮箱2被最先写入,则优先发送邮箱2的数据。
5.1 TX FIFO 的寄存器格式
具体说明见手册1969页,我就不复制了,翻一下就能懂每个BIT代表的意思。
根据上表,我们就可以写出对应各个标志位的结构体,方便后期指针使用。
由于其buffer支持 11-bit ID 和 29-bit ID ,因此将其写为共同体。
typedef union
{
uint32_t HallfWord[54];
struct
{
uint32_t T0_ID:29; // ID
uint32_t T0_RTR:1; //【0|发送数据帧】【1|发送远程帧】
uint32_t T0_XTD:1; //【0|11-bit】【1|29-bit】
uint32_t T0_ESI:1; //
uint32_t T1_Reserved1:16;
uint32_t T1_DLC:4; //【0~8|发送数据为0~8】【9~15|经典CAN为8,FDCAN为12/16/20/24/32/48/64】
uint32_t T1_BRS:1; //【0|无波特率切换】【1|有波特率切换】
uint32_t T1_FDF:1; //【0|经典CAN】【1|FDCAN】
uint32_t T1_Reserved2:1;
uint32_t T1_EFC:1; //【0|不保存TX事件】【1|保存】
uint32_t T1_MM:8; //
uint32_t DataWord[16];
}bit_29ID;
struct
{
uint32_t T0_Reserved:18;
uint32_t T0_ID:11; // ID
uint32_t T0_RTR:1; //【0|发送数据帧】【1|发送远程帧】
uint32_t T0_XTD:1; //【0|11-bit】【1|29-bit】
uint32_t T0_ESI:1; //
uint32_t T1_Reserved1:16;
uint32_t T1_DLC:4; //【0~8|发送数据为0~8】【9~15|经典CAN为8,FDCAN为12/16/20/24/32/48/64】
uint32_t T1_BRS:1; //【0|无波特率切换】【1|有波特率切换】
uint32_t T1_FDF:1; //【0|经典CAN】【1|FDCAN】
uint32_t T1_Reserved2:1;
uint32_t T1_EFC:1; //【0|不保存TX事件】【1|保存】
uint32_t T1_MM:8; //
uint32_t DataWord[16];
}bit_11ID;
}FDCAN_Buffer_Union;
6. FDCAN的初始化
IO口配置我就不介绍了,想必大家都会配置IO。
- 首先在RCC->APB1RSTR1寄存器中使能RCC_APB1ENR1_FDCANEN,这样FDCAN的寄存器就可以配置了。
- 然后选择FDCAN内核时钟的时钟源,在RCC->CCIPR寄存器的RCC_CCIPR_FDCANSEL中配置。
- 置位INIT标志位,开始配置寄存器(只有INIT标志位置位,才可置位CCE标志位)
- 等待INIT标志位置位
- 置位CCE标志位,解锁受保护的寄存器
- 等待CCE标志位置位
- 配置时钟分频 (FDCAN_CKDIV 寄存器)
- 配置波特率
- 配置中断
- 配置筛选器
- 使能筛选器
- 清除INIT标志位
初始化代码见
7. 发送操作
7.1 FDCAN帧模式
FDCAN帧模式由下表各个标志位配置:
根据上表所示,可以通过 CCCR寄存器 和 Tx Buffer 内部的标志位 配合,实现不同模式的CAN。
由于鄙人只想使用 经典CAN,因此将 CCCR寄存器 中的 FDOE 配置为 0,其他标志位我就不管了。
7.2 发送步骤
- 读取 FDCAN1->TXFQS 是否有可用信箱( FDCAN_TXFQS_TFQF 是否置位)
- 如果没置位邮箱满标志,则查询 FDCAN_TXFQS_TFQPI 索引,获得的索引就是可以写入的邮箱
- 将要发送的数据写入刚才读取的索引的 Tx Buffer 中(在这里可以配置发送长度、ID等信息)
- 置位发送请求
- 等待发送完成(可以不等待,配置发送完成中断使能后,在中断中置位发送完成标志来判断是否发送完毕)
示例代码见
附录2 发送函数
8. 接收操作
首先配置筛选器来选择接收的消息和接收后存放的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 标志位。
因此,接收操作的步骤为:
- 读取接收的数据
- 确认读取完毕
接收程序见
附录3 中断程序
9. 参考资料传送门
9.1 代码下载(0积分)
9.2 其他 CAN 知识了解
附录1 初始化
附录1.1 RCC配置
为方便其他模块配置,将其他模块的RCC列表了出来,方便当库文件使用
void RCC_Init(void)//
{
//--------------------------------------------------------------------------------------//
//---------------------------------------- AHB1 ----------------------------------------//
//--------------------------------------------------------------------------------------//
RCC->AHB1RSTR |= 0 //default: 0x0000 0000
// |RCC_AHB1RSTR_CRCRST //bit12
// |RCC_AHB1RSTR_FLASHRST //bit08
// |RCC_AHB1RSTR_FMACRST //bit04
// |RCC_AHB1RSTR_CORDICRST //bit03
// |RCC_AHB1RSTR_DMAMUX1RST //bit02
// |RCC_AHB1RSTR_DMA2RST //bit01
// |RCC_AHB1RSTR_DMA1RST //bit00
;
RCC->AHB1RSTR &= 0xffffffff //default: 0x0000 0000
// &~RCC_AHB1RSTR_CRCRST //bit12
// &~RCC_AHB1RSTR_FLASHRST //bit08
// &~RCC_AHB1RSTR_FMACRST //bit04
// &~RCC_AHB1RSTR_CORDICRST //bit03
// &~RCC_AHB1RSTR_DMAMUX1RST //bit02
// &~RCC_AHB1RSTR_DMA2RST //bit01
// &~RCC_AHB1RSTR_DMA1RST //bit00
;
RCC->AHB1ENR |= 0 //default: 0x0000 0100
// |RCC_AHB1ENR_CRCEN //bit12
// |RCC_AHB1ENR_FLASHEN //bit08
// |RCC_AHB1ENR_FMACEN //bit04
// |RCC_AHB1ENR_CORDICEN //bit03
// |RCC_AHB1ENR_DMAMUX1EN //bit02
// |RCC_AHB1ENR_DMA2EN //bit01
// |RCC_AHB1ENR_DMA1EN //bit00
;
//--------------------------------------------------------------------------------------//
//---------------------------------------- AHB2 ----------------------------------------//
//--------------------------------------------------------------------------------------//
RCC->AHB2RSTR |= 0 //defualt: 0x0000 0000
// |RCC_AHB2RSTR_RNGRST //bit26
// |RCC_AHB2RSTR_RNGRST //bit24
// |RCC_AHB2RSTR_DAC4RST //bit19
// |RCC_AHB2RSTR_DAC3RST //bit18
// |RCC_AHB2RSTR_DAC2RST //bit17
// |RCC_AHB2RSTR_DAC1RST //bit16
|RCC_AHB2RSTR_ADC345RST //bit14
|RCC_AHB2RSTR_ADC12RST //bit13
// |RCC_AHB2RSTR_GPIOGRST //bit06
|RCC_AHB2RSTR_GPIOFRST //bit05
|RCC_AHB2RSTR_GPIOERST //bit04
|RCC_AHB2RSTR_GPIODRST //bit03
|RCC_AHB2RSTR_GPIOCRST //bit02
|RCC_AHB2RSTR_GPIOBRST //bit01
|RCC_AHB2RSTR_GPIOARST //bit00
;
RCC->AHB2RSTR &= 0xffffffff //defualt: 0x0000 0000
// &~RCC_AHB2RSTR_RNGRST //bit26
// &~RCC_AHB2RSTR_RNGRST //bit24
// &~RCC_AHB2RSTR_DAC4RST //bit19
// &~RCC_AHB2RSTR_DAC3RST //bit18
// &~RCC_AHB2RSTR_DAC2RST //bit17
// &~RCC_AHB2RSTR_DAC1RST //bit16
&~RCC_AHB2RSTR_ADC345RST //bit14
&~RCC_AHB2RSTR_ADC12RST //bit13
// &~RCC_AHB2RSTR_GPIOGRST //bit06
&~RCC_AHB2RSTR_GPIOFRST //bit05
&~RCC_AHB2RSTR_GPIOERST //bit04
&~RCC_AHB2RSTR_GPIODRST //bit03
&~RCC_AHB2RSTR_GPIOCRST //bit02
&~RCC_AHB2RSTR_GPIOBRST //bit01
&~RCC_AHB2RSTR_GPIOARST //bit00
;
RCC->AHB2ENR = 0 //default: 0x0000 0000
// |RCC_AHB2ENR_RNGEN //bit26
// |RCC_AHB2ENR_DAC4EN //bit19
// |RCC_AHB2ENR_DAC3EN //bit18
// |RCC_AHB2ENR_DAC2EN //bit17
// |RCC_AHB2ENR_DAC1EN //bit16
|RCC_AHB2ENR_ADC345EN //bit14
|RCC_AHB2ENR_ADC12EN //bit13
// |RCC_AHB2ENR_GPIOGEN //bit06
|RCC_AHB2ENR_GPIOFEN //bit05
|RCC_AHB2ENR_GPIOEEN //bit04
|RCC_AHB2ENR_GPIODEN //bit03
|RCC_AHB2ENR_GPIOCEN //bit02
|RCC_AHB2ENR_GPIOBEN //bit01
|RCC_AHB2ENR_GPIOAEN //bit00
;
//--------------------------------------------------------------------------------------//
//---------------------------------------- AHB3 ----------------------------------------//
//--------------------------------------------------------------------------------------//
RCC->AHB3RSTR |= 0 //default:0x0000 0000
// |RCC_AHB3RSTR_QSPIRST //bit08
// |RCC_AHB3RSTR_FMCRST //bit00
;
RCC->AHB3RSTR &= 0xffffffff //default:0x0000 0000
// &~RCC_AHB3RSTR_QSPIRST //bit08
// &~RCC_AHB3RSTR_FMCRST //bit00
;
RCC->AHB3ENR |= 0 //default: 0x0000 0000
// |RCC_AHB3ENR_QSPIEN //bit08
// |RCC_AHB3ENR_FMCEN //bit00
;
//--------------------------------------------------------------------------------------//
//---------------------------------------- APB1 ----------------------------------------//
//--------------------------------------------------------------------------------------//
RCC->APB1RSTR1 |= 0 //default: 0x0000 0000
// |RCC_APB1RSTR1_LPTIM1RST //bit31
// |RCC_APB1RSTR1_I2C3RST //bit30
// |RCC_APB1RSTR1_PWRRST //bit28
|RCC_APB1RSTR1_FDCANRST //bit25
// |RCC_APB1RSTR1_USBRST //bit23
// |RCC_APB1RSTR1_I2C2RST //bit22
// |RCC_APB1RSTR1_I2C1RST //bit21
// |RCC_APB1RSTR1_UART5RST //bit20
// |RCC_APB1RSTR1_UART4RST //bit19
// |RCC_APB1RSTR1_USART3RST //bit18
// |RCC_APB1RSTR1_USART2RST //bit17
// |RCC_APB1RSTR1_SPI3RST //bit15
// |RCC_APB1RSTR1_SPI2RST //bit14
// |RCC_APB1RSTR1_CRSRST //bit08
|RCC_APB1RSTR1_TIM7RST //bit05
|RCC_APB1RSTR1_TIM6RST //bit04
// |RCC_APB1RSTR1_TIM5RST //bit03
|RCC_APB1RSTR1_TIM4RST //bit02
|RCC_APB1RSTR1_TIM3RST //bit01
|RCC_APB1RSTR1_TIM2RST //bit00
;
RCC->APB1RSTR1 &= 0xffffffff//default: 0x0000 0000
// &~RCC_APB1RSTR1_LPTIM1RST //bit31
// &~RCC_APB1RSTR1_I2C3RST //bit30
// &~RCC_APB1RSTR1_PWRRST //bit28
&~RCC_APB1RSTR1_FDCANRST //bit25
// &~RCC_APB1RSTR1_USBRST //bit23
// &~RCC_APB1RSTR1_I2C2RST //bit22
// &~RCC_APB1RSTR1_I2C1RST //bit21
// &~RCC_APB1RSTR1_UART5RST //bit20
// &~RCC_APB1RSTR1_UART4RST //bit19
// &~RCC_APB1RSTR1_USART3RST //bit18
// &~RCC_APB1RSTR1_USART2RST //bit17
// &~RCC_APB1RSTR1_SPI3RST //bit15
// &~RCC_APB1RSTR1_SPI2RST //bit14
// &~RCC_APB1RSTR1_CRSRST //bit08
&~RCC_APB1RSTR1_TIM7RST //bit05
&~RCC_APB1RSTR1_TIM6RST //bit04
// &~RCC_APB1RSTR1_TIM5RST //bit03
&~RCC_APB1RSTR1_TIM4RST //bit02
&~RCC_APB1RSTR1_TIM3RST //bit01
&~RCC_APB1RSTR1_TIM2RST //bit00
;
RCC->APB1ENR1 |= 0 //default: 0x0000 0400
// |RCC_APB1ENR1_LPTIM1EN //bit31
// |RCC_APB1ENR1_I2C3EN //bit30
// |RCC_APB1ENR1_PWREN //bit28
|RCC_APB1ENR1_FDCANEN //bit25
// |RCC_APB1ENR1_USBEN //bit23
// |RCC_APB1ENR1_I2C2EN //bit22
// |RCC_APB1ENR1_I2C1EN //bit21
// |RCC_APB1ENR1_UART5EN //bit20
// |RCC_APB1ENR1_UART4EN //bit19
// |RCC_APB1ENR1_USART3EN //bit18
// |RCC_APB1ENR1_USART2EN //bit17
// |RCC_APB1ENR1_SPI3EN //bit15
// |RCC_APB1ENR1_SPI2EN //bit14
// |RCC_APB1ENR1_WWDGEN //bit11
// |RCC_APB1ENR1_RTCAPBEN //bit10
// |RCC_APB1ENR1_CRSEN //bit08
|RCC_APB1ENR1_TIM7EN //bit05
|RCC_APB1ENR1_TIM6EN //bit04
// |RCC_APB1ENR1_TIM5EN //bit03
|RCC_APB1ENR1_TIM4EN //bit02
|RCC_APB1ENR1_TIM3EN //bit01
|RCC_APB1ENR1_TIM2EN //bit00
;
RCC->APB1RSTR2 |= 0 //default: 0x0000 0000
// |RCC_APB1RSTR2_UCPD1RST //bit08
// |RCC_APB1RSTR2_I2C4RST //bit01
// |RCC_APB1RSTR2_LPUART1RST //bit00
;
RCC->APB1RSTR2 &= 0xffffffff//default: 0x0000 0000
// &~RCC_APB1RSTR2_UCPD1RST //bit08
// &~RCC_APB1RSTR2_I2C4RST //bit01
// &~RCC_APB1RSTR2_LPUART1RST //bit00
;
RCC->APB1ENR2 |= 0 //default: 0x0000 0000
// |RCC_APB1ENR2_UCPD1EN //bit08
// |RCC_APB1ENR2_I2C4EN //bit01
// |RCC_APB1ENR2_LPUART1EN //bit00
;
//--------------------------------------------------------------------------------------//
//---------------------------------------- APB2 ----------------------------------------//
//--------------------------------------------------------------------------------------//
RCC->APB2RSTR |= 0 //default: 0x0000 0000
// |RCC_APB2RSTR_HRTIM1RST //bit26
// |RCC_APB2RSTR_SAI1RST //bit21
// |RCC_APB2RSTR_TIM20RST //bit20
|RCC_APB2RSTR_TIM17RST //bit18
|RCC_APB2RSTR_TIM16RST //bit17
|RCC_APB2RSTR_TIM15RST //bit16
// |RCC_APB2RSTR_SPI4RST //bit15
|RCC_APB2RSTR_USART1RST //bit14
|RCC_APB2RSTR_TIM8RST //bit13
// |RCC_APB2RSTR_SPI1RST //bit12
|RCC_APB2RSTR_TIM1RST //bit11
|RCC_APB2RSTR_SYSCFGRST //bit00
;
RCC->APB2RSTR &= 0xffffffff //default: 0x0000 0000
// &~RCC_APB2RSTR_HRTIM1RST //bit26
// &~RCC_APB2RSTR_SAI1RST //bit21
// &~RCC_APB2RSTR_TIM20RST //bit20
&~RCC_APB2RSTR_TIM17RST //bit18
&~RCC_APB2RSTR_TIM16RST //bit17
&~RCC_APB2RSTR_TIM15RST //bit16
// &~RCC_APB2RSTR_SPI4RST //bit15
&~RCC_APB2RSTR_USART1RST //bit14
&~RCC_APB2RSTR_TIM8RST //bit13
// &~RCC_APB2RSTR_SPI1RST //bit12
&~RCC_APB2RSTR_TIM1RST //bit11
&~RCC_APB2RSTR_SYSCFGRST //bit00
;
RCC->APB2ENR |= 0 //default: 0x0000 0000
// |RCC_APB2ENR_HRTIM1EN //bit26
// |RCC_APB2ENR_SAI1EN //bit21
// |RCC_APB2ENR_TIM20EN //bit20
|RCC_APB2ENR_TIM17EN //bit18
|RCC_APB2ENR_TIM16EN //bit17
|RCC_APB2ENR_TIM15EN //bit16
// |RCC_APB2ENR_SPI4EN //bit15
|RCC_APB2ENR_USART1EN //bit14
|RCC_APB2ENR_TIM8EN //bit13
// |RCC_APB2ENR_SPI1EN //bit12
|RCC_APB2ENR_TIM1EN //bit11
|RCC_APB2ENR_SYSCFGEN //bit00
;
RCC->CCIPR |= 0
// |(0 << RCC_CCIPR_ADC345SEL_Pos) //
// |(0 << RCC_CCIPR_ADC12SEL_Pos) //
// |(0 << RCC_CCIPR_CLK48SEL_Pos) //
|(0 << RCC_CCIPR_FDCANSEL_Pos) //HSE 8MHz
// |(0 << RCC_CCIPR_I2S23SEL_Pos) //
// |(0 << RCC_CCIPR_SAI1SEL_Pos) //
// |(0 << RCC_CCIPR_LPTIM1SEL_Pos) //
// |(0 << RCC_CCIPR_I2C3SEL_Pos) //
// |(0 << RCC_CCIPR_I2C2SEL_Pos) //
// |(0 << RCC_CCIPR_I2C1SEL_Pos) //
// |(0 << RCC_CCIPR_LPUART1SEL_Pos) //
// |(0 << RCC_CCIPR_UART5SEL_Pos) //
// |(0 << RCC_CCIPR_UART4SEL_Pos) //
// |(0 << RCC_CCIPR_USART3SEL_Pos) //
// |(0 << RCC_CCIPR_USART2SEL_Pos) //
// |(0 << RCC_CCIPR_USART1SEL_Pos) //
;
}
附录1.2 FDCAN寄存器配置
/**
* @description: FDCAN1经典CAN模式,波特率250k
* @param {*}
* @return {*}
*/
void FDCAN1_Function_Init(void)
{
//在RCC_CCIPR寄存器中选择FDCAN时钟为HSE,即8MHz
//
FDCAN1->CCCR |= FDCAN_CCCR_INIT; //置位INIT
while (!(FDCAN1->CCCR & FDCAN_CCCR_INIT)); //等待置位
FDCAN1->CCCR |= FDCAN_CCCR_CCE; //置位CCE
while (!(FDCAN1->CCCR & FDCAN_CCCR_CCE)); //等待置位
FDCAN1->CCCR |= 0
// |FDCAN_CCCR_NISO //bit15: 【0|ISO11898-1】【1|CANFD v1.0】
// |FDCAN_CCCR_TXP //bit14: 【1|在下上一个成功帧后暂停两个bit再起始】
// |FDCAN_CCCR_EFBI //bit13: 【1|同步检测边沿需要两个显性tq】
// |FDCAN_CCCR_PXHD //bit12: 【0|启动协议异常处理】【1|禁用协议异常处理】
// |FDCAN_CCCR_BRSE //bit09: 【1|启用波特率切换】
// |FDCAN_CCCR_FDOE //bit08: 【0|FD操作禁止】【1|FD操作使能】
// |FDCAN_CCCR_TEST //bit07: 【1|测试模式使能】
|FDCAN_CCCR_DAR //bit06: 【0|启用发送失败后自动重传】【1|禁止自动重传】
// |FDCAN_CCCR_MON //bit05: 【0|总线监控模式禁止】【1|总线监控模式使能】
// |FDCAN_CCCR_CSR //bit04: 【0|无时钟停止请求】【1|时钟停止请求,当时钟停止请求发生,先置位INIT在置位CSA在所有传输请求完成并且CAN总线空闲】
// |FDCAN_CCCR_CSA //bit03: 【0|没有时钟停止】【1|FDCAN可通过停止APB时钟和内核时钟来进行掉电】
// |FDCAN_CCCR_ASM //bit02: 【1|启用限制模式,限制模式下不会主动发送数据】
// |FDCAN_CCCR_CCE //bit01: 【1|允许配置受保护的寄存器,INIT标志位必须置位】
// |FDCAN_CCCR_INIT //bit00: 【1|初始化开始】
;
FDCAN_CONFIG->CKDIV = 0; //fdcan_clk = RCC_CCIPR_FDCAN1CLK / CKDIV
FDCAN1->NBTP = 0
|(7 << FDCAN_NBTP_NSJW_Pos) //bit[31:25]: 同步脉宽 务必小于 二阶段采样
|(0 << FDCAN_NBTP_NBRP_Pos) //bit[24:16]: BRP。 tq = (BRP + 1)*fdcan_clk
|(22 << FDCAN_NBTP_NTSEG1_Pos) //bit[15:08]: 一阶段采样
|(7 << FDCAN_NBTP_NTSEG2_Pos) //bit[06:00]: 二阶段采样 波特率 = fdcan_clk/(BRP + 1)/(3+DTSEG1+DTSEG2) = 8000000/(0+1)/(3+22+7) = 250k
;
// FDCAN1->DBTP = 0 //数据帧的波特率(经典CAN可忽略)
// |FDCAN_DBTP_TDC //bit23: 【1|收发延时补偿使能】
// |(0 << FDCAN_DBTP_DBRP_Pos) //bit[20:16]: tq = (BRP + 1)*fdcan_clk
// |(22 << FDCAN_DBTP_DTSEG1_Pos) //bit[12:08]: 一阶段采样
// |(7 << FDCAN_DBTP_DTSEG2_Pos) //bit[07:04]: 二阶段采样 波特率 = 8000000/(3+DTSEG1+DTSEG2) = 8000000/32 = 250k
// |(7 << FDCAN_DBTP_DSJW_Pos) //bit[03:00]: 同步脉宽
// ;
FDCAN1->IE |= 0
// |FDCAN_IE_ARAE //bit23: 访问保留地址使能
// |FDCAN_IE_PEDE //bit22: 数据阶段协议错误
// |FDCAN_IE_PEAE //bit21: 仲裁阶段协议错误
// |FDCAN_IE_WDIE //bit20: 看门狗使能
// |FDCAN_IE_BOE //bit19: 总线关闭使能
// |FDCAN_IE_EWE //bit18: 警告状态中断使能
// |FDCAN_IE_EPE //bit17: 错误被动中断使能
// |FDCAN_IE_ELOE //bit16: 错误记录语出中断使能
// |FDCAN_IE_TOOE //bit15: 超时中断使能
// |FDCAN_IE_MRAFE //bit14: 信息RAM访问失败中断使能
// |FDCAN_IE_TSWE //bit13: 时间戳重复中断使能
// |FDCAN_IE_TEFLE //bit12: TX事件FIFO元素丢失中断使能
// |FDCAN_IE_TEFFE //bit11: TX时间FIFO满中断使能
// |FDCAN_IE_TEFNE //bit10: TX事件FIFO新元素进入中断使能
// |FDCAN_IE_TFEE //bit09: TXFIFO空中断使能
// |FDCAN_IE_TCFE //bit08: 发送取消完成中断使能
|FDCAN_IE_TCE //bit07: 传输完成中断使能
// |FDCAN_IE_HPME //bit06: 高优先级消息中断使能
// |FDCAN_IE_RF1LE //bit05: RXFIFO1报文丢失中断使能
// |FDCAN_IE_RF1FE //bit04: RXFIFO1消息满中断使能
|FDCAN_IE_RF1NE //bit03: RXFIFO1新消息中断使能
// |FDCAN_IE_RF0LE //bit02: RXFIFO0报文丢失中断使能
// |FDCAN_IE_RF0FE //bit01: RXFIFO0消息满中断使能
|FDCAN_IE_RF0NE //bit00: RXFIFO0新消息中断使能
;
FDCAN1->ILE = 0x00000000
|FDCAN_ILE_EINT1 //bit01: 中断总线 fdcan_intr1_it 使能
|FDCAN_ILE_EINT0 //bit00: 中断总线 fdcan_intr0_it 使能
;
FDCAN1->RXGFC = 0
// |(0 << FDCAN_RXGFC_LSE_Pos) //bit[27:24]: 列表信息拓展【0|无拓展消息过滤】【1|1~8拓展消息】【>8|被解释为8】
|(1 << FDCAN_RXGFC_LSS_Pos) //bit[20:16]: 【0|无标准消息ID过滤】【1~28|标准消息ID元素过滤数量】【>28|被解释为28】
// |FDCAN_RXGFC_F0OM //bit09: FIFO0模式:覆盖或者堵塞【0|阻塞模式】【1|覆盖模式】
// |FDCAN_RXGFC_F1OM //bit08: FIFO1模式:覆盖或者堵塞【0|阻塞模式】【1|覆盖模式】
// |(0 << FDCAN_RXGFC_ANFS_Pos) //bit[05:04]: 定义如何处理接收到的id为11位且与筛选器列表中的任何元素不匹配的消息。【0|在FIFO0中接收】【1|在FIFO1中接收】【2~3|拒绝】
// |(0 << FDCAN_RXGFC_ANFE_Pos) //bit[03:02]: 定义如何处理接收到的id为29位且与筛选器列表中的任何元素不匹配的消息。【0|在FIFO0中接收】【1|在FIFO1中接收】【2~3|拒绝】
// |FDCAN_RXGFC_RRFS //bit01: 【1|拒绝所有11位ID远程标准帧】
// |FDCAN_RXGFC_RRFE //bit00: 【1|拒绝所有29位ID远程标准帧】
;
FDCAN1->XIDAM = 0x1FFFFFFF; //FDCAN 扩展 ID 和屏蔽寄存器
FDCAN1->TXBTIE = 0
// |0x00000004 //bit02: TxBuffer【1|发送中断使能】
// |0x00000002 //bit01: TxBuffer【1|发送中断使能】
|0x00000001 //bit00: TxBuffer【1|发送中断使能】
;
FDCAN1->TXBCIE = 0
// |0x00000004 //bit02: TxBuffer【1|取消中断使能】
// |0x00000002 //bit01: TxBuffer【1|取消中断使能】
// |0x00000001 //bit00: TxBuffer【1|取消中断使能】
;
FDCAN1_RAM->FILTER_11BIT[0] = 0x00000000
|(1 << FDCANx_RAM_FILTER11_S0_SFT_Pos)
|(1 << FDCANx_RAM_FILTER11_S0_SFEC_Pos)
|(0x209 << FDCANx_RAM_FILTER11_S0_SFID1_Pos)
|(0x609 << FDCANx_RAM_FILTER11_S0_SFID2_Pos)
;
// FDCAN1_RAM->FILTER_11BIT[1] = 0x00000000
// |(1 << FDCANx_RAM_FILTER11_S0_SFT_Pos)
// |(1 << FDCANx_RAM_FILTER11_S0_SFEC_Pos)
// |(0x209 << FDCANx_RAM_FILTER11_S0_SFID1_Pos)
// |(0x609 << FDCANx_RAM_FILTER11_S0_SFID2_Pos)
// ;
FDCAN1->RXGFC = 0x00000000
|(0 << FDCAN_RXGFC_LSE_Pos) //bit[27:24]: 29-bit ID列表大小【0|无拓展帧ID滤波】【1~8|29bitID列表大小数】【>8|认为是8】
|(1 << FDCAN_RXGFC_LSS_Pos) //bit[20:16]: 11-bit ID列表大小【0|无拓展帧ID滤波】【1~28|11bitID列表大小数】【>28|认为是28】
|FDCAN_RXGFC_F0OM //bit09: FIFO0的接收模式(【0|阻塞】或【1|覆盖】)
|FDCAN_RXGFC_F1OM //bit08: FIFO1的接收模式(【0|阻塞】或【1|覆盖】)
|(1 << FDCAN_RXGFC_ANFS_Pos) //bit[05:04]: 不匹配的29-bitID接收配置【0|FIFO0接收】【1|FIFO1接收】【2~3|拒绝】
|(1 << FDCAN_RXGFC_ANFE_Pos) //bit[03:02]: 不匹配的11-bitID接收配置【0|FIFO0接收】【1|FIFO1接收】【2~3|拒绝】
// |FDCAN_RXGFC_RRFS //bit01: 拒绝远程帧【1|拒绝所有带有 11 位标准 ID 的远程帧】
// |FDCAN_RXGFC_RRFE //bit00: 拒绝远程拓展帧【1|拒绝所有带有 29 位标准 ID 的远程帧】
;
FDCAN1->CCCR &= ~FDCAN_CCCR_INIT;
while (FDCAN1->CCCR & FDCAN_CCCR_INIT);
}
附录2 发送函数
/**
* @description: 经典CAN模式,11-bit地址,发送数据帧或远程帧,使用该函数之前应判断该信箱是否空闲,
* 否则会导致发送失败
* @param {uint16_t} ID 11位ID
* @param {uint8_t} RTR 【0|发送数据帧】【1|发送远程帧】
* @param {uint8_t} DLC 【0~8|发送数据数量为0~8】
* @param {uint8_t} *buffer 数据地址
* @return {*}
*/
void FDCAN1_TxBuffer1_SendData_11ID(uint16_t ID,uint8_t RTR,uint8_t DLC,Buffer_64Byte_Struct *buffer)
{
FDCAN1_TXBUFFER1->bit_11ID.T0_ESI = 0;//
FDCAN1_TXBUFFER1->bit_11ID.T0_XTD = 0;//【0|11-bit】【1|29-bit】
FDCAN1_TXBUFFER1->bit_11ID.T0_RTR = 0;//【0|发送数据帧】【1|发送远程帧】
FDCAN1_TXBUFFER1->bit_11ID.T0_ID = ID;
FDCAN1_TXBUFFER1->bit_11ID.T1_MM = 0;
FDCAN1_TXBUFFER1->bit_11ID.T1_EFC = 0;//【0|不保存TX事件】【1|保存】
FDCAN1_TXBUFFER1->bit_11ID.T1_FDF = 0;//【0|经典CAN】【1|FDCAN】
FDCAN1_TXBUFFER1->bit_11ID.T1_BRS = 0;//【0|无波特率切换】【1|有波特率切花】
FDCAN1_TXBUFFER1->bit_11ID.T1_DLC = DLC;//【0~8|发送数据为0~8】【9~15|经典CAN为8,FDCAN为12/16/20/24/32/48/64】
FDCAN1_TXBUFFER1->bit_11ID.DataWord[0] = buffer->DataWord[0];
FDCAN1_TXBUFFER1->bit_11ID.DataWord[1] = buffer->DataWord[1];
FDCAN1->TXBAR |= 0x00000000
// |BIT2
// |BIT1
|BIT0
;
}
附录3 中断程序
void FDCAN1_IT1_IRQHandler(void)
{
uint8_t temp;
if(FDCAN1->IR & FDCAN_IR_RF1N)//FIFO1有新消息标志
{
FDCAN1->IR |= FDCAN_IR_RF1N;//清除新消息标志
temp = FDCAN1->RXF1S & FDCAN_RXF1S_F1GI) >> FDCAN_RXF1S_F0GI_Pos;
CAN_Rxbuffer[4] = FDCAN1_RAM->Rx_FIFO_1[temp][0];//读取地址和拓展帧标志等
CAN_Rxbuffer[5] = FDCAN1_RAM->Rx_FIFO_1[temp][1];//读取数据长度等
CAN_Rxbuffer[6] = FDCAN1_RAM->Rx_FIFO_1[temp][2];//读取4byte数据
CAN_Rxbuffer[7] = FDCAN1_RAM->Rx_FIFO_1[temp][3];//读取4byte数据,算上上面的 一共8个byte
FDCAN1->RXF1A = temp;//返回读取完成
}
}
版权声明:本文为CSDN博主「Vice Versa XL」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xl22126/article/details/118514472
暂无评论