CAN - stm32f10x实现

STM32 自带的是 bxCAN,即基本扩展 CAN。它支持 CAN 协议 2.0A 和 2.0B。它的设计目标是,以最小的 CPU
负荷来高效处理大量收到的报文。它也支持报文发送的优先级要求(优先级特性可软件配置)。对于安全紧要的应用,bxCAN
提供所有支持时间触发通信模式所需的硬件功能。 STM32 的 bxCAN 的主要特点有:
 支持 CAN 协议 2.0A 和 2.0B
主动模式
 波特率最高达 1Mbps
 支持时间触发通信
 具有 3 个发送邮箱
 具有 3 级深度的 2 个接收 FIFO
 可变的过滤器组(最多 28 个)
在这里插入图片描述
如上图所示,stm32有两个can控制器,can1(主),和can2(从),其中过滤器的设置是通过can1来设置,其他工作模式,波特率等,可以各自设置。每个控制器有三个发送邮箱,两个fifo,每个fifo有三个接收邮箱。

发送:选择一个空的发送邮箱,把帧信息写到该发送邮箱的寄存器里,请求发送,控制器就会根据标识符的优先级把帧先后发送出去。

接收:如果接收到的帧的标识符能过过滤表的一系列过滤,该帧信息就会保存在fifo接收邮箱的寄存器里。

一.模式

一.工作模式

通过CAN_MCR寄存器控制INRQ和SLEEP
1.初始化 INRQ=1 SLEEP=0
软件初始化应该在硬件
2.正常 INRQ=0 SLEEP=0
在初始化完成后,软件应该让硬件进入正常模式,以便正常接收和发送报文
3.睡眠 SLEEP=1
bxCAN可工作在低功耗的睡眠模式

二.测试模式

通过CAN_BTR寄存器控制LBKM和SILM

  1. 静默 可以接受不能发送 LBKM=0 SLIM=1
    在这里插入图片描述
  2. 循回 可以发送不能接受 LBKM=1 SLIM=0
    3.环回静默 只能自发自收 LBKM=1 SLIM=1
    在这里插入图片描述
三.调试模式

**

2. **主控制寄存器 CAN_MCR

在这里插入图片描述

主控制寄存器 CAN_MCR 负责管理 CAN 的工作模式,它使用以下寄存器位实现控制。
(1) DBF 调试冻结功能
DBF(Debug freeze)调试冻结,使用它可设置 CAN 处于工作状态或禁止收发的状态,禁
止收发时仍可访问接收 FIFO 中的数据。这两种状态是当 STM32 芯片处于程序调试模
式时才使用的,平时使用并不影响。
(2) TTCM 时间触发模式
TTCM(Time triggered communication mode)时间触发模式,它用于配置 CAN 的时间触
发通信模式,在此模式下, CAN 使用它内部定时器产生时间戳, 并把它保存在
CAN_RDTxR、 CAN_TDTxR 寄存器中。内部定时器在每个 CAN 位时间累加,在接收
和发送的帧起始位被采样,并生成时间戳。 利用它可以实现 ISO 11898-4 CAN 标准的
分时同步通信功能。
(3) ABOM 自动离线管理
ABOM(Automatic bus-off management) 自动离线管理,它用于设置是否使用自动离线
管理功能。 当节点检测到它发送错误或接收错误超过一定值时,会自动进入离线状态,
在离线状态中, CAN 不能接收或发送报文。 处于离线状态的时候,可以软件控制恢复
或者直接使用这个自动离线管理功能,它会在适当的时候自动恢复。
(4) AWUM 自动唤醒
AWUM(Automatic bus-off management), 自动唤醒功能, CAN 外设可以使用软件进入低
功耗的睡眠模式,如果使能了这个自动唤醒功能,当 CAN 检测到总线活动的时候,
会自动唤醒。
(5) NART 自动重传
NART(No automatic retransmission)报文自动重传功能,设置这个功能后, 当报文发送
失败时会自动重传至成功为止。若不使用这个功能,无论发送结果如何,消息只发送
一次。
(6) RFLM 锁定模式
RFLM(Receive FIFO locked mode)FIFO 锁定模式,该功能用于锁定接收 FIFO。锁定后,
当接收 FIFO 溢出时,会丢弃下一个接收的报文。若不锁定,则下一个接收到的报文
会覆盖原报文。
(7) TXFP 报文发送优先级的判定方法
TXFP(Transmit FIFO priority)报文发送优先级的判定方法,当 CAN 外设的发送邮箱中
有多个待发送报文时,本功能可以控制它是根据报文的 ID 优先级还是报文存进邮箱的
顺序来发送。

位时序及波特率

在这里插入图片描述
STM32 的 CAN 外设位时序中只包含 3 段,分别是同步段 SYNC_SEG、位段 BS1 及位段 BS2,采样点位于 BS1 及 BS2 段的交界处。其中 SYNC_SEG 段固定长度为 1Tq,而BS1 及 BS2 段可以在位时序寄存器 CAN_BTR 设置它们的时间长度,它们可以在重新同步期间增长或缩短,该长度 SJW 也可在位时序寄存器中配置。
理解 STM32 的 CAN 外设的位时序时,可以把它的 BS1 段理解为是由前面介绍的CAN 标准协议中 PTS 段与 PBS1 段合在一起的,而 BS2 段就相当于 PBS2 段。了解位时序后,我们就可以配置波特率了。 通过配置位时序寄存器 CAN_BTR 的TS1[3:0]及 TS2[2:0]寄存器位设定 BS1 及 BS2 段的长度后,我们就可以确定每个 CAN 数据位的时间:
BS1 段时间:
TS1=Tq x (TS1[3:0] + 1),
BS2 段时间:
TS2= Tq x (TS2[2:0] + 1),
一个数据位的时间:
T1bit =1Tq+TS1+TS2 =1+ (TS1[3:0] + 1)+ (TS2[2:0] + 1)= N Tq
其中单个时间片的长度 Tq 与 CAN 外设的所挂载的时钟总线及分频器配置有关,CAN1 和 CAN2 外设都是挂载在 APB1 总线上的,而位时序寄存器 CAN_BTR 中的 BRP[9:0]。寄存器位可以设置 CAN 外设时钟的分频值 ,所以:
Tq = (BRP[9:0]+1) x TPCLK
其中的 PCLK 指 APB1 时钟,默认值为 36MHz。
最终可以计算出 CAN 通讯的波特率:
BaudRate = 1/N Tq在这里插入图片描述

二. STM32标识符筛选器

在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的优先级相关的。因此,节点在接收报文时-根据标识符的值-决定软件是否需要该报文;如果需要,就拷贝到SRAM里;如果不需要,报文就被丢弃且无需软件的干预。为满足这一需求,bxCAN为应用程序提供了14个位宽可变的、可配置的过滤器组(13~0),以便只接收那些软件需要的报文。硬件过滤的做法节省了CPU开销,否则就必须由软件过滤从而占用一定的CPU开销。
STM32普通型芯片的 CAN 有14组过滤器组(互联型有28组过滤器组) ,用以对接收到的帧进行过滤。每组过滤器包括了2个可配置的32位寄存器:CAN_FxR1和 CAN_FxR2。对于过滤器组,通过设置CAN_FM0R的FBMx位,

STM32 每个过滤器组的位宽都可以独立配置,以满足应用程序的不同需求。根据位宽的不同,每个过滤器组可提供:
● 1 个 32 位过滤器,包括:STDID[10:0]、EXTID[17:0]、IDE 和 RTR 位
● 2 个 16 位过滤器,包括:STDID[10:0]、IDE、RTR 和 EXTID[17:15]位
此外过滤器可配置为,屏蔽位模式标识符列表模式
在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按照**“必须匹配”或“不用关心”**处理。
而在标识符列表模式下,屏蔽寄存器也被当作标识符寄存器用。因此,不是采用一个标识符加一个屏蔽位的方式,而是使用 2 个标识符寄存器。接收报文标识符的每一位都必须跟过滤器标识符相同。
1.屏蔽位模式
这样 CAN_FxR0中保存的就是标识符匹配值,CAN_FxR2中保存的是屏蔽码,即 CAN_FxR2中如果某一位为1,则 CAN_FxR1中相应的位必须与收到的帧的标志符中的相应位吻合才能通过过滤器。CAN_FxR2中为0的位表示 CAN_FxR1中的相应位可不必与收到的帧进行匹配。
2.标识符列表模式
此时 CAN_FxR1和CAN_FxR2中的都是要匹配的标识符,收到的帧的标识符必须与其中的一个吻合才能通过过滤。
理解:标识符列表模式是为了过滤出一个标识符,而屏蔽位模式因为屏蔽了某些位所以可以过滤出一组标识符,对于不需要用筛选器组的应处以禁用状态
一般我们用的都是普通型的,所以在本文中可以说 STM32有14组过滤器组。根据配置,每1组过滤器组可以有1个,2个或4个过滤器。这些过滤器相当于关卡,每当收到一条报文时,CAN 要先将收到的报文从这些过滤器上”过”一下,能通过的报文是有效报文,收进 FIFO,不能通过的是无效报文(不是发给”我”的报文),直接丢弃。通过对两个可配置寄存器值得改变可以选择过滤器的数量。在一组过滤器中,整组的过滤器都使用同一种工作模式。
另外,每组过滤器中的过滤器宽度是可变的,可以是32位或16位。按工作模式和宽度,一个过滤器组可以变成以下几中形式之一:
(1) 1个32位的屏蔽位模式的过滤器。
(2) 2个32位的列表模式的过滤器。
(3) 2个16位的屏蔽位模式的过滤器。
(4) 4个16位的列表模式的过滤器。
所有的过滤器是并联的,即一个报文只要通过了一个过滤器,就是算是有效的。每组过滤器组有两个32位的寄存器用于存储过滤用的”标准值”,分别是 FxR1,FxR2.
在这里插入图片描述

1.在32位的屏蔽位模式下: 有1个过滤器。 FxR2用于指定需要关心哪些位,FxR1用于指定这些位的标准值。
2.在32位的列表模式下: 有两个过滤器。 FxR1指定过滤器0的标准值,收到报文的标识符只有跟 FxR1完全相同时,才算通过。 FxR2指定过滤器1的标准值。
3.在16位的屏蔽位模式下: 有2个过滤器。 FxR1配置过滤器0,其中,[31-16]位指定要关心的位,[15-0]位指定这些位的标准值。 FxR2配置过滤器1,其中,[31-16]位指定要关心的位,[15-0]位指定这些位的标准值。
4.在16位的列表模式下: 有4个过滤器。 FxR1的[15-0]位配置过滤器0,FxR1的[31-16]位配置过滤器1。 FxR2的[15-0]位配置过滤器2,FxR2的[31-16]位配置过滤器3。

标识符筛选器通俗理解

为了过滤出一组标识符,应该设置过滤器组工作在屏蔽位模式。
为了过滤出一个标识符,应该设置过滤器组工作在标识符列表模式。
应用程序不用的过滤器组,应该保持在禁用状态。
过滤器组中的每个过滤器,都被编号为(叫做过滤器号,图 30.1.11 中的 n)从 0 开始,到某个最大数值-取决于过滤器组的模式和位宽的设置。
举个简单的例子,我们设置过滤器组 0 工作在:1 个 32 为位过滤器-标识符屏蔽模式,然后设置 CAN_F0R1=0XFFFF0000,CAN_F0R2=0XFF00FF00。其中存放到 CAN_F0R1 的值就是期望收到的 ID,即我们希望收到的映像(STID+EXTID+IDE+RTR)最好是:0XFFFF0000。而0XFF00FF00 就是设置我们需要必须关心的 ID,表示收到的映像,其位[31:24]和位[15:8]这 16个位的必须和 CAN_F0R1 中对应的位一模一样,而另外的 16 个位则不关心,可以一样,也可以不一样,都认为是正确的 ID,即收到的映像必须是 0XFFxx00xx,才算是正确的(x 表示不关心)。

在这里插入图片描述

通过配置筛选模式寄存器 CAN_FM1R 的 FBMx 位可以设置筛选器工作在哪个模式

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

三。发送接收流程

CAN 发送流程为:
 程序选择 1 个空置的邮箱(TME=1)
 设置标识符(ID),数据长度和发送数据
 设置 CAN_TIxR 的 TXRQ 位为 1,请求发送
 邮箱挂号(等待成为最高优先级)
 预定发送(等待总线空闲)
 发送
 邮箱空置。

CAN 发送邮箱

在这里插入图片描述
每个发送邮箱中包含有标识符寄存器 CAN_TIxR、数据长度控制寄存器 CAN_TDTxR及 2 个数据寄存器 CAN_TDLxR、 CAN_TDHxR,
在这里插入图片描述
当我们要使用 CAN 外设发送报文时,把报文的各个段分解,按位置写入到这些寄存器中,并对标识符寄存器 CAN_TIxR 中的发送请求寄存器位 TMIDxR_TXRQ 置 1,即可把数据发送出去。
其中标识符寄存器 CAN_TIxR 中的 STDID 寄存器位比较特别。我们知道 CAN 的标准标识符的总位数为 11 位,而扩展标识符的总位数为 29 位的。当报文使用扩展标识符的时候,标识符寄存器 CAN_TIxR 中的 STDID[10:0]等效于 EXTID[18:28]位,它与 EXTID[17:0]共同组成完整的 29 位扩展标识符。

CAN 接收 FIFO

CAN 接收到的有效报文,被存储在 3 级邮箱深度的 FIFO 中。 FIFO 完全由硬件来管理,从 而节省了 CPU的处理负荷,简化了软件并保证了数据的一致性。应用程序只能通过读取 FIFO 输出邮箱,来读取 FIFO中最先收到的报文。这里的有效报文是指那些正确被接收的(直到 EOF 都没有错误)且通过了标识符过滤的报文。前面我们知道 CAN 的接收有 2个 FIFO,我们每个 滤波器组都可以设置其关联的 FIFO,通过 CAN_FFA1R 的设置,可以将滤波器组关联到FIFO0/FIFO1。
CAN 接收流程为:
FIFO 空
收到有效报文
挂号_1(存入 FIFO 的一个邮箱,这个由硬件控制,我们不需要理会)
收到有效报文挂号_2
收到有效报文挂号_3
收到有效报文
 溢出。
这个流程里面,我们没有考虑从 FIFO读出报文的情况,实际情况是:我们必须在 FIFO 溢 出之前,读出至少 1 个报文,否则下个报文到来,将导致 FIFO溢出,从而出现报文丢失。每 读出 1 个报文,相应的挂号就减 1,直到 FIFO 空。
在这里插入图片描述
CAN 外设框图,在标号处的是 CAN 外设的接收 FIFO,它一共有 2 个接收 FIFO,每个 FIFO 中有 3 个邮箱,即最多可以缓存 6 个接收到的报文。当接收到报文时, FIFO 的报文计数器会自增,而 STM32 内部读取 FIFO 数据之后,报文计数器会自减,我们通过状态寄存器可获知报文计数器的值,而通过前面主控制寄存器的 RFLM 位,可设置锁定模式,锁定模式下 FIFO 溢出时会丢弃新报文,非锁定模式下 FIFO 溢出时新报文会覆盖旧报文。跟发送邮箱类似,每个接收 FIFO 中包含有标识符寄存器 CAN_RIxR、数据长度控制寄存器 CAN_RDTxR 及 2 个数据寄存器 CAN_RDLxR、 CAN_RDHxR。
在这里插入图片描述
通过中断或状态寄存器知道接收 FIFO 有数据后,我们再读取这些寄存器的值即可把接收到的报文加载到 STM32 的内存中。

四。stm32配置步骤

4.1 配置相关引脚的复用功能,使能 CAN 时钟。

我们要用 CAN,第一步就要使能 CAN 的时钟。其次要设置 CAN 的相关引脚为复用输出,这里我们需要设置 PA11 为上拉输入(CAN_RX 引脚) PA12 为复用输出(CAN_TX 引脚),并使能 PA 口的时钟。 使能 CAN1 时钟的函数是:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能 CAN1 时钟

4.2 2)设置 CAN 工作模式及波特率等。

这一步通过先设置 CAN_MCR 寄存器的 INRQ 位,让 CAN 进入初始化模式,然后设置CAN_MCR 的其他相关控制位。再通过 CAN_BTR 设置波特率和工作模式(正常模式/环回模式)等信息。 最后设置 INRQ 为 0,退出初始化模式。
在库函数中,提供了函数 CAN_Init()用来初始化 CAN 的工作模式以及波特率, CAN_Init()函数体中,在初始化之前,会设置 CAN_MCR 寄存器的 INRQ 为 1 让其进入初始化模式,然后初始化 CAN_MCR 寄存器和 CRN_BTR 寄存器之后,会设置 CAN_MCR 寄存器的 INRQ 为 0让其退出初始化模式。所以我们在调用这个函数的前后不需要再进行初始化模式设置。 下面我们来看看 CAN_Init()函数的定义:

uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct);

第一个参数就是 CAN 标号。
第二个参数是 CAN 初始化结构体指针,结构体类型是 CAN_InitTypeDef,下面我们来看看这个
结构体的定义:
在这里插入图片描述
1) CAN_Prescaler

本成员设置 CAN 外设的时钟分频,它可控制时间片 Tq 的时间长度,这里设置的值最终会减 1 后再写入 BRP 寄存器位,即前面介绍的 Tq 计算公式:
Tq = (BRP[9:0]+1) x TPCLK
等效于: Tq = CAN_Prescaler x TPCLK

(2) CAN_Mode
本成员设置 CAN 的工作模式,可设置为正常模式(CAN_Mode_Normal)、回环模式(CAN_Mode_LoopBack) 、 静 默 模 式 (CAN_Mode_Silent) 以 及 回 环 静 默 模 式(CAN_Mode_Silent_LoopBack)。

(3) CAN_SJW
本成员可以配置 SJW 的极限长度,即 CAN 重新同步时单次可增加或缩短的最大长度,它可以被配置为 1-4Tq(CAN_SJW_1/2/3/4tq)。

(4) CAN_BS1
本成员用于设置 CAN 位时序中的 BS1 段的长度,它可以被配置为 1-16 个 Tq 长度
(CAN_BS1_1/2/3…16tq)。

(5) CAN_BS2
本成员用于设置 CAN 位时序中的 BS2 段的长度,它可以被配置为 1-8 个 Tq 长度(CAN_BS2_1/2/3…8tq)。
SYNC_SEG、 BS1 段及 BS2 段的长度加起来即一个数据位的长度,即前面介绍的原来计算公式:
T1bit =1Tq+TS1+TS2 =1+ (TS1[3:0] + 1)+ (TS2[2:0] + 1)
等效于: T1bit = 1Tq+CAN_BS1+CAN_BS2

(6) CAN_TTCM
本成员用于设置是否使用时间触发功能(ENABLE/DISABLE),时间触发功能在某些CAN 标准中会使用到。

(7) CAN_ABOM
本成员用于设置是否使用自动离线管理(ENABLE/DISABLE),使用自动离线管理可以在节点出错离线后适时自动恢复,不需要软件干预。

(8) CAN_ AWUM
本成员用于设置是否使用自动唤醒功能(ENABLE/DISABLE),使能自动唤醒功能后它会在监测到总线活动后自动唤醒。

(9) CAN_ABOM
本成员用于设置是否使用自动离线管理功能(ENABLE/DISABLE),使用自动离线管理可以在出错时离线后适时自动恢复,不需要软件干预。

(10) CAN_NART
本成员用于设置是否使用自动重传功能(ENABLE/DISABLE),使用自动重传功能时,会一直发送报文直到成功为止。

(11) CAN_RFLM
本成员用于设置是否使用锁定接收 FIFO(ENABLE/DISABLE),锁定接收 FIFO 后,若FIFO 溢出时会丢弃新数据,否则在 FIFO 溢出时以新数据覆盖旧数据。

(12) CAN_RFLM
本成员用于设置发送报文的优先级判定方法(ENABLE/DISABLE),使能时,以报文存入发送邮箱的先后顺序来发送,否则按照报文 ID 的优先级来发送。配置完这些结构体成员后,我们调用库函数 CAN_Init 即可把这些参数写入到 CAN 控制寄存器中,实现 CAN 的初始化。

CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式
CAN_InitStructure.CAN_ABOM=DISABLE; //软件自动离线管理
CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒
CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送
CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的
CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定
CAN_InitStructure.CAN_Mode= CAN_Mode_LoopBack; //模式设置: 1,回环模式;
//设置波特率
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;//重新同步跳跃宽度为1个时间单位
CAN_InitStructure.CAN_BS1=CAN_BS1_8tq; //时间段 1 占用 8 个时间单位
CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;//时间段 2 占用 7 个时间单位
CAN_InitStructure.CAN_Prescaler=5; //分频系数(Fdiv)
CAN_Init(CAN1, &CAN_InitStructure); // 初始化 CAN1

4.3 设置滤波器。

我们将使用滤波器组 0,并工作在 32 位标识符屏蔽位模式下。先设置 CAN_FMR的 FINIT 位,让过滤器组工作在初始化模式下,然后设置滤波器组 0 的工作模式以及标识符 ID和屏蔽位。最后激活滤波器,并退出滤波器初始化模式。
在库函数中,提供了函数 CAN_FilterInit ()用来初始化 CAN 的滤波器相关参数, CAN_Init()函数体中,在初始化之前,会设置 CAN_FMR 寄存器的 INRQ 为 INIT 让其进入初始化模式,然后初始化 CAN 滤波器相关的寄存器之后,会设置 CAN_FMR 寄存器的 FINIT 为 0 让其退出初始化模式。所以我们在调用这个函数的前后不需要再进行初始化模式设置。下面我们来看看
CAN_FilterInit ()函数的定义:

void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct);

这 个 函 数 只 有 一 个 入 口 参 数 就 是 CAN 滤 波 器 初 始 化 结 构 体 指 针 , 结 构 体 类 型 为CAN_FilterInitTypeDef,下面我们看看类型定义
在这里插入图片描述
(1) CAN_FilterIdHigh
CAN_FilterIdHigh 成员用于存储要筛选的 ID,若筛选器工作在 32 位模式,它存储的是所筛选 ID 的高 16 位;若筛选器工作在 16 位模式,它存储的就是一个完整的要筛选的 ID。

(2) CAN_FilterIdLow
类似地, CAN_FilterIdLow 成员也是用于存储要筛选的 ID,若筛选器工作在 32 位模式,它存储的是所筛选 ID 的低 16 位;若筛选器工作在 16 位模式,它存储的就是一个完整的要筛选的 ID。

(3) CAN_FilterMaskIdHigh
CAN_FilterMaskIdHigh 存储的内容分两种情况,当筛选器工作在标识符列表模式时,它的功能与 CAN_FilterIdHigh 相同,都是存储要筛选的 ID; 而当筛选器工作在掩码模式时,它存储的是 CAN_FilterIdHigh 成员对应的掩码,与 CAN_FilterIdLow 组成一组筛选器。

(4) CAN_FilterMaskIdLow
类似地, CAN_FilterMaskIdLow 存储的内容也分两种情况,当筛选器工作在标识符列表模式时,它的功能与 CAN_FilterIdLow 相同,都是存储要筛选的 ID; 而当筛选器工作 在 掩 码 模 式 时 , 它 存 储 的 是 CAN_FilterIdLow 成 员 对 应 的 掩 码 , 与CAN_FilterIdLow 组成一组筛选器。
在这里插入图片描述
(5) CAN_FilterFIFOAssignment
本成员用于设置当报文通过筛选器的匹配后,该报文会被存储到哪一个接收 FIFO,它的可选值为 FIFO0 或 FIFO1(CAN_Filter_FIFO0/1)。

(6) CAN_FilterNumber
本成员用于设置筛选器的编号,即本过滤器结构体配置的是哪一组筛选器, CAN 一共有 28 个筛选器,所以它的可输入参数范围为 0-27(STM32F103 系列芯片的可输入参数为 0-13)。

(7) CAN_FilterMode
本成员用于设置筛选器的工作模式,可以设置为列表模式(宏 CAN_FilterMode_IdList)及掩码模式(宏 CAN_FilterMode_IdMask)。

(8) CAN_FilterScale
本成员用于设置筛选器的尺度,可以设置为 32 位长(宏 CAN_FilterScale_32bit)及 16 位长(宏 CAN_FilterScale_16bit)。

(9) CAN_FilterActivation
本成员用于设置是否激活这个筛选器(宏 ENABLE/DISABLE)。

CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器 0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32 位
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32 位 ID
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32 位 MASK
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;// FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器 0
CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化

4.4 发送接受消息

在这里插入图片描述
(1) StdId
本成员存储的是报文的 11 位标准标识符,范围是 0-0x7FF。

(2) ExtId
本成员存储的是报文的 29 位扩展标识符,范围是 0-0x1FFFFFFF。 ExtId 与 StdId 这两个成员根据下面的 IDE 位配置,只有一个是有效的。

(3) IDE
本成员存储的是扩展标志 IDE 位,当它的值为宏 CAN_ID_STD 时表示本报文是标准帧,使用 StdId 成员存储报文 ID;当它的值为宏 CAN_ID_EXT 时表示本报文是扩展帧,使用 ExtId 成员存储报文 ID。

(4) RTR
本成员存储的是报文类型标志 RTR 位,当它的值为宏 CAN_RTR_Data 时表示本报文是数据帧;当它的值为宏 CAN_RTR_Remote 时表示本报文是遥控帧,由于遥控帧没有数据段,所以当报文是遥控帧时,下面的 Data[8]成员的内容是无效的。

(5) DLC*
本成员存储的是数据帧数据段的长度,它的值的范围是 0-8,当报文是遥控帧时 DLC值为 0。

(6) Data[8]
本成员存储的就是数据帧中数据段的数据。

(7) FMI
本成员只存在于接收结构体,它存储了筛选器的编号,表示本报文是经过哪个筛选器存储进接收 FIFO 的,可以用它简化软件处理。当需要使用 CAN 发送报文时,先定义一个上面发送类型的结构体,然后把报文的内容按成员赋值到该结构体中,最后调用库函数 CAN_Transmit 把这些内容写入到发送邮箱即可把报文发送出去。
接收报文时,通过检测标志位获知接收 FIFO 的状态,若收到报文,可调用库函数CAN_Receive 把接收 FIFO 中的内容读取到预先定义的接收类型结构体中,然后再访问该结构体即可利用报文了。

库函数中提供了发送和接受消息的函数。 发送消息的函数是:

uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage);

这个函数比较好理解,第一个参数是 CAN 标号,我们使用 CAN1。第二个参数是相关消息结构体 CanTxMsg 指针类型, CanTxMsg 结构体的成员变量用来设置标准标识符,扩展标示符,消息类型和消息帧长度等信息。
接受消息的函数是:

void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage);

前面两个参数也比较好理解, CAN 标号和 FIFO 号。 第二个参数 RxMessage 是用来存放接受到的消息信息。
结构体 CanRxMsg 和结构体 CanTxMsg 比较接近,分别用来定义发送消息和描述接受消息,大家可以对照看一下,也比较好理解。

4.5 CAN 状态获取

对于 CAN 发送消息的状态,挂起消息数目等等之类的传输状态信息,库函数提供了一些列的函数,包括 CAN_TransmitStatus()函数, CAN_MessagePending()函数, CAN_GetFlagStatus()函数等等,根据需要来调用。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值