首页 » 智能 » 周全解读CAN 总线协议的相关常识_暗记_报文

周全解读CAN 总线协议的相关常识_暗记_报文

admin 2024-11-29 23:26:29 0

扫一扫用手机浏览

文章目录 [+]

1.1 CAN 协议简介

CAN 是掌握器局域网络 (Controller Area Network) 的简称,它是由研发和生产汽车电子产品著称的德国 BOSCH 公司开拓的,并终极成为国际标准(ISO11519以及ISO11898),是国际上运用最广泛的现场总线之一。
差异点如下:

周全解读CAN 总线协议的相关常识_暗记_报文 周全解读CAN 总线协议的相关常识_暗记_报文 智能

CAN 总线协议已经成为汽车打算机掌握系统嵌入式工业掌握局域网的标准总线,并且拥有以CAN 为底层协议专为大型货车和重工机器车辆设计的 J1939 协议。
近年来,它具有的高可靠性和良好的缺点检测能力受到重视,被广泛运用于汽车打算机掌握系统和环境温度恶劣、电磁辐射强及振动大的工业环境。

周全解读CAN 总线协议的相关常识_暗记_报文 周全解读CAN 总线协议的相关常识_暗记_报文 智能
(图片来自网络侵删)

我们来贴图一个车载网络构想图

1.2 CAN 物理层

I2C、SPI 等具有时钟旗子暗记的同步通讯办法不同,CAN 通讯并不因此时钟旗子暗记来进行同步的,它是一种异步通讯,只具有 CAN_High 和 CAN_Low 两条旗子暗记线,共同构成一组差分旗子暗记线,以差分旗子暗记的形式进行通讯。
我们来看一个示意图

1.2.1 闭环总线网络

CAN 物理层的形式紧张有两种,图中的 CAN 通讯网络是一种遵照 ISO11898 标准的高速、短间隔“闭环网络”,它的总线最大长度为 40m,通信速率最高为 1Mbps,总线的两端各哀求有一个“120 欧”的电阻。

1.2.2 开环总线网络

图中的是遵照 ISO11519-2 标准的低速、远间隔“开环网络”,它的最大传输间隔为 1km,最高通讯速率为 125kbps,两根总线是独立的、不形成闭环,哀求每根总线上各串联有一个“2.2千欧”的电阻。

1.2.3 通讯节点

从 CAN 通讯网络图可理解到,CAN 总线上可以挂载多个通讯节点,节点之间的旗子暗记经由总线传输,实现节点间通讯。
由于 CAN 通讯协议不对节点进行地址编码,而是对数据内容进行编码的,以是网络中的节点个数理论上不受限定,只要总线的负载足够即可,可以通过中继器增强负载。

CAN 通讯节点由一个 CAN 掌握器及 CAN 收发器组成,掌握器与收发器之间通过 CAN_Tx 及CAN_Rx 旗子暗记线相连,收发器与 CAN 总线之间利用 CAN_High 及 CAN_Low 旗子暗记线相连。
个中CAN_Tx 及 CAN_Rx 利用普通的类似 TTL 逻辑旗子暗记,而 CAN_High 及 CAN_Low 是一对差分旗子暗记线,利用比较特殊的差分旗子暗记,下一小节再详细解释。

当 CAN 节点须要发送数据时,掌握器把要发送的二进制编码通过 CAN_Tx 线发送到收发器,然后由收发器把这个普通的逻辑电平旗子暗记转化成差分旗子暗记,通过差分线 CAN_High 和 CAN_Low 线输出到 CAN 总线网络。
而通过收发器吸收总线上的数据到掌握器时,则是相反的过程,收发器把总线上收到的 CAN_High 及 CAN_Low 旗子暗记转化成普通的逻辑电平旗子暗记,通过 CAN_Rx 输出到掌握器中。

例如,STM32 的 CAN 片上外设便是通讯节点中的掌握器,为了构成完全的节点,还要给它外接一个收发器,在我们实验板中利用型号为 TJA1050 的芯片作为 CAN 收发器。
CAN 掌握器与 CAN收发器的关系犹如 TTL 串口与 MAX3232 电平转换芯片的关系, MAX3232 芯片把 TTL 电平的串口旗子暗记转换成 RS-232 电平的串口旗子暗记,CAN 收发器的浸染则是把 CAN 掌握器的 TTL 电平旗子暗记转换成差分旗子暗记 (或者相反) 。

目前有以下CAN电平转换芯片(不全)

我们来用TJA1050来看下事理图:

1.2.4 差分旗子暗记

差分旗子暗记又称差模旗子暗记,与传统利用单根旗子暗记线电压表示逻辑的办法有差异,利用差分旗子暗记传输时,须要两根旗子暗记线,这两个旗子暗记线的振幅相等,相位相反,通过两根旗子暗记线的电压差值来表示

逻辑 0 和逻辑 1。
见图,它利用了 V+ 与 V-旗子暗记的差值表达出了图下方的旗子暗记。

相对付单旗子暗记线传输的办法,利用差分旗子暗记传输具有如下优点:

• 抗滋扰能力强,当外界存在噪声滋扰时,险些会同时耦合到两条旗子暗记线上,而吸收端只关心两个旗子暗记的差值,以是外界的共模噪声可以被完备抵消。

举一个例子,正常的单线假设逻辑1是3.3V,逻辑0假设是0V,但是如果有噪声,把3.3V弄成了0V(极度),把0V弄成了-3.3V,此时就逻辑缺点,但是有Can高/Can低一样平常都浸染于两根线,以是两个虽然都有噪声影响,但是差值还是不变的

• 能有效抑制它对外部的电磁滋扰,同样的道理,由于两根旗子暗记的极性相反,他们对外辐射的电磁场可以相互抵消,耦合的越紧密,泄放到外界的电磁能量越少。

举一个例子,假设一根是10V,一根是-10V,单跟都会对外部造成电磁滋扰,但是CAN可以把线拧在一起,跟编麻花一样,可以相互抵消电子滋扰

• 时序定位精确,由于差分旗子暗记的开关变革是位于两个旗子暗记的交点,而不像普通单端旗子暗记依赖高低两个阈值电压判断,因而受工艺,温度的影响小,能降落时序上的偏差,同时也更适宜于低幅度旗子暗记的电路。

由于差分旗子暗记线具有这些优点,以是在 USB 协议、485 协议、以太网协议及 CAN 协议的物理层中,都利用了差分旗子暗记传输。

1.2.5 CAN 协议中的差分旗子暗记

CAN 协议中对它利用的 CAN_High 及 CAN_Low 表示的差分旗子暗记做了规定,见表及图。
以高速 CAN 协议为例,当表示逻辑 1 时 (隐性电平) ,CAN_High 和 CAN_Low 线上的电压均为 2.5v,即它们的电压差 VH-VL=0V;而表示逻辑 0 时 (显性电平) ,CAN_High 的电平为 3.5V,CAN_Low 线的电平为 1.5V,即它们的电压差为 VH-VL=2V。
例如,当 CAN收发器从 CAN_Tx 线吸收到来自 CAN 掌握器的低电平旗子暗记时 (逻辑 0),它会使 CAN_High 输出3.5V,同时 CAN_Low 输出 1.5V,从而输出显性电平表示逻辑 0 。

在 CAN 总线中,必须使它处于隐性电平 (逻辑 1) 或显性电平 (逻辑 0) 中的个中一个状态。
假如有两个 CAN 通讯节点,在同一韶光,一个输出隐性电平,另一个输出显性电平,类似 I2C 总线的“线与”特性将使它处于显性电平状态,显性电平的名字便是这样来的,即可以认为显性具有优先的意味。

由于 CAN 总线协议的物理层只有 1 对差分线,在一个时候只能表示一个旗子暗记,以是对通讯节点来说,CAN 通讯是半双工的,收发数据须要分时进行。
在 CAN 的通讯网络中,由于共用总线,在全体网络中同一时候只能有一个通讯节点发送旗子暗记,别的的节点在该时候都只能吸收。

1.3 CAN 协议层

1.3.1 CAN 的波特率及位同步

由于 CAN 属于异步通讯,没有时钟旗子暗记线,连接在同一个总线网络中的各个节点会像串口异步通讯那样,节点间利用约定好的波特率进行通讯,特殊地, CAN 还会利用“位同步”的办法来抗滋扰、接管偏差,实现对总线电平旗子暗记进行精确的采样,确保通讯正常。

1.3.2 位时序分解

为了实现位同步,CAN 协议把每一个数据位的时序分解成如图 所示的 SS 段、PTS 段、PBS1 段、PBS2 段,这四段的长度加起来即为一个 CAN 数据位的长度。
分解后最小的韶光单位是 Tq,而一个完全的位由 8~25 个 Tq 组成。
为方便表示,图 中的高低电平直接代表旗子暗记逻辑 0 或逻辑 1(不是差分旗子暗记)。

该图中表示的 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.3 通讯的波特率

总线上的各个通讯节点只要约定好 1 个 Tq 的韶光长度以及每一个数据位霸占多少个 Tq,就可以确定 CAN 通讯的波特率。

例如,假设上图中的 1Tq=1us,而每个数据位由 19 个 Tq 组成,则传输一位数据须要韶光 T1bit=19us,从而每秒可以传输的数据位个数为:1x10次方/19 = 52631.6 (bps)

这个每秒可传输的数据位的个数即为通讯中的波特率。

1.3.4 同步过程剖析

波特率只是约定了每个数据位的长度,数据同步还涉及到相位的细节,这个时候就须要用到数据位内的 SS、PTS、PBS1 及 PBS2 段了。
根据对段的运用办法差异, CAN 的数据同步分为硬同步和重新同步。
个中硬同步只是当存在“帧起始旗子暗记”时起浸染,无法确保后续持续串的位时序都是同步的,而重新同步办法可办理该问题,这两种办法详细先容如下:

(1) 硬同步

若某个 CAN 节点通过总线发送数据时,它会发送一个表示通讯起始的旗子暗记 (即下一小节先容的帧起始旗子暗记),该旗子暗记是一个由高变低的低落沿。
而挂载到 CAN 总线上的通讯节点在不发送数据时,会时候检测总线上的旗子暗记。
见图 ,可以看到当总线涌现帧起始旗子暗记时,某节点检测到总线的帧起始旗子暗记不在节点内部时序的 SS 段范围,以是判断它自己的内部时序与总线不同步,因而这个状态的采样点采集得的数据是禁绝确的。
以是节点以硬同步的办法调度,把自己的位时序中的 SS 段平移至总线涌现低落沿的部分,得到同步,同步后采样点就可以采集得精确数据了。

(2) 重新同步

前面的硬同步只是当存在帧起始旗子暗记时才起浸染,如果在一帧很长的数据内,节点旗子暗记与总线旗子暗记相位有偏移时,这种同步办法就无能为力了。
因而须要引入重新同步办法,它利用普通数据位的高至低电平的跳变沿来同步 (帧起始旗子暗记是分外的跳变沿)。
重新同步与硬同步办法相似的地方是它们都利用 SS 段来进行检测,同步的目的都是使节点内的 SS 段把跳变沿包含起来。
重新同步的办法分为超前和滞后两种情形,以总线跳变沿与 SS 段的相对位置进行区分。
第一种相位超前的情形如图 ,节点从总线的边沿跳变中,检测到它内部的时序比总线的时序相对超前 2Tq,这时掌握器不才一个位时序中的 PBS1 段增加 2Tq 的韶光长度,使得节点与总线时序重新同步。

第二种相位滞后的情形如图 ,节点从总线的边沿跳变中,检测到它的时序比总线的时序相对滞后 2Tq,这时掌握器在前一个位时序中的 PBS2 段减少 2Tq 的韶光长度,得到同步。

在重新同步的时候,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 种类型的帧,它们的类型及用场解释如表

1.3.5.2 数据帧的构造

数据帧是在 CAN 通讯中最紧张、最繁芜的报文,我们来理解它的构造,见图

数据帧以一个显性位 (逻辑 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 竞争总线成功,这个报文得以被连续发送出去。

仲裁段 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 其它报文的构造

二. STM32 CAN 掌握器先容

STM32 的芯片中具有 bxCAN 掌握器 (Basic Extended CAN),它支持 CAN 协议 2.0A 和 2.0B 标准。
该 CAN 掌握器支持最高的通讯速率为 1Mb/s;可以自动地吸收和发送 CAN 报文,支持利用标准ID 和扩展 ID 的报文;外设中具有 3 个发送邮箱,发送报文的优先级可以利用软件掌握,还可以记录发送的韶光;具有 2 个 3 级深度的吸收 FIFO,可利用过滤功能只吸收或不吸收某些 ID 号的报文;可配置成自动重发;不支持利用 DMA 进行数据收发。
框架示意图如下:

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 的事情模式,它利用以下寄存器位实现掌握。

(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) 及波特率

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寄存器位可以掌握利用正常模式、静默模式、回环模式及静默回环模式,见图。

各个事情模式先容如下:

• 正常模式

正常模式下便是一个正常的 CAN 节点,可以向总线发送数据和吸收数据。

• 静默模式

静默模式下,它自己的输出真个逻辑 0 数据会直接传输到它自己的输入端,逻辑 1 可以被发送到总线,以是它不能向总线发送显性位 (逻辑 0),只能发送隐性位 (逻辑 1)。
输入端可以从总线吸收内容。
由于它只可发送的隐性位不会逼迫影响总线的状态,以是把它称为静默模式。
这种模式一样平常用于监测,它可以用于剖析总线上的流量,但又不会由于发送显性位而影响总线。

• 回环模式

回环模式下,它自己的输出真个所有内容都直接传输到自己的输入端,输出真个内容同时也会被传输到总线上,即也可利用总线监测它的发送内容。
输入端只吸收自己发送真个内容,不吸收来自总线上的内容。
利用回环模式可以进行自检。

• 回环静默模式

回环静默模式因此上两种模式的结合,自己的输出真个所有内容都直接传输到自己的输入端,并且不会向总线发送显性位影响总线,不能通过总线监测它的发送内容。
输入端只吸收自己发送真个内容,不吸收来自总线上的内容。
这种办法可以在“热自检”时利用,即自我检讨的时候,不会滋扰总线。

以上说的各个模式,是不须要修正硬件接线的,例如,当输出直接连输入时,它是在 STM32 芯片内部连接的,传输路径不经由 STM32 的 CAN_Tx/Rx 引脚,更不经由外部连接的 CAN 收发器,只有输出数据到总线或从总线吸收的情形下才会经由 CAN_Tx/Rx 引脚和收发器

2.1.2.2 位时序及波特率

STM32 外设定义的位时序与我们前面阐明的 CAN 标准时序有一点差异,见图

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!

推举一个CAN波特率打算器

CAN波特率打算 f103AHP1_36M f407AHP1_42M 采样点软件有解释.rar

2.2 CAN 发送邮箱

回到图 中的 CAN 外设框图,在标号处的是 CAN 外设的发送邮箱,它一共有 3 个发送邮箱,即最多可以缓存 3 个待发送的报文。
每个发送邮箱中包含有标识符寄存器 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位扩展标识符。

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,它们的功能见表。

通过中断或状态寄存器知道吸收 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 种状态。

每组筛选器包含 2 个 32 位的寄存器,分别为 CAN_FxR1 和 CAN_FxR2,它们用来存储要筛选的ID 或掩码,各个寄存器位代表的意义与图中两个寄存器下面“映射”的一栏同等,各个模式的解释见表。

例如下面的表格所示,在掩码模式时,第一个寄存器存储要筛选的 ID,第二个寄存器存储掩码,掩码为 1 的部分表示该位必须与 ID 中的内容同等,筛选的结果为表中第三行的 ID 值,它是一组包含多个的 ID 值,个中 x 表示该位可以为 1 可以为 0。

而事情在标识符模式时,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 的源码来剖析。

表不同模式下各构造体成员的内容

对这些构造体成员赋值的时候,还要把稳寄存器位的映射,即把稳哪部分代表 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分别都是设置什么的? 答案:如图

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

答案:用我上面贴的工具(CAN波特率打算 f103AHP1_36M f407AHP1_42M 采样点软件有解释.rar)直接配置,举两个个例子

例子1:我们要配置成500KHz,那么我们这样配置

我们用采集点为80%,以是BS1为4tq,BS2为2tq,分频系数为12,代进公式Fpclk1/((CAN_BS1+CAN_BS2+1)CAN_Prescaler)=42M/(4+2+1)/12=500kHz

例子2:我们要配置成1M Hz,那么我们这样配置

我们用采集点为75%,以是BS1为3tq,BS2为2tq,分频系数为7,代进公式Fpclk1/((CAN_BS1+CAN_BS2+1)CAN_Prescaler)=42M/(3+2+1)/7=1MHz

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

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中断呢?

答案:STM32有2个3级深度的吸收缓冲区:FIFO0和FIFO1,每个FIFO都可以存放3个完全的报文,它们完备由硬件来管理。
如果是来自FIFO0的吸收中断,则用CAN1_RX0_IRQn中断来处理。
如果是来自FIFO1的吸收中断,则用CAN1_RX1_IRQn中断来处理,如图:

问题:CAN SCE中断时什么?

答案:status chanege error,缺点和状态变革中断!

四.CAN剖析工具的利用

下面我们会用到CAN剖析工具,还是比较好用的,此部分利用作为自己利用

https://www.zhcxgd.com/h-col-112.html

五. 实验

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

1.1 CubeMx配置

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协议剖析仪来抓下结果

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!"); HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &header, recv_data); if(header.IDE == CAN_ID_STD) { printf("StdId ID:%d",header.StdId); } else { printf("ExtId ID:%d",header.ExtId); } printf("CAN IDE:0x%x",header.IDE); printf("CAN RTR:0x%x",header.RTR); printf("CAN DLC:0x%x",header.DLC); printf("RECV DATA:"); for(index = 0; index < header.DLC; index++) { printf("0x%x ",recv_data[index]); } printf(""); }}

实验一总结:

1.没用调用HAL_CAN_Start(&hcan1);使能CAN

2.没有编写Filter函数,我开始自认为不设置就默认不过滤,现在看来是我想多了,实在想想也合理,你如果不过滤分配FIFO,STM32怎么决定把收到的放到哪个FIFO中

待提升:

1.目前只用到FIFO0,待把FIFO1利用起来2.Normal模式测试500K 波特率(定时发送,中断吸收)

2.1 CubeMx配置

步骤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",header.StdId); } else { printf("ExtId ID:%d",header.ExtId); } printf("CAN IDE:0x%x",header.IDE); printf("CAN RTR:0x%x",header.RTR); printf("CAN DLC:0x%x",header.DLC); printf("RECV DATA:"); for(index = 0; index < header.DLC; index++) { printf("0x%x ",recv_data[index]); } printf("");}参考内容:

1.[野火EmbedFire]《STM32 HAL库开拓实战指南——基于野火寻衅者开拓板》.pdf

2.STM32F4参考手册.pdf

3.CAN入门书.pdf

标签:

相关文章