can协议规范,can协议的特点是什么

一、CAN协议概念1.1 CAN 协议简介CAN 是控制器局域网络 (Controller Area Network) 的简称,它是由研发和生产汽车电子产品著称

1. CAN协议概念

1.1 CAN 协议简介

CAN是Controller Area Network的缩写,由以开发和制造汽车电子产品而闻名的德国公司BOSCH开发,并最终成为国际标准(ISO11519和ISO11898)。世界上使用最广泛的现场总线之一。差异是:

696de35abbf24289b4ac8fd6551e103a~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=SsRp7O59DVPhMMpZtLZAlD%2BiJ4Y%3D

CAN总线协议已成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,其中J1939协议是专为重型卡车和重型装备车辆设计的,采用CAN作为底层协议。近年来,它们以其高可靠性和优异的错误检测能力而受到关注,广泛应用于汽车计算机控制系统和存在恶劣环境温度、强电磁辐射和大振动的工业环境中。

我们先贴一张车载网络的概念图。

14c0eaaef2a149c78b55ef6c0a72a8b3~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=KHZZPZkaHwMZXnOyxa4d8XbH6lI%3D

1.2 CAN 物理层

与使用I2C 和SPI 等时钟信号的同步通信不同,CAN 通信不使用时钟信号进行同步,而是仅使用CAN_High 和CAN_Low 两条信号线作为一组,使用差分信号线进行通信。以差分信号的形式。我们看一下示意图

6c4e2fee068c4c8d9a5fdcdc5fb6c265~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=P7kI1W8z%2BaM2%2B79tvaUNb5kzlJs%3D

1.2.1 闭环总线网络

CAN物理层有两种主要形式。所示的CAN通信网络是一个符合ISO11898标准的高速、短距离“闭环网络”。其最大总线长度为40m。最大通讯速度为1Mbps。总线电路的两端都需要一个120欧姆的电阻。

f13b5166f0634c50b1a203c456542912~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=ZmwhYdM0iEqxqochKYqZ40BpQ48%3D

1.2.2 开环总线网络

照片为符合ISO11519-2标准的低速长距离“开环网络”。 最大传输距离1km,最大通信速度125kbps。两辆巴士是独立的。每条总线上串联一个2.2 k 电阻。

81e28d0fe28548c59688f0ab536ddbb0~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=tQwLI%2B093sQmoNI6med0w0gESKA%3D

从CAN通信网络图中我们可以看到,一条CAN总线上可以挂载多个通信节点,节点之间的通信是通过总线在节点之间传输信号来实现的。由于CAN通信协议不编码节点的地址,而是数据的内容,因此理论上网络中的节点数量没有限制,只要总线负载足够,并且可以通过中继器路由可以增加负载。

CAN通信节点由CAN控制器和CAN收发器组成。控制器和收发器通过CAN_Tx 和CAN_Rx 信号线连接。收发器使用CAN_High 和CAN_Low 信号线连接到CAN 总线。其中,CAN_Tx和CAN_Rx使用普通的类似TTL的逻辑信号,而CAN_High和CAN_Low是一对使用特殊差分信号的差分信号线,这将在下一节中详细解释。

当CAN节点需要传输数据时,控制器通过CAN_Tx线向收发器发送二进制代码,收发器将这个正常逻辑电平信号转换为差分信号,并将其发送到CAN_High和CAN_Low线输出。通过差分线。当总线上的数据通过收发器接收并发送到控制器时,收发器将总线上接收到的CAN_High 和CAN_Low 信号转换为正常逻辑电平信号,并通过CAN_Rx 输出到控制器。

例如,STM32 CAN片上外设是一个通信节点控制器,必须连接外部收发器才能形成完整的节点。实验板上采用型号为TJA1050的芯片作为CAN。收发器。 CAN控制器和CAN收发器之间的关系类似于TTL串口和MAX3232电平转换芯片之间的关系。 MAX3232芯片将TTL电平串口信号转换为RS-232电平串口信号。 CAN 收发器转换CAN。控制器将TTL 电平信号转换为差分信号,反之亦然。

目前,有以下(但不是全部)CAN电平转换芯片可供选择:

a487b4d2501242b7a39aa74f67981874~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=c3DiAHGfjVUapg9Btxh96qhtTxw%3D

我们来看一下使用TJA1050的电路图。

b9ba8ce00f8b4e27ad88bf5f416992c8~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=xqK%2BsTNgrSUioLL121m21Wuib24%3D

1.2.3 通讯节点

差分信号也称为差模信号。使用差分信号不同于使用单个信号线电压表示逻辑的传统方法。它表示为同相、反相的两条信号线之间的电压差。

逻辑0 和逻辑1。参见插图。该图使用V+ 和V- 信号之间的差异来表示图底部的信号。

b1857d60a1a9411cbcb97a675e4e62b6~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=ZkTUGS5QLZ7L0qCiJIDFa%2Bzkhns%3D

与单信号线传输相比,差分信号传输具有以下优点:

• 抗干扰能力强。在存在外部噪声干扰的情况下,接收器仅考虑两个信号之间的差异,因此考虑外部共模。噪音可以完全消除。

例如,在正常的单线上,预计逻辑1为3.3V,逻辑0为0V,但如果有噪声,3.3V变为0V(极端),0V变为-3.3到V。是错误的,Can high/Can low 通常使用两条线,因此两者都会受到噪声的影响,但差异保持不变。

• 同样,两个信号耦合得越近,向外界发射的电磁能量就越少,因为两个信号的极性相反。外面的世界。

例如,假设一根线是10V,另一根是-10V,每根线都会对外界产生电磁干扰,但是CAN允许你像编织物一样将线绞在一起,它们就可以抵消电子干扰。

• 精确的授时定位。与依赖高阈值电压和低阈值电压做出决策的普通单端信号不同,差分信号的开关变化位于两个信号的交叉点,这使得它们对过程和温度不太敏感。它可以减少时序误差,也适用于低幅度信号的电路。

由于差分信号线的这些优点,USB、485、以太网和CAN协议的物理层都采用差分信号传输。

1.2.4 差分信号

CAN 协议指定使用CAN_High 和CAN_Low 表示的差分信号。见表和图。以高速CAN协议为例,表示逻辑1(隐性电平)时,CAN_High和CAN_Low线上的电压均为2.5V,即表示逻辑时,两者的电压差为VH-V:sub:L=马苏。 0(显性电平)电平),CAN_High线的电平为3.5V,CAN_Low线的电平为1.5V,即它们之间的电压差为VH-V:sub:L=2V。例如,当CAN收发器在CAN_Tx线上接收到来自CAN控制器的低电平信号(逻辑0)时,CAN_High输出3.5V,CAN_Low输出1.5V,从而产生代表逻辑0的显性电平输出。

d76a7f73d99544d59cc82f1e49579224~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=w3yodOKctXFfmBxLqdvCurkCnbI%3D

e78d883991184c338028245410f806e3~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=0C3ahVYZF%2FovArtlSvZ2sT2%2B44w%3D

CAN 总线必须处于隐性电平(逻辑1)或显性电平(逻辑0)。如果有两个CAN通信节点,一个输出隐性电平,另一个输出显性电平。这类似于I2C总线的“线与”特性。人们认为名称的起源,即明确性,是优先考虑的。

由于CAN 总线协议的物理层只有一对差分线,每次只能向通信节点表示一个信号,因此CAN 通信是半双工的,这意味着只能使用一种方法发送和接收数据。你需要做。分时法。在CAN通信网络中,总线是共享的,因此一次只有一个通信节点可以通过网络发送信号,其余节点只能接收该时刻的信号。

1.2.5 CAN 协议中的差分信号

1.3 CAN 协议层

由于CAN是异步通信,没有时钟信号线,因此连接到同一总线网络的各个节点可以使用约定的波特率相互通信,类似于串口异步通信。还采用“同步”的方法来容忍干扰、吸收误差,实现总线电平信号的正确采样,保证通信成功。

1.3.1 CAN 的波特率及位同步

为了实现位同步,CAN协议将每个数据位的时序分解为SS段、PTS段、PBS1段和PBS2段,如图所示。这四段的长度加起来为1。 CAN 数据位长度。分解后的最小时间单位是Tq,一个完整的比特由8到25个Tq组成。为了便于表示,图中的高低电平直接代表信号的逻辑0或逻辑1(不是差分信号)。

a09c8a61da5445d399aad6ca748237c2~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=teg6L8374hg7Is5xi3zQJ7PMsyo%3D

该图所示的CAN通信信号每个数据位的长度为19Tq,其中SS段占用1Tq,PTS段占用6Tq,PBS1段占用5Tq,PBS2段占用7Tq。信号采样点位于PBS1和PBS2段之间,通过控制每段的长度,可以偏移采样点位置以实现精确采样。

下面介绍各段的作用。

SS段(SYNC SEG)

SS 翻译为同步段。当通信节点检测到总线上信号的跳变沿包含在SS段内时,意味着节点和总线的时序同步。与总线同步采集采样点。总线电平可以通过该位的电平来确定。 SS段的大小固定为1Tq。

PTS部分(PROP SEG)

PTS翻译为传播时间,用于补偿网络中的物理延迟时间。这是输入比较器延迟加上总线上的输出驱动器延迟的两倍。 PTS 段大小为1-8Tq。

PBS1段(PHASE SEG1),

PBS1被转换为相位缓冲段,主要用于补偿边缘阶段的误差,并且可以在重新同步期间增加其时间长度。 PBS1 段的初始大小为1-8Tq。

PBS2段(PHASE SEG2)

PBS2 这是另一个相位缓冲段,也用于补偿边缘相位误差,从而允许在重新同步期间缩短其时间长度。 PBS2 段的初始大小为2-8Tq。

1.3.2 位时序分解

总线上的每个通信节点可以通过约定1 Tq中的时间长度以及每个数据位占用多少Tq来确定CAN通信的波特率。

例如上图中,如果1Tq=1us,每个数据位由19个Tq组成,则发送1位数据需要T1bit=19us,所以每秒可以发送的数据位数将如下所示: 1×10/19=52631.6(bps)

通信中每秒可以发送的数据位数就是波特率。

1.3.3 通讯的波特率

波特率仅指定每个数据位的长度。数据同步还包括阶段详细信息。您必须在数据位中使用SS、PTS、PBS1 和PBS2 段。根据段的应用方式不同,CAN数据同步可分为硬同步和重同步。硬同步仅在存在“帧开始信号”时才起作用,并且不能保证后续位的时序同步。这个问题可以通过两种方式解决:

(1)硬同步

当CAN节点通过总线发送数据时,它会发送一个指示通信开始的信号(即帧开始信号,我们将在下一节中介绍)。这是一个从高到低的下降沿。每当CAN 总线上的通信节点不传输数据时,它们就会检测总线上的信号。参见图,当总线上出现帧起始信号时,节点检测到总线上的帧起始信号不在节点内部时序的SS段范围内,并确定自己的内部时序。这种情况会导致采样点采集的数据不正确,因为它与总线不同步。因此,节点采用硬同步方法进行调整,将具有自己位定时的SS段移至总线下降沿出现的部分,一旦获得同步,采样点即可采集到正确的数据。

cd7ab59cd80c4392a70ec1501a5a651b~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=j7iZSH48qSqP5rZoKmOVcsT1ljk%3D

(2)重新同步

旧的硬同步仅在存在帧开始信号时才起作用。如果节点和总线信号的相位在很长的数据帧内发生偏移,则该同步方法没有用处。因此,必须引入一种重新同步方法,利用常规数据位的高到低跳变沿进行同步(帧起始信号是特殊的跳变沿)。重新同步和硬同步的相似之处在于它们都使用SS段进行检测。同步的目的是将过渡边包含在节点内的SS 段中。根据总线转换沿与SS段的相对位置,重同步方法分为超前和滞后两种情况。初始阶段推进情况如图所示。根据总线上的边沿转换,节点检测到其内部时序相对于总线时序为2Tq。此时控制器增加2Tq的时间长度。 PBS1 段下一位的时序。重新同步节点和总线时序。

;from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=u9owCsWP0WU5vm%2Bx0N6%2FR6EjujE%3D” />
第二种相位滞后的情况如图 ,节点从总线的边沿跳变中,检测到它的时序比总线的时序相对滞后 2Tq,这时控制器在前一个位时序中的 PBS2 段减少 2Tq 的时间长度,获得同步。
451f36eec6454a30bfbf016fec33a980~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=9CH%2FYDQVxCvkq%2B1tceCs9sDiovo%3D
在重新同步的时候,PBS1 和 PBS2 中增加或减少的这段时间长度被定义为“重新同步补偿宽度SJW* (reSynchronization Jump Width)”。一般来说 CAN 控制器会限定 SJW 的最大值,如限定了最大 SJW=3Tq 时,单次同步调整的时候不能增加或减少超过 3Tq 的时间长度,若有需要,控制器会通过多次小幅度调整来实现同步。当控制器设置的 SJW 极限值较大时,可以吸收的误差加大,但通讯的速度会下降

1.3.5 CAN 的报文种类及结构

在 SPI 通讯中,片选、时钟信号、数据输入及数据输出这 4 个信号都有单独的信号线,I2C 协议包含有时钟信号及数据信号 2 条信号线,异步串口包含接收与发送 2 条信号线,这些协议包含的信号都比 CAN 协议要丰富,它们能轻易进行数据同步或区分数据传输方向。而 CAN 使用的是两条差分信号线,只能表达一个信号,简洁的物理层决定了 CAN 必然要配上一套更复杂的协议,如何用一个信号通道实现同样、甚至更强大的功能呢?CAN 协议给出的解决方案是对数据、操作命令 (如读/写) 以及同步信号进行打包,打包后的这些内容称为报文。

1.3.5.1 报文的种类

在原始数据段的前面加上传输起始标签、片选 (识别) 标签和控制标签,在数据的尾段加上 CRC校验标签、应答标签和传输结束标签,把这些内容按特定的格式打包好,就可以用一个通道表达各种信号了,各种各样的标签就如同 SPI 中各种通道上的信号,起到了协同传输的作用。当整个数据包被传输到其它设备时,只要这些设备按格式去解读,就能还原出原始数据,这样的报文就被称为 CAN 的“数据帧”。
为了更有效地控制通讯,CAN 一共规定了 5 种类型的帧,它们的类型及用途说明如表
54baed57f45c495c9ae93d10a309f7ee~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=37SBKC%2BSJ3Op3kQeFVuVVBI8VGo%3D

1.3.5.2 数据帧的结构

数据帧是在 CAN 通讯中最主要、最复杂的报文,我们来了解它的结构,见图
90b400684c5b41f2ac21e67064078c07~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=TNiZoLck1%2FPLbXXj0FRHCPdlqCo%3D
数据帧以一个显性位 (逻辑 0) 开始,以 7 个连续的隐性位 (逻辑 1) 结束,在它们之间,分别有仲裁段、控制段、数据段、CRC 段和 ACK 段。
• 帧起始
SOF 段 (Start OfFrame),译为帧起始,帧起始信号只有一个数据位,是一个显性电平,它用于通知各个节点将有数据传输,其它节点通过帧起始信号的电平跳变沿来进行硬同步。
• 仲裁段
当同时有两个报文被发送时,总线会根据仲裁段的内容决定哪个数据包能被传输,这也是它名称的由来。
仲裁段的内容主要为本数据帧的 ID 信息 (标识符),数据帧具有标准格式和扩展格式两种,区别就在于 ID 信息的长度,标准格式的 ID 为 11 位,扩展格式的 ID 为 29 位,它在标准 ID 的基础上多出 18 位。在 CAN 协议中, ID 起着重要的作用,它决定着数据帧发送的优先级,也决定着其它节点是否会接收这个数据帧。
CAN 协议不对挂载在它之上的节点分配优先级和地址,对总线的占有权是由信息的重要性决定的,即对于重要的信息,我们会给它打包上一个优先级高的 ID,使它能够及时地发送出去。也正因为它这样的优先级分配原则,使得 CAN 的扩展性大大加强,在总线上增加或减少节点并不影响其它设备。报文的优先级,是通过对 ID 的仲裁来确定的。根据前面对物理层的分析我们知道如果总线上同时出现显性电平和隐性电平,总线的状态会被置为显性电平,CAN 正是利用这个特性进行仲裁。
若两个节点同时竞争 CAN 总线的占有权,当它们发送报文时,若首先出现隐性电平,则会失去对总线的占有权,进入接收状态。见图 ,在开始阶段,两个设备发送的电平一样,所以它们一直继续发送数据。到了图中箭头所指的时序处,节点单元 1 发送的为隐性电平,而此时节点单元 2 发送的为显性电平,由于总线的“线与”特性使它表达出显示电平,因此单元 2 竞争总线成功,这个报文得以被继续发送出去。
806d565813b64ff0a39d2777aaa0b049~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=1WIp66TG%2FiPk%2FkLEBiPkO0ZxcVM%3D
仲裁段 ID 的优先级也影响着接收设备对报文的反应。因为在 CAN 总线上数据是以广播的形式发送的,所有连接在 CAN 总线的节点都会收到所有其它节点发出的有效数据,因而我们的 CAN
控制器大多具有根据 ID 过滤报文的功能,它可以控制自己只接收某些 ID 的报文。回看数据帧格式,可看到仲裁段除了报文 ID 外,还有 RTR、IDE 和 SRR 位。
(1) RTR 位 (Remote Transmission Request Bit),译作远程传输请求位,它是用于区分数据帧和遥控帧的,当它为显性电平时表示数据帧,隐性电平时表示遥控帧。
(2) IDE 位 (Identifier ExtensionBit),译作标识符扩展位,它是用于区分标准格式与扩展格式,当它为显性电平时表示标准格式,隐性电平时表示扩展格式。
(3) SRR 位 (Substitute Remote Request Bit),只存在于扩展格式,它用于替代标准格式中的 RTR位。由于扩展帧中的 SRR 位为隐性位,RTR 在数据帧为显性位,所以在两个 ID 相同的标准格式报文与扩展格式报文中,标准格式的优先级较高。
• 控制段
在控制段中的 r1 和 r0 为保留位,默认设置为显性位。它最主要的是 DLC 段 (Data Length Code),译为数据长度码,它由 4 个数据位组成,用于表示本报文中的数据段含有多少个字节, DLC 段表示的数字为 0~8。
• 数据段
数据段为数据帧的核心内容,它是节点要发送的原始信息,由 0~8 个字节组成,MSB 先行。
• CRC 段
为了保证报文的正确传输,CAN 的报文包含了一段 15 位的 CRC 校验码,一旦接收节点算出的CRC 码跟接收到的 CRC 码不同,则它会向发送节点反馈出错信息,利用错误帧请求它重新发送。CRC 部分的计算一般由 CAN 控制器硬件完成,出错时的处理则由软件控制最大重发数。在 CRC 校验码之后,有一个 CRC 界定符,它为隐性位,主要作用是把 CRC 校验码与后面的 ACK段间隔起来。
• ACK 段
ACK 段包括一个 ACK 槽位,和 ACK 界定符位。类似 I2C 总线,在 ACK 槽位中,发送节点发送的是隐性位,而接收节点则在这一位中发送显性位以示应答。在 ACK 槽和帧结束之间由 ACK 界定符间隔开。
• 帧结束
EOF 段 (End Of Frame),译为帧结束,帧结束段由发送节点发送的 7 个隐性位表示结束。

1.3.5.3 其它报文的结构

a0f66b7dcde349d7a8382ef42fb647cd~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=zTKs3nTsc7fXoc9NZtLWxQYbZoE%3D
5898f6a8e6e446f99e30a241efa4aa47~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=opbLKfKLUTcG05CRjxZrceBWSJQ%3D
二、STM32 CAN控制器介绍
STM32 的芯片中具有 bxCAN 控制器 (Basic Extended CAN),它支持 CAN 协议 2.0A 和 2.0B 标准。该 CAN 控制器支持最高的通讯速率为 1Mb/s;可以自动地接收和发送 CAN 报文,支持使用标准ID 和扩展 ID 的报文;外设中具有 3 个发送邮箱,发送报文的优先级可以使用软件控制,还可以记录发送的时间;具有 2 个 3 级深度的接收 FIFO,可使用过滤功能只接收或不接收某些 ID 号的报文;可配置成自动重发;不支持使用 DMA 进行数据收发。框架示意图如下:
92f5ce93876b4e56b67652c57056ca8f~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=rp9QQs2qjZbVkGW6wffbMcz%2BSbE%3D
STM32 的有两组 CAN 控制器,其中 CAN1 是主设备,框图中的“存储访问控制器”是由 CAN1控制的,CAN2 无法直接访问存储区域,所以使用 CAN2 的时候必须使能 CAN1 外设的时钟。框图中主要包含 CAN 控制内核、发送邮箱、接收 FIFO 以及验收筛选器,下面对框图中的各个部分进行介绍。

2.1 CAN 控制内核

框图中标号处的 CAN 控制内核包含了各种控制寄存器及状态寄存器,我们主要讲解其中的主控制寄存器 CAN_MCR 及位时序寄存器 CAN_BTR。

2.1.1 主控制寄存器 CAN_MCR

主控制寄存器 CAN_MCR 负责管理 CAN 的工作模式,它使用以下寄存器位实现控制。
a4b299522e484b379fca2f3b6c2db07a~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=uxOlVAwbLByMBIkUreUXCeLEkqo%3D
(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 优先级还是报文存进邮箱的顺序来发送。

2.1.2 位时序寄存器 (CAN_BTR) 及波特率

a2dd7e49b49d402ca3f7ced6e2aa0661~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=ydFgcb8LrNI5t1z2NO%2B8LmsnenY%3D
CAN 外设中的位时序寄存器 CAN_BTR 用于配置测试模式、波特率以及各种位内的段参数。

2.1.2.1 模式

位31 SILM:静默模式(调试)(Silent mode (debug))
0:正常工作
1:静默模式
位30 LBKM:环回模式(调试)(Loop back mode (debug))
0:禁止环回模式
1:使能环回模式
为方便调试,STM32 的 CAN 提供了测试模式,配置位时序寄存器 CAN_BTR 的 SILM 及 LBKM寄存器位可以控制使用正常模式、静默模式、回环模式及静默回环模式,见图。
f3ef11b1fb3d43d38fe2a8e3c7bc49a3~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=%2B%2Fcgdy%2FYu8b3PO7FlIGMlKSs65A%3D
各个工作模式介绍如下:
• 正常模式
正常模式下就是一个正常的 CAN 节点,可以向总线发送数据和接收数据。
• 静默模式
静默模式下,它自己的输出端的逻辑 0 数据会直接传输到它自己的输入端,逻辑 1 可以被发送到总线,所以它不能向总线发送显性位 (逻辑 0),只能发送隐性位 (逻辑 1)。输入端可以从总线接收内容。由于它只可发送的隐性位不会强制影响总线的状态,所以把它称为静默模式。这种模式一般用于监测,它可以用于分析总线上的流量,但又不会因为发送显性位而影响总线。
• 回环模式
回环模式下,它自己的输出端的所有内容都直接传输到自己的输入端,输出端的内容同时也会被传输到总线上,即也可使用总线监测它的发送内容。输入端只接收自己发送端的内容,不接收来自总线上的内容。使用回环模式可以进行自检。
• 回环静默模式
回环静默模式是以上两种模式的结合,自己的输出端的所有内容都直接传输到自己的输入端,并且不会向总线发送显性位影响总线,不能通过总线监测它的发送内容。输入端只接收自己发送端的内容,不接收来自总线上的内容。这种方式可以在“热自检”时使用,即自我检查的时候,不会干扰总线。
以上说的各个模式,是不需要修改硬件接线的,例如,当输出直接连输入时,它是在 STM32 芯片内部连接的,传输路径不经过 STM32 的 CAN_Tx/Rx 引脚,更不经过外部连接的 CAN 收发器,只有输出数据到总线或从总线接收的情况下才会经过 CAN_Tx/Rx 引脚和收发器

2.1.2.2 位时序及波特率

STM32 外设定义的位时序与我们前面解释的 CAN 标准时序有一点区别,见图
659858e1c7bc4b76bcfa3a73c0625de4~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=J%2BhdPatVr6bAvE8Y1OVHXgTeC%2Fg%3D
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波特率=Fpclk1/((CAN_BS1+CAN_BS2+1)*CAN_Prescaler)
其中clk为42M!
83c8ba5f515a49cd9f4504c4c55b901f~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=vtF3vwknz2g7AnOHuG8jna%2FcyIs%3D
8967ca9e771e4da2aec0f689857a9b1d~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=DcKub89biZIC3AAit7VCTT1r9Jo%3D
推荐一个CAN波特率计算器
1e47d67ae9b549efaf7a1c572678cd14~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=fM5ND6UC1S5OjTOBLZ8NOA%2FZG44%3D
CAN波特率计算 f103AHP1_36M f407AHP1_42M 采样点软件有说明.rar

2.2 CAN 发送邮箱

回到图 中的 CAN 外设框图,在标号处的是 CAN 外设的发送邮箱,它一共有 3 个发送邮箱,即最多可以缓存 3 个待发送的报文。每个发送邮箱中包含有标识符寄存器 CAN_TIxR、数据长度控制寄存器 CAN_TDTxR 及 2 个数据寄存器 CAN_TDLxR、CAN_TDHxR,它们的功能见表
1cca796100a149088b5235e49be59f46~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=coSHlg3FfKY7yh%2FkLsMhnrYuBMk%3D
当我们要使用 CAN 外设发送报文时,把报文的各个段分解,按位置写入到这些寄存器中,并对标识符寄存器 CAN_TIxR 中的发送请求寄存器位 TMIDxR_TXRQ 置 1,即可把数据发送出去。其中标识符寄存器 CAN_TIxR 中的 STDID 寄存器位比较特别。我们知道 CAN 的标准标识符的总位数为 11 位,而扩展标识符的总位数为 29 位的。当报文使用扩展标识符的时候,标识符寄存器 CAN_TIxR 中的 STDID[10:0] 等效于 EXTID[18:28] 位,它与 EXTID[17:0] 共同组成完整的 29位扩展标识符。

2.3 CAN 接收 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,它们的功能见表。
52861579d96d4db39373aecb0b33334c~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=zh7O1Is9m5EdvHmgPBj1ImTGrwI%3D
通过中断或状态寄存器知道接收 FIFO 有数据后,我们再读取这些寄存器的值即可把接收到的报文加载到 STM32 的内存中

2.4 验收筛选器

图 中的 CAN 外设框图,在标号处的是 CAN 外设的验收筛选器,一共有 28 个筛选器组,每个筛选器组有 2 个寄存器,CAN1 和 CAN2 共用的筛选器的。在 CAN 协议中,消息的标识符与节点地址无关,但与消息内容有关。因此,发送节点将报文广播给所有接收器时,接收节点会根据报文标识符的值来确定软件是否需要该消息,为了简化软件的工作,STM32 的 CAN 外设接收报文前会先使用验收筛选器检查,只接收需要的报文到 FIFO中。
筛选器工作的时候,可以调整筛选 ID 的长度及过滤模式。根据筛选 ID 长度来分类有有以下两种:
(1) 检查 STDID[10:0]、EXTID[17:0]、IDE 和 RTR 位,一共 31 位。
(2) 检查 STDID[10:0]、RTR、IDE 和 EXTID[17:15],一共 16 位。
通过配置筛选尺度寄存器 CAN_FS1R 的 FSCx 位可以设置筛选器工作在哪个尺度。而根据过滤的方法分为以下两种模式:
(1) 标识符列表模式,它把要接收报文的 ID 列成一个表,要求报文 ID 与列表中的某一个标识符完全相同才可以接收,可以理解为白名单管理。
(2) 掩码模式,它把可接收报文 ID 的某几位作为列表,这几位被称为掩码,可以把它理解成关键字搜索,只要掩码 (关键字) 相同,就符合要求,报文就会被保存到接收 FIFO。通过配置筛选模式寄存器 CAN_FM1R 的 FBMx 位可以设置筛选器工作在哪个模式。不同的尺度和不同的过滤方法可使筛选器工作在图 的 4 种状态。
ce2311612dd7401ca474e925b64e3a0e~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=EXe1y1W%2FqCUI7k%2B0EYf9dYqUu4s%3D
每组筛选器包含 2 个 32 位的寄存器,分别为 CAN_FxR1 和 CAN_FxR2,它们用来存储要筛选的ID 或掩码,各个寄存器位代表的意义与图中两个寄存器下面“映射”的一栏一致,各个模式的说明见表。
eaf7e82af12d45448b9ce7389acde8f7~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=PZ%2B0AwRtZBoW4q31AT1309U7nrc%3D
例如下面的表格所示,在掩码模式时,第一个寄存器存储要筛选的 ID,第二个寄存器存储掩码,掩码为 1 的部分表示该位必须与 ID 中的内容一致,筛选的结果为表中第三行的 ID 值,它是一组包含多个的 ID 值,其中 x 表示该位可以为 1 可以为 0。
88eb5c6c232a46b7bd73777a3b130ba6~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=%2Bbm4ZmyjH%2B218VV2Ogo0K77PUvc%3D
而工作在标识符模式时,2 个寄存器存储的都是要筛选的 ID,它只包含 2 个要筛选的 ID 值 (32位模式时)。
如果使能了筛选器,且报文的 ID 与所有筛选器的配置都不匹配,CAN 外设会丢弃该报文,不存入接收 FIFO。

2.5 整体控制逻辑

回到图 结构框图,图中的标号处表示的是 CAN2 外设的结构,它与 CAN1 外设是一样的,他们共用筛选器且由于存储访问控制器由 CAN1 控制,所以要使用 CAN2 的时候必须要使能CAN1 的时钟。其中 STM32F103 系列芯片不具有 CAN2 控制器。

2.6 STM32 HAL库代码逻辑

2.6.1 初始化

注意:网络上基本上用的很久的HAL库,我们采用很新的1.25.2,最新的库还是差异挺大的!
从 STM32 的 CAN 外设我们了解到它的功能非常多,控制涉及的寄存器也非常丰富,而使用STM32 HAL 库提供的各种结构体及库函数可以简化这些控制过程。跟其它外设一样,STM32
HAL 库提供了 CAN 初始化结构体及初始化函数来控制 CAN 的工作方式,提供了收发报文使用的结构体及收发函数,还有配置控制筛选器模式及 ID 的结构体。这些内容都定义在库文件“STM32F4xx_hal_can.h”及“STM32F4xx_hal_can.c”中,编程时我们可以结合这两个文件内的注释使用或参考库帮助文档。首先我们来学习初始化结构体的内容,见代码清单 1。代码清单 CAN 初始化结构
typedef struct{ uint32_t Prescaler; /* 配置 CAN 外设的时钟分频,可设置为 1-1024*/ uint32_t Mode; /* 配置 CAN 的工作模式,回环或正常模式 */ uint32_t SyncJumpWidth; /* 配置 SJW 极限值 */ uint32_t TimeSeg1; /* 配置 BS1 段长度 */ uint32_t TimeSeg2; /* 配置 BS2 段长度 */ FunctionalState TimeTriggeredMode; /* 是否使能 TTCM 时间触发功能 */ FunctionalState AutoBusOff; /* 是否使能 ABOM 自动离线管理功能 */ FunctionalState AutoWakeUp; /* 是否使能 AWUM 自动唤醒功能 */ FunctionalState AutoRetransmission; /* 是否使能 NART 自动重传功能 */ FunctionalState ReceiveFifoLocked; /* 是否使能 RFLM 锁定 FIFO 功能 */ FunctionalState TransmitFifoPriority;/* 配置 TXFP 报文优先级的判定方法 */} CAN_InitTypeDef;体这些结构体成员说明如下,其中括号内的文字是对应参数在 STM32 HAL 库中定义的宏
(1) Prescaler
本成员设置 CAN 外设的时钟分频,它可控制时间片 Tq 的时间长度,这里设置的值最终会减 1 后再写入 BRP 寄存器位,即前面介绍的 Tq 计算公式:
Tq = (BRP[9:0]+1) x TPCLK
等效于:Tq = CAN_Prescaler x TPCLK
(2) Mode
本成员设置 CAN 的工作模式,可设置为正常模式 (CAN_MODE_NORMAL)、回环模式 (CAN_MODE_LOOPBACK)、静默模式 (CAN_MODE_SILENT) 以及回环静默模式(CAN_MODE_SILENT_LOOPBACK)。
(3) SyncJumpWidth
本成员可以配置 SJW 的极限长度,即 CAN 重新同步时单次可增加或缩短的最大长度,它可以被配置为 1-4Tq(CAN_SJW_1/2/3/4tq)。
(4) TimeSeg1
本成员用于设置 CAN 位时序中的 BS1 段的长度,它可以被配置为 1-16 个 Tq 长度(CAN_BS1_1/2/3…16tq)。
(5) TimeSeg2
本成员用于设置 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) TimeTriggeredMode
本成员用于设置是否使用时间触发功能 (ENABLE/DISABLE),时间触发功能在某些CAN 标准中会使用到。
(7) AutoBusOff
本成员用于设置是否使用自动离线管理 (ENABLE/DISABLE),使用自动离线管理可以在节点出错离线后适时自动恢复,不需要软件干预。
(8) AutoWakeUp
本成员用于设置是否使用自动唤醒功能 (ENABLE/DISABLE),使能自动唤醒功能后它会在监测到总线活动后自动唤醒。
(9) AutoWakeUp
本成员用于设置是否使用自动离线管理功能 (ENABLE/DISABLE),使用自动离线管理可以在出错时离线后适时自动恢复,不需要软件干预。
(10) AutoRetransmission
本成员用于设置是否使用自动重传功能 (ENABLE/DISABLE),使用自动重传功能时,会一直发送报文直到成功为止。
(11) ReceiveFifoLocked
本成员用于设置是否使用锁定接收 FIFO(ENABLE/DISABLE),锁定接收 FIFO 后,若FIFO 溢出时会丢弃新数据,否则在 FIFO 溢出时以新数据覆盖旧数据。
(12) TransmitFifoPriority
本成员用于设置发送报文的优先级判定方法 (ENABLE/DISABLE),使能时,以报文存入发送邮箱的先后顺序来发送,否则按照报文 ID 的优先级来发送。配置完这些结构体成员后,我们调用库函数 HAL_CAN_Init 即可把这些参数写入到 CAN 控制寄存器中,实现 CAN 的初始化

2.6.2 CAN 发送及接收结构体

在发送或接收报文时,需要往发送邮箱中写入报文信息或从接收 FIFO 中读取报文信息,利用STM32HAL 库的发送及接收结构体可以方便地完成这样的工作,它们的定义见代码清单 。代码清单 39‑2 CAN 发送及接收结构体
typedef struct{ uint32_t StdId; /* 存储报文的标准标识符 11 位,0-0x7FF. */ uint32_t ExtId; /* 存储报文的扩展标识符 29 位,0-0x1FFFFFFF. */ uint32_t IDE; /* 存储 IDE 扩展标志 */ uint32_t RTR; /* 存储 RTR 远程帧标志 */ uint32_t DLC; /* 存储报文数据段的长度,0-8 */ FunctionalState TransmitGlobalTime; } CAN_TxHeaderTypeDef;typedef struct{ uint32_t StdId; /* 存储报文的标准标识符 11 位,0-0x7FF. */ uint32_t ExtId; /* 存储报文的扩展标识符 29 位,0-0x1FFFFFFF. */ uint32_t IDE; /* 存储 IDE 扩展标志 */ uint32_t RTR; /* 存储 RTR 远程帧标志 */ uint32_t DLC; /* 存储报文数据段的长度,0-8 */ uint32_t Timestamp; uint32_t FilterMatchIndex; } CAN_RxHeaderTypeDef;这些结构体成员, 说明如下:
(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 时表示本报文是遥控帧,由于遥控帧没有数据段,所以当报文是遥控帧时,数据是无效的
(5) DLC
本成员存储的是数据帧数据段的长度,它的值的范围是 0-8,当报文是遥控帧时 DLC值为 0。

2.6.3 CAN 筛选器结构体

CAN 的筛选器有多种工作模式,利用筛选器结构体可方便配置,它的定义见代码清单 。代码清单CAN 筛选器结构体
typedef struct{ uint32_t FilterIdHigh; /*CAN_FxR1 寄存器的高 16 位 */ uint32_t FilterIdLow; /*CAN_FxR1 寄存器的低 16 位 */ uint32_t FilterMaskIdHigh; /*CAN_FxR2 寄存器的高 16 位 */ uint32_t FilterMaskIdLow; /*CAN_FxR2 寄存器的低 16 位 */ uint32_t FilterFIFOAssignment; /* 设置经过筛选后数据存储到哪个接收 FIFO */ uint32_t FilterBank; /* 筛选器编号,范围 0-27,数据手册上说0-27是CAN1/CAN2共享,但是实测发现并不是这样,CAN1是0-13,CAN2是14-27 */ uint32_t FilterMode; /* 筛选器模式 */ uint32_t FilterScale; /* 设置筛选器的尺度 */ uint32_t FilterActivation; /* 是否使能本筛选器 */ uint32_t SlaveStartFilterBank; } CAN_FilterTypeDef;这些结构体成员都是“41.2.14 验收筛选器”小节介绍的内容,可对比阅读,各个结构体成员的介绍如下:
(1) FilterIdHigh
FilterIdHigh 成员用于存储要筛选的 ID,若筛选器工作在 32 位模式,它存储的是所筛选 ID 的高 16 位;若筛选器工作在 16 位模式,它存储的就是一个完整的要筛选的 ID。
(2) FilterIdLow
类似地,FilterIdLow 成员也是用于存储要筛选的 ID,若筛选器工作在 32 位模式,它存储的是所筛选 ID 的低 16 位;若筛选器工作在 16 位模式,它存储的就是一个完整的要筛选的 ID。
(3) FilterMaskIdHigh
FilterMaskIdHigh 存储的内容分两种情况,当筛选器工作在标识符列表模式时,它的功能与 FilterIdHigh 相同,都是存储要筛选的 ID;而当筛选器工作在掩码模式时,它存储的是 FilterIdHigh 成员对应的掩码,与 FilterIdLow 组成一组筛选器。
(4) FilterMaskIdLow
类似地, FilterMaskIdLow 存储的内容也分两种情况,当筛选器工作在标识符列表模式时,它的功能与 FilterIdLow 相同,都是存储要筛选的 ID;而当筛选器工作在掩码模式时,它存储的是 FilterIdLow 成员对应的掩码,与 FilterIdLow 组成一组筛选器。上面四个结构体的存储的内容很容易让人糊涂,请结合前面的图 39_0_15 和下面的表 39‑7 理解,如果还搞不清楚,再结合库函数 FilterInit 的源码来分析。
表不同模式下各结构体成员的内容
2ea09ea190514885b5aad7a19e06a54f~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=R38GCUsKZFLepEUOcR%2F%2BrFQT4tU%3D
对这些结构体成员赋值的时候,还要注意寄存器位的映射,即注意哪部分代表 STID,哪部分代表 EXID 以及 IDE、RTR 位。
(5) FilterFIFOAssignment
本成员用于设置当报文通过筛选器的匹配后,该报文会被存储到哪一个接收 FIFO,它的可选值为 FIFO0 或 FIFO1(宏 CAN_FILTER_FIFO0/1)。
(6) FilterBank
本成员用于设置筛选器的编号,即本过滤器结构体配置的是哪一组筛选器,CAN 一共有 28 个筛选器,所以它的可输入参数范围为 0-27。
(7) FilterMode
本 成 员 用 于 设 置 筛 选 器 的 工 作 模 式, 可 以 设 置 为 列 表 模 式 (宏CAN_FILTERMODE_IDLIST) 及掩码模式 (宏 CAN_FILTERMODE_IDMASK)。
(8) FilterScale
本成员用于设置筛选器的尺度,可以设置为 32 位长 (宏 CAN_FILTERSCALE_32BIT)及 16 位长 (宏 CAN_FILTERSCALE_16BIT)。
(9) FilterActivation
本成员用于设置是否激活这个筛选器 (宏 ENABLE/DISABLE)。
三、CAN Cubemx配置
我们通过问题来熟悉下cubemx配置,你熟悉了这些问题基本就知道怎么配置了!
问题:Parameter Settings分别都是设置什么的?答案:如图
85ce50cb61cd49e09f233640f697dd27~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=tyxkJEUxkPZAaxj97YOe4ce2etw%3D

问题:怎么配置波特率呢?

答案:用我上面贴的工具(CAN波特率计算 f103AHP1_36M f407AHP1_42M 采样点软件有说明.rar)直接配置,举两个个例子
例子1:我们要配置成500KHz,那么我们这样配置
401866ad24904a6fb158a661b6a1daac~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=9tj4Tk3K%2FdelNw5mU3lWZfPEdJI%3D
e7bd7be7aae046f6b7206216713fff33~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=ED6gqY3W1P7tD7RK%2BBZOznYoEMs%3D
我们用采集点为80%,所以BS1为4tq,BS2为2tq,分频系数为12,代进公式Fpclk1/((CAN_BS1+CAN_BS2+1)*CAN_Prescaler)=42M/(4+2+1)/12=500kHz
例子2:我们要配置成1M Hz,那么我们这样配置
267fee86b3b2413d8c08b57f2bfaca29~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=M7o7wXMnSgm0nr2uNieJUXFFz1M%3D
我们用采集点为75%,所以BS1为3tq,BS2为2tq,分频系数为7,代进公式Fpclk1/((CAN_BS1+CAN_BS2+1)*CAN_Prescaler)=42M/(3+2+1)/7=1MHz
cd5a9b0ad494405aa884b54dab50a6db~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=ro6Kh3hIcoglxCglg95j%2FRcii9w%3D

问题:Basic Parameter分别是啥意思呢?

11d839f637d64c5abe9288d831f39c2c~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=Fy0PATF2b%2BeDxCS3ueyOXa0F0Rc%3D
Timer Triggered Communication Mode:否使用时间触发功能 (ENABLE/DISABLE),时间触发功能在某些CAN 标准中会使用到。
Automatic Bus-Off Management:用于设置是否使用自动离线管理功能 (ENABLE/DISABLE),使用自动离线管理可以在出错时离线后适时自动恢复,不需要软件干预。
Automatic Wake-Up Mode:用于设置是否使用自动唤醒功能 (ENABLE/DISABLE),使能自动唤醒功能后它会在监测到总线活动后自动唤醒。
Automatic Retransmission:用于设置是否使用自动重传功能 (ENABLE/DISABLE),使用自动重传功能时,会一直发送报文直到成功为止。
Receive Fifo Locked Mode:用于设置是否使用锁定接收 FIFO(ENABLE/DISABLE),锁定接收 FIFO 后,若FIFO 溢出时会丢弃新数据,否则在 FIFO 溢出时以新数据覆盖旧数据。
Transmit Fifo Priority:用于设置发送报文的优先级判定方法 (ENABLE/DISABLE),使能时,以报文存入发送邮箱的先后顺序来发送,否则按照报文 ID 的优先级来发送。配置完这些结构体成员后,我们调用库函数 HAL_CAN_Init 即可把这些参数写入到 CAN 控制寄存器中,实现 CAN 的初始化

问题:为啥CAN分为RX0,RX1中断呢?

f52ad41406de4d1490537aa69f5168fd~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=CCw0coUNqeTfHr5Y9ntWVnINqJg%3D
答案:STM32有2个3级深度的接收缓冲区:FIFO0和FIFO1,每个FIFO都可以存放3个完整的报文,它们完全由硬件来管理。如果是来自FIFO0的接收中断,则用CAN1_RX0_IRQn中断来处理。如果是来自FIFO1的接收中断,则用CAN1_RX1_IRQn中断来处理,如图:
859a894d84f84fff9375feabd5361ffc~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=8eAQ7VwRxAxoKos%2FunfH6yTLT0g%3D

问题:CAN SCE中断时什么?

35989aacc17340029782fa7177d5d11c~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=3UwdPMqMh9YSh6BcF2PMMeY80SQ%3D
答案:status chanege error,错误和状态变化中断!
四、CAN分析工具的使用
下面我们会用到CAN分析工具,还是比较好用的,此部分使用作为自己使用
https://www.zhcxgd.com/h-col-112.html
五、实验

1.Normal模式测试500K 波特率(定时发送,轮询接收)

1.1 CubeMx配置

1a69f129b87f488db181869d72ce92a0~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=gS4iDkfTNFEBDuXui2rjdDEtgRY%3D
757b2391ac674df18bcc677003bf1b12~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=B3WJx1E5uZ5gFvlKhrxyHmBijT8%3D

1.2 设置Filter过滤,我们只使能FIFO0,并且不过滤任何消息

uint8_t bsp_can1_filter_config(void){ CAN_FilterTypeDef filter = {0}; filter.FilterActivation = ENABLE; filter.FilterMode = CAN_FILTERMODE_IDMASK; filter.FilterScale = CAN_FILTERSCALE_32BIT; filter.FilterBank = 0; filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; filter.FilterIdLow = 0; filter.FilterIdHigh = 0; filter.FilterMaskIdLow = 0; filter.FilterMaskIdHigh = 0; HAL_CAN_ConfigFilter(&hcan1, &filter); return BSP_CAN_OK;}

1.3 开启CAN(注意,默认Cubemx生成的代码并没有can start)

HAL_CAN_Start(&hcan1);

1.4 编写发送函数

我们开出了几个参数,id_type是扩展帧还是标准帧,basic_id标准帧ID(在标准帧中有效),ex_id扩展帧ID(在扩展帧中有效),data要发送的数据,data_len要发送的数据长度
uint8_t bsp_can1_send_msg(uint32_t id_type,uint32_t basic_id,uint32_t ex_id,uint8_t *data,uint32_t data_len){ uint8_t index = 0; uint32_t *msg_box; uint8_t send_buf[8] = {0}; CAN_TxHeaderTypeDef send_msg_hdr; send_msg_hdr.StdId = basic_id; send_msg_hdr.ExtId = ex_id; send_msg_hdr.IDE = id_type; send_msg_hdr.RTR = CAN_RTR_DATA; send_msg_hdr.DLC = data_len; send_msg_hdr.TransmitGlobalTime = DISABLE; for(index = 0; index < data_len; index++) send_buf[index] = data[index]; HAL_CAN_AddTxMessage(&hcan1,&send_msg_hdr,send_buf,msg_box); return BSP_CAN_OK;}我们在main函数中1s发送一帧,标准帧跟扩展帧交叉调用,代码如下:
send_data[0]++;send_data[1]++;send_data[2]++;send_data[3]++;send_data[4]++;send_data[5]++;send_data[6]++;send_data[7]++;if(id_type_std == 1){ bsp_can1_send_msg(CAN_ID_STD,1,2,send_data,8); id_type_std = 0;}else{ bsp_can1_send_msg(CAN_ID_EXT,1,2,send_data,8); id_type_std = 1;}HAL_Delay(1000);我们通过CAN协议分析仪来抓下结果
ff770e0762a0422bba9fce747f3984d2~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=2dQ3nWsfNhZ%2FzOSqAvr2kXBRvuE%3D

1.5 编写轮询接收函数

uint8_t bsp_can1_polling_recv_msg(uint32_t *basic_id,uint32_t *ex_id,uint8_t *data,uint32_t *data_len){ uint8_t index = 0; uint8_t recv_data[8]; CAN_RxHeaderTypeDef header; while (HAL_CAN_GetRxFifoFillLevel(&hcan1, CAN_RX_FIFO0) != 0) { if (__HAL_CAN_GET_FLAG(&hcan1, CAN_FLAG_FOV0) != RESET) printf(“[CAN] FIFO0 overrun!\n”); HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &header, recv_data); if(header.IDE == CAN_ID_STD) { printf(“StdId ID:%d\n”,header.StdId); } else { printf(“ExtId ID:%d\n”,header.ExtId); } printf(“CAN IDE:0x%x\n”,header.IDE); printf(“CAN RTR:0x%x\n”,header.RTR); printf(“CAN DLC:0x%x\n”,header.DLC); printf(“RECV DATA:”); for(index = 0; index < header.DLC; index++) { printf(“0x%x “,recv_data[index]); } printf(“\n”); }}实验一总结:
1.没用调用HAL_CAN_Start(&hcan1);使能CAN
2.没有编写Filter函数,我开始自认为不设置就默认不过滤,现在看来是我想多了,其实想想也合理,你如果不过滤分配FIFO,STM32怎么决定把收到的放到哪个FIFO中
待提升:
1.目前只用到FIFO0,待把FIFO1使用起来2.Normal模式测试500K 波特率(定时发送,中断接收)

2.1 CubeMx配置

1e21f71176374e4ba433b951b9655a38~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=Noi6zcpr1zYqL23Qt4hstXrzTLI%3D
f1a6881cc1494e1bb760a455ae5fa653~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1717729200&x-signature=211SJkh4XNIGElYPkt9W6SoFNM8%3D
步骤2,3,4跟polling完全一致,我们来直接说下中断怎么用(主要是使能notifity就行了)
static void MX_CAN1_Init(void){ /* USER CODE BEGIN CAN1_Init 0 */ /* USER CODE END CAN1_Init 0 */ /* USER CODE BEGIN CAN1_Init 1 */ /* USER CODE END CAN1_Init 1 */ hcan1.Instance = CAN1; hcan1.Init.Prescaler = 12; hcan1.Init.Mode = CAN_MODE_NORMAL; hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ; hcan1.Init.TimeSeg1 = CAN_BS1_4TQ; hcan1.Init.TimeSeg2 = CAN_BS2_2TQ; hcan1.Init.TimeTriggeredMode = DISABLE; hcan1.Init.AutoBusOff = ENABLE; hcan1.Init.AutoWakeUp = ENABLE; hcan1.Init.AutoRetransmission = DISABLE; hcan1.Init.ReceiveFifoLocked = DISABLE; hcan1.Init.TransmitFifoPriority = DISABLE; if (HAL_CAN_Init(&hcan1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN CAN1_Init 2 */ bsp_can1_filter_config(); HAL_CAN_Start(&hcan1); HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING); /* USER CODE END CAN1_Init 2 */}下面我们来编写下中断函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan){ uint8_t index = 0; uint8_t recv_data[8]; CAN_RxHeaderTypeDef header; HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &header, recv_data); if(header.IDE == CAN_ID_STD) { printf(“StdId ID:%d\n”,header.StdId); } else { printf(“ExtId ID:%d\n”,header.ExtId); } printf(“CAN IDE:0x%x\n”,header.IDE); printf(“CAN RTR:0x%x\n”,header.RTR); printf(“CAN DLC:0x%x\n”,header.DLC); printf(“RECV DATA:”); for(index = 0; index < header.DLC; index++) { printf(“0x%x “,recv_data[index]); } printf(“\n”);}
另外,整理了一些电子工程类的资料,分享给大家,目前有模拟电路、单片机、C语言、PCB设计、电源相关、FPGA、EMC、物联网、Linux相关学习资料,还有针对大学生的资料包,后续还会有更多资料分享给大家,助力大家学习,成就梦想~
博主福利:点击链接免费获取电子工程类学习资料「链接」

原创文章,作者:小条,如若转载,请注明出处:https://www.sudun.com/ask/80873.html

Like (0)
小条的头像小条
Previous 2024年5月31日 上午10:59
Next 2024年5月31日 上午11:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注