I.MX6ULL_Linux_驱动篇(52)linux CAN驱动

CAN 是目前应用非常广泛的现场总线之一,主要应用于汽车电子和工业领域,尤其是汽车领域,汽车上大量的传感器与模块都是通过 CAN 总线连接起来的。 CAN 总线目前是自动化领域发展的热点技术之一,由于其高可靠性, CAN 总线目前广泛的应用于工业自动化、船舶、汽车、医疗和工业设备等方面。 I.MX6ULL 自带了 CAN 外设,因此可以开发 CAN 相关的设备,本章我们就来学习一下如何驱动 I.MX6U-ALPHA 开发板上的 CAN 接口。

CAN简介

CAN 的全称为 Controller Area Network,也就是控制局域网络,简称为 CAN。 CAN 最早是由德国 BOSCH(博世)开发的,目前已经是国际标准(ISO 11898),是当前应用最广泛的现场总线之一。 BOSCH 主要是做汽车电子的,因此 CAN 一开始主要是为汽车电子准备的,事实也是如此, CAN 协议目前已经是汽车网络的标准协议。当然了, CAN 不仅仅应用于汽车电子,经过几十年的发展, CAN 协议的高性能和高可靠性已经得到了业界的认可,目前除了汽车电子以外也广泛应用于工业自动化、医疗、工业和船舶等领域。以汽车电子为例,汽车上有空调、车门、发动机、大量传感器等,这些部件都是通过 CAN总线连在一起形成一个网络,车载网络结构如图所示:

图中各个单元通过 CAN 总线连接在一起,每个单元都是独立的 CAN 节点。同一个 CAN 网络中所有单元的通信速度必须一致,不同的网络之间通信速度可以不同。比如图中 125Kbps 的 CAN 网络下所有的节点速度都是 125Kbps 的,整个网络由一个网关与其他的网络连接。
CAN 的特点主要有以下几点:
①、多主控制。在总线空闲时,所有单元都可以发送消息(多主控制),而两个以上的单元同时开始发送消息时,根据标识符(Identifier 以下称为 ID)决定优先级。 ID 并不是表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始发送消息时,对各消息 ID 的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。
②、系统的柔软性。与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单元时,连接在总线上的其它单元的软硬件及应用层都不需要改变。
③、通信速度快,距离远最高 1Mbps(距离小于 40M),最远可达 10KM(速率低于 5Kbps)。
④、具有错误检测、错误通知和错误恢复功能,所有单元都可以检测错误(错误检测功能),检测出错误的单元会立即同时通知其他所有单元(错误通知功能),正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新发送此消息直到成功发送为止(错误恢复功能)。
⑤、故障封闭功能。CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。
⑥、连接节点多。CAN 总线是可同时连接多个单元的总线。可连接的单元总数理论上是没有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。

CAN 电气属性

CAN 总线使用两根线来连接各个单元: CAN_H 和 CAN_L, CAN 控制器通过判断这两根线上的电位差来得到总线电平, CAN 总线电平分为显性电平和隐性电平两种。显性电平表示逻辑“0”,此时 CAN_H 电平比 CAN_L 高,分别为 3.5V 和 1.5V,电位差为 2V。隐形电平表示逻辑“1”,此时 CAN_H 和 CAN_L 电压都为 2.5V 左右,电位差为 0V。 CAN 总线就通过显性和隐形电平的变化来将具体的数据发送出去,如图所示:

CAN 总线上没有节点传输数据的时候一直处于隐性状态,也就是说总线空闲状态的时候一直处于隐性。 CAN 网络中的所有单元都通过 CAN_H 和 CAN_L 这两根线连接在一起,如图所示:

图中所有的 CAN 节点单元都采用 CAN_H 和 CAN_L 这两根线连接在一起, CAN_H 接CAN_H、 CAN_L 接 CAN_L, CAN 总线两端要各接一个 120Ω的端接电阻,用于匹配总线阻抗,吸收信号反射及回拨,提高数据通信的抗干扰能力以及可靠性。CAN 总线传输速度可达 1Mbps/S,最新的 CAN-FD 最高速度可达 5Mbps/S,甚至更高,CAN-FD 不在本章讨论范围,感兴趣的可以自行查阅相关资料。 CAN 传输速度和总线距离有关,总线距离越短,传输速度越快。

CAN 协议

通过 CAN 总线传输数据是需要按照一定协议进行的, CAN 协议提供了 5 种帧格式来传输数据:数据帧、遥控帧、错误帧、过载帧和帧间隔。其中数据帧和遥控帧有标准格式和扩展格式两种,标准格式有 11 位标识符(ID),扩展格式有 29 个标识符(ID)。这 5 种帧的用途见下表:

1、数据帧
数据帧由 7 段组成:
①、帧起始,表示数据帧开始的段。
②、仲裁段,表示该帧优先级的段。
③、控制段,表示数据的字节数及保留位的段。
④、数据段,数据的内容,一帧可发送 0~8 个字节的数据。
⑤、 CRC 段,检查帧的传输错误的段。
⑥、 ACK 段,表示确认正常接收的段。
⑦、帧结束,表示数据帧结束的段。
数据帧结构如图所示:

图中给出了数据帧标准格式和扩展格式两种帧结构,图中 D 表示显性电平 0、 R 表示隐性电平 1, D/R 表示显性或隐性,也就是 0 或 1,我们来简单分析一下数据帧的这 7 个段。
①、帧起始:帧起始很简单,标准格式和扩展格式都是由一个位的显性电平 0 来表示帧起始。
②、仲裁段:仲裁段表示帧优先级,仲裁段结构如图所示:

标准格式和扩展格式的仲裁段不同,从图可以看出,标准格式的 ID 为 11 位,发送顺序是从 ID10 到 ID0,最高 7 位 ID10~ID4 不能全为隐性(1),也就是禁止 0X1111111XXXXX这样的 ID。扩展格式的 ID 为 29 位,基本 ID 从 ID28 到 ID18,扩展 ID 由 ID17 到 ID0,基本ID 与标准格式一样,禁止最高 7 位都为隐性。
③、 控制段:控制段由 6 个位构成,表示数据段的字节数,标准格式和扩展格式的控制段略有不同,如图所示:

图中 r1 和 r0 为保留位,保留位必须以显性电平发送。 DLC 为数据长度,高位在前, DLC 段有效值范围为 0~8。
④、数据段:数据段也就是帧的有效数据,标准格式和扩展格式相同,可以包含 0~8 个字节的数据,从最高位(MSB)开始发送,结构如图所示:

注意,图中数据段的 0~64 为 bit,对应到字节就是 0~8 字节。
⑤、 CRC 段:CRC 段保存 CRC 校准值,用于检查帧传输错误,标准格式和扩展格式相同, CRC 段结构如图所示:

从图可以看出, CRC 段由 15 位的 CRC 值与 1 位的 CRC 界定符组成。 CRC 值的计算范围包括:帧起始、仲裁段、控制段、数据段,接收方以同样的算法进行计算,然后用计算得到的 CRC 值与此 CRC 段进行比较,如果不一致的话就会报错。
⑥、 ACK 段:ACK 段用来确认接收是否正常,标准格式和扩展格式相同, ACK 段结构如图所示:

从图可以看出, ACK 段由 ACK 槽(ACK Slot)和 ACK 界定符两部分组成。 发送单元的 ACK,发送 2 个隐性位,而接收到正确消息的单元在 ACK 槽(ACK Slot)发送显性位,通知发送单元正常接收结束,这个过程叫发送 ACK/返回 ACK。发送 ACK 的是所有接收单元中接收到正常消息的单元, 所谓正常消息是指不含填充错误、格式错误、 CRC 错误的消息,这些接收单元既不处于总线关闭态也不处于休眠态的所有接收单元中。
⑦、帧结束
最后就是帧结束段,标准格式和扩展格式相同,帧结束段结构如图所示:

从图可以看出,帧结束段很简单,由 7 位隐性位构成。

2、 遥控帧

接收单元向发送单元请求数据的时候就用遥控帧,遥控帧由 6 个段组成:
①、帧起始,表示数据帧开始的段。
②、仲裁段,表示该帧优先级的段。
③、控制段,表示数据的字节数及保留位的段。
④、 CRC 段,检查帧的传输错误的段。
⑤、 ACK 段,表示确认正常接收的段。
⑥、帧结束,表示数据帧结束的段。
遥控帧结构如图所示:

从图可以看出,遥控帧结构基本和数据帧一样,最主要的区别就是遥控帧没有数据段。遥控帧的 RTR 位为隐性的,数据帧的 RTR 位为显性,因此可以通过 RTR 位来区分遥控帧和没有数据的数据帧。遥控帧没有数据,因此 DLC 表示的是所请求的数据帧数据长度,遥控帧的其他段参考数据帧的描述即可。

3、 错误帧

当接收或发送消息出错的时候使用错误帧来通知,错误帧由错误标志和错误界定符两部分组成,错误帧结构如图所示:

错误标志有主动错误标志和被动错误标志两种,主动错误标志是 6 个显性位,被动错误标志是 6 个隐性位,错误界定符由 8 个隐性位组成。

4、过载帧

接收单元尚未完成接收准备的话就会发送过载帧,过载帧由过载标志和过载界定符构成,过载帧结构如图所示:

过载标志由 6 个显性位组成,与主动错误标志相同,过载界定符由 8 个隐性位组成,与错误帧中的错误界定符构成相同。

5、 帧间隔

帧间隔用于分隔数据帧和遥控帧,数据帧和遥控帧可以通过插入帧间隔来将本帧与前面的任何帧隔开,过载帧和错误帧前不能插入帧间隔,帧间隔结构如图所示:

图中间隔由 3 个隐性位构成,总线空闲为隐性电平,长度没有限制,本状态下表示总线空闲,发送单元可以访问总线。延迟发送由 8 个隐性位构成,处于被动错误状态的单元发送一个消息后的帧间隔中才会有延迟发送。

CAN 速率

CAN 总线以帧的形式发送数据,但是最终到总线上的就是“0”和“1”这样的二进制数据,这里就涉及到了通信速率,也就是每秒钟发送多少位数据,前面说了 CAN2.0 最高速度为1Mbps/S。对于 CAN 总线,一个位分为 4 段:
①、同步段(SS)
②、传播时间段(PTS)
③、相位缓冲段 1(PBS1)
④、相位缓冲段 2(PBS2)
这些段由 Tq(Time Quantum)组成, Tq 是 CAN 总线的最小时间单位。帧由位构成,一个位由 4 个段构成,每个段又由若干个 Tq 组成,这个就是位时序。 1 位由多少个 Tq 构成、每个段又由多少个 Tq 构成等,可以任意设定位时序。通过设定位时序,多个单元可同时采样,也可任意设定采样点。 各段的作用和 Tq 数如图所示:

1 个位的构成如图所示:

图中的采样点是指读取总线电平,并将读到的电平作为位值的点。位置在 PBS1结束处。根据这个位时序,我们就可以计算 CAN 通信的波特率了。具体计算方法,我们等下再介绍,前面提到的CAN 协议具有仲裁功能,下面我们来看看是如何实现的。

在总线空闲态,最先开始发送消息的单元获得发送权。当多个单元同时开始发送时,各发送单元从仲裁段的第一位开始进行仲裁。连续输出显性电平最多的单元可继续发送。实现过程,如图所示:

图中,单元 1 和单元 2 同时开始向总线发送数据,开始部分他们的数据格式是一样的,故无法区分优先级,直到 T 时刻,单元 1 输出隐性电平,而单元 2 输出显性电平,此时单元 1 仲裁失利,立刻转入接收状态工作,不再与单元 2 竞争,而单元 2 则顺利获得总线使用权,继续发送自己的数据。这就实现了仲裁,让连续发送显性电平多的单元获得总线使用权。
关于 CAN 协议就讲到这里,关于 CAN 协议更详细的内容请参考《CAN 入门教程》。

I.MX6ULL FlexCAN 简介

I.MX6ULL 带有 CAN 控制器外设,叫做 FlexCAN, FlexCAN 符合 CAN2.0B 协议。 FlexCAN完全符合CAN协议,支持标准格式和扩展格式,支持64个消息缓冲。I.MX6ULL自带的FlexCAN
模块特性如下:
①、支持 CAN2.0B 协议,数据帧和遥控帧支持标准和扩展两种格式,数据长度支持 0~8 字节,可编程速度,最高 1Mbit/S。
②、灵活的消息邮箱,最高支持 8 个字节。
③、每个消息邮箱可以配置为接收或发送,都支持标准和扩展这两种格式的消息。
④、每个消息邮箱都有独立的接收掩码寄存器。
⑤、强大的接收 FIFO ID 过滤。
⑥、未使用的空间可以用作通用 RAM。
⑦、可编程的回测模式,用于进行自测。
⑧、可编程的优先级组合。
……
FlexCAN 支持四种模式:正常模式(Normal)、冻结模式(Freeze)、仅监听模式(Listen-Only)和回环模式(Loop-Back),另外还有两种低功耗模式:禁止模式(Disable)和停止模式(Stop)。

①、正常模式(Normal)
在正常模式下, FlexCAN 正常接收或发送消息帧,所有的 CAN 协议功能都使能。
②、冻结模式(Freeze)
当 MCR 寄存器的 FRZ 位置 1 的时候使能此模式,在此模式下无法进行帧的发送或接收,CAN 总线同步丢失。
③、仅监听模式(Listen-Onley)
当 CTRL 寄存器的LOM位置 1 的时候使能此模式,在此模式下帧发送被禁止,所有错误计数器被冻结,CAN 控制器工作在被动错误模式,此时只会接收其他 CAN 单元发出的 ACK 消息。
④、 回环模式(Loop-Back)
当 CTRL 寄存器的 LPB 位置 1 的时候进入此模式,此模式下 FlexCAN 工作在内部回环模式,一般用来进行自测。从模式下发送出来的数据流直接反馈给内部接收单元。

前面在讲解 CAN 协议的时候说过 CAN 位时序, FlexCAN 支持 CAN 协议的这些位时序,控制寄存器 CTRL 用于设置这些位时序, CTRL 寄存器中的 PRESDIV、 PROPSEG、 PSEG1、
PSEG2 和 RJW 这 5 个位域用于设置 CAN 位时序。PRESDIV 为 CAN 分频值,也即是设置 CAN 协议中的 Tq 值,公式如下:

𝑓𝑇𝑞 = 𝑓𝐶𝐴𝑁𝐶𝐿𝐾 / (PRESDIV + 1)

fCANCLK 为 FlexCAN 模块时钟,这个根据时钟章节设置即可,设置好以后就是一个定值,因此只需要修改 PRESDIV 即可修改 FlexCAN 的 Tq 频率值。

Tq 定了以后我们结合CAN协议各个段来看一下如何设置 FlexCAN 的速率:
SS: 同步段(Synchronization Segment),在 I.MX6ULL 参考手册中叫做 SYNC_SEG,此段固定为 1 个 Tq 长度,因此不需要我们去设置。
PTS: 传播时间段(Propagatin Segment), FlexCAN 的 CTRL 寄存器中的 PROPSEG 位域设置此段,可以设置为 0~7,对应 1~8 个 Tq。
PBS1: 相位缓冲段 1(Phase Buffer Segment 1), FlexCAN 的 CRTL 寄存器中的 PSEG1 位域设置此段,可以设置为 0~7,对应 1~8 个 Tq。
PBS2:相位缓冲段 2(Phase Buffer Segment 2), FlexCAN 的 CRTL 寄存器中的 PSEG2 位域设置此段,可以设置为 1~7,对应 2~8 个 Tq。
SJW: 再同步补偿宽度(reSynchronization Jump Width), FlexCAN 的 CRTL 寄存器中的 RJW位域设置此段,可以设置 0~3,对应 1~4 个 Tq。
FlexCAN 的 CAN 位时序如图所示:

根据图所示, SYNC_SEG+(PROP_SEG+PSEG1+2)+(PSEG2+1)就是总的 Tq,因此FlexCAN 的波特率就是:

𝐶𝐴𝑁波特率 = 𝑓𝑇𝑞 / 总 Tq

关于 I.MX6ULL 的 FlexCAN 控制器就讲解到这里,如果想更加详细的了解 FlexCAN,请参考《I.MX6ULL 参考手册》的“Chapter 26 Flexible Controller Area Network(FLEXCAN)”章节。

实验

设备树

NXP 原厂提供的设备树已经配置好了 FlexCAN 的节点信息(FlexCAN1 和 FlexCAN2),但是我们还是要来看一下如何配置 I.MX6ULL 的 CAN1 节点。首先看一下 I.MX6ULL 的 FlexCAN
设备树绑定文档,打开 Documentation/devicetree/bindings/net/can/ fsl-flexcan.txt,此文档描述了FlexCAN 节点下的相关属性信息,这里就不做介绍了,大家自行查阅。

1 flexcan1: can@02090000 {
2     compatible = "fsl,imx6ul-flexcan", "fsl,imx6q-flexcan";
3     reg = <0x02090000 0x4000>;
4     interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
5     clocks = <&clks IMX6UL_CLK_CAN1_IPG>,
6              <&clks IMX6UL_CLK_CAN1_SERIAL>;
7     clock-names = "ipg", "per";
8     stop-mode = <&gpr 0x10 1 0x10 17>;
9     status = "disabled";
10 };

注意dtsi中的 flexcan1 节点不需要我们修改,这里只是告诉大家 FlexCAN1完整节点信息。根据第 2 行的 compatible 属性就可以找到 I.MX6ULL 的 FlexCAN 驱动源文件,驱动文名为 drivers/net/can/flexcan.c。第 9 行的 status 属性为 disabled,所以 FlexCAN1 默认关闭的。在 imx6ull-alientek-emmc.dts 中添加使能 FlexCAN1 的相关操作,找到如下所示代码:

1 &flexcan1 {
2     pinctrl-names = "default";
3     pinctrl-0 = <&pinctrl_flexcan1>;
4     xceiver-supply = <&reg_can_3v3>;
5     status = "okay";
6 };

第 3 行指定 FlexCAN1 所使用的 pinctrl 节点为 pinctrl_flecan1。
第 4 行 xceiver-supply 属性指定 CAN 收发器的电压为 3.3V。
第 5 行将 flexcan1 节点的 status 属性改为“okay”,也就是使能 FlexCAN1。

使能 Linux 内核驱动

NXP 官方提供的 linux 内核默认已经集成了 I.MX6ULL 的 FlexCAN 驱动,但是没有使能,因此我们需要配置 Linux 内核,打开 FlexCAN 驱动,步骤如下:

-> Networking support
-> <*> CAN bus subsystem support //打开 CAN 总线子系统

接着使能 Freescale 系 CPU 的 FlexCAN 外设驱动,配置路径如下:

-> Networking support
-> CAN bus subsystem support
-> CAN Device Drivers
-> Platform CAN drivers with Netlink support
-> <*> Support for Freescale FLEXCAN based chips //选中

配置好以后重新编译内核,然后使用新的内核和设备树启动开发板。

FlexCAN 测试

使用新编译的内核和设备树启动开发板,然后输入如下命令:

ifconfig -a //查看所有网卡

前面我们说了, Linux 系统中把 CAN 总线接口设备作为网络设备进行统一管理,因此如果FlexCAN 驱动工作正常的话就会看到 CAN 对应的网卡接口,如图所示:

从图可以看出,有一个名为“can0”的网卡,这个就是 I.MX6U-ALPHA 开发板上的 CAN1 接口对应的 can 网卡设备。如果使能了 I.MX6ULL 上的 FlexCAN2 的话也会出现一个名为“can1”的 can 网卡设备。

移植 iproute2

busybox 自带的 ip 命令并不支持对 can 的操作,因此我们需要重新移植 ip 命令,也就是iproute2, iproute2 源码下载地址为: https://mirrors.edge.kernel.org/pub/linux/utils/net/iproute2/。这里我们下载 4.4.0 版本的。 将 iproute2-4.4.0.tar.gz 发送到 ubuntu 中并解压。解压完成以后会得到一个名为“iproute2-4.4.0”的目录,进入此目录中,打开 Makefile 并修改。在 Makefile 中找到下面这行:

CC := gcc
改为
CC:=arm-linux-gnueabihf-gcc

Makefile 修改完成以后直接使用“make”命令编译,编译成功以后就会在 iproute2 源码的ip 目录下得到一个名为“ip”的命令,如图所示:

替换开发板中的ip命令,重启。

移植 can-utils 工具

can0 网卡已经出现了,但是工作正不正常还不知道,必须要进行数据收发测试。这里我们使用 can-utils 这个工具来对 can0 网卡进行测试,因此要先移植 can-utils 到我们的开发板根文件系统中。 在 ubuntu 中新建一个名为“can-utils”的目录来存放 can-utils 的编译结果。然后将 can-utils源码拷贝到 ubuntu 中并解压。解压完成以后得到一个名为“can-utils-2020.02.04”的目录,这个即是 can-utils 源码,进入到此目录中,然后配置并编译,命令如下:

cd can-utils-2020.02.04 //进入 can-utils 源码目录
./autogen.sh //先执行 autogen.sh,生成配置文件 configure
./configure --target=arm-linux-gnueabihf --host=arm-linux-gnueabihf 
--prefix=/home/zuozhongkai/linux/IMX6ULL/tool/can-utils --disable-static --enable-shared //配置
make //编译
make install

编译完成以后就会前面创建的“can-utils”目录下就会多出一个“bin”目录,此目录下保存着 can-utils 的各种小工具,如图所示:

将图中的所有 can-utils 小工具全部拷贝到开发板根文件系统下的/usr/bin 目录下,拷贝完成以后我们就可以使用这些小工具来测试 CAN 了。

CAN 通信测试

正点原子的 I.MX6U-ALPHA 开发板上只有一个 CAN 接口,因此我们还需要另外一个 CAN设备,可以使用另一块 I.MX6U-ALPHA 开发板,或者 USB 转 CAN 设备,这里我两个都测试一下。
将两个开发板的 CAN 接口连接起来,注意, CAN_H 接 CAN_H, CAN_L 接 CAN_L!

①、收发测试
首先使用 ip 命令设置两个开发板的 CAN 接口,首先设置 CAN 接口的速度,输入如下所示命令:

ip link set can0 type can bitrate 500000

上述命令设置 can0 速度为 500Kbit/S,两个 CAN 设备的速度要设置为一样的!速度设置好以后打开 can0 网卡,命令如下:

ifconfig can0 up //打开 can0

can0 打开以后就可以使用 can-utils 里面的小工具进行数据收发测试了。一个开发板用来接收数据,一个用来发送数据,接收数据的开发板使用 candump 命令,输入如下命令:

candump can0 //接收数据

发送数据的开发板使用 cansend 命令向接收单元发送 8 个字节的数据: 0X11、 0X22、 0X33、0X44、 0X55、 0X66、 0X77、 0X88。输入如下命令:

cansend can0 5A1#11.22.33.44.55.66.77.88

cansend 命令用于发送 can 数据,“5A1”是帧 ID,“#”号后面的“11.22.33.44.55.66.77.88”就是要发送的数据,十六进制。 CAN2.0 一次最多发送 8 个字节的数据, 8 个字节的数据之间用“.”隔开。
如果CAN工作正常的话接收端就会接收到上面发送过来的这8个字节的数据,如图所示:

从图中可以看出,接收端的 can0 接口接收到了 8 个字节的数据,帧 ID 为 5A1,说明 CAN 驱动工作正常。如果要关闭 can0 的话输入如下命令:

ifconfig can0 down

②、回环测试
如果要在一个板子上进行 CAN 回环测试,按照如下命令设置 CAN:

ifconfig can0 down //如果 can0 已经打开了,先关闭
ip link set can0 type can bitrate 500000 loopback on //开启回环测试
ifconfig can0 up //重新打开 can0
candump can0 & //candump 后台接收数据
cansend can0 5A1#11.22.33.44.55.66.77.88 //cansend 发送数据

如果回环测试成功的话那么开发板就会收到发送给自己的数据,如图所示:

USB 转 CAN 卡测试

接下来我们使用一个 USB 转 CAN 卡与正点原子的 I.MX6U-ALPHA 开发板进行数据收发测试。
首先设置开发板的 can0 接口,速度为 500Kbit/S,命令如下:

ip link set can0 type can bitrate 500000 //设置 can0,速率 500Kbit
ifconfig can0 up //打开 can0
candump can0 & //candump 后台接收数据

按照 USBCAN 说明手册设置好 USB CAN 卡,速度设置为 500Kbit,首先通过 USBCAN 向ALPHA 发送数据,发送的数据如图所示:

从图可以看出, USBCAN 发送了 5 帧数据帧,帧类型为标准帧,这 5 帧数据都是一样的,帧 ID 分别为 0~4。开发板 CAN 接口工作正常的话就会接收到这 5 帧数据,接收到的数据如图所示:

从图可以看出,开发板 can0 接口接收到了 5 帧数据,和 USBCAN 发送的一致。也可以通过开发板向 USBCAN 发送数据,输入如下命令发送数据:

cansend can0 5A1#11.22.33.44.55.66.77.88

关于 CAN 驱动就讲解到这里,如果要编写 CAN 总线应用的话就直接使用 Linux 提供的SocketCAN 接口,使用方法类似网络通信,本教程不讲解应用编程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/288134.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

酷雷曼精彩亮相CMC 2023中国元宇宙大会,助力云上VR直播

12月23日&#xff0c;2023中关村论坛系列活动——CMC 2023中国元宇宙大会在石景山首钢园冰壶馆成功举办。酷雷曼VR作为元宇宙领域代表企业之一受邀出席会议&#xff0c;分享元宇宙技术研发成果及应用方案&#xff0c;并为大会提供VR直播技术支持。 大咖云集&#xff0c;共商元宇…

数据库进阶教学——主从复制(Ubuntu22.04主+Win10从)

目录 一、概述 二、原理 三、搭建 1、备份数据 2、主库配置Ubuntu22.04 2.1、设置阿里云服务器安全组 2.2、修改配置文件 /etc/my.cnf 2.3、重启MySQL服务 2.4、登录mysql&#xff0c;创建远程连接的账号&#xff0c;并授予主从复制权限 2.5、通过指令&#xff0c;查…

进程终结之道:kill与pskill的神奇战斗

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 进程终结之道&#xff1a;kill与pskill的神奇战斗 前言基本用法kill命令&#xff1a;基础语法&#xff1a;选项&#xff1a;示例&#xff1a; pskill命令&#xff1a;基础语法&#xff1a;选项&#x…

kbdnecnt.DLL文件缺失,软件或游戏无法启动运行,怎样快速修复?

不少人都在问“kbdnecnt.DLL文件”是什么&#xff1f;为什么电脑总是报错提示说“kbdnecnt.DLL文件缺失&#xff0c;软件无法启动”&#xff1f; 首先&#xff0c;先来了解“kbdnecnt.DLL文件”是什么&#xff1f; kbdnecnt.DLL是Windows操作系统中的一个动态链接库文件&#…

JOSEF约瑟 断电延时继电器 SRTD-220VDC-2H2D 导轨安装

系列型号&#xff1a; SRTD-24VDC-1H1D断电延时继电器&#xff1b;SRTD-110VDC-1H1D断电延时继电器&#xff1b; SRTD-220VDC-1H1D断电延时继电器&#xff1b;SRTD-110VAC-1H1D断电延时继电器&#xff1b; SRTD-220VAC-1H1D断电延时继电器&#xff1b;SRTD-24VDC-2H断电延时继电…

考PMP真的有用吗?看完立马不犹豫了!

其实我个人觉得在你考证之前&#xff0c;值得反思的是&#xff1a;为什么要考这个证书&#xff1f;是因为公司需要&#xff1f;个人职业发展&#xff1f;还是受到新闻报道或广告的影响&#xff0c;觉得PMP证书有价值&#xff0c;只是想了解一下。这样就会导致很多人会说&#x…

golang并发编程-channel

在golang 并发编程里&#xff0c;经常会听到一句话&#xff1a;不要通过共享内存进行通信&#xff0c;通过通信来共享内存。下面我们会介绍下channel, 通过源码的方式去了解channel是怎么工作的。 基本结构 流程图 代码解读 type hchan struct {qcount uint // …

HubSpot邮件营销好用吗?

HubSpot的邮件营销工具通常被认为是非常强大和易用的&#xff0c;但用户的体验和满意度会因个人需求和经验而异。以下是一些通常与HubSpot邮件营销工具相关的优势&#xff1a; 全面的功能&#xff1a; HubSpot的邮件营销工具提供了丰富的功能&#xff0c;包括电子邮件自动化、…

西门子消防主机电源维修控制器BCB8005

火灾自动报警部分主要由各个部位的火灾探测器及手动报警按钮、消火栓按钮等设备组成。火灾探测器就如同火灾报警系统的“眼睛”,通过各自的火灾探测器采集现场的火警信号&#xff0c;实时传送给火灾报警控制器&#xff0c;火灾报警控制器进行各种智能的分析判断后发出火灾报警&…

【力扣题解】P700-二叉搜索树中的搜索-Java题解

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【力扣题解】 文章目录 【力扣题解】P700-二叉搜索树中的搜索-Java题解&#x1f30f;题目描述&#x1f4a1;题解&#x1f…

Python 从入门到精通之通俗易懂学闭包

系列 Python从入门到精通之安装与快速入门-CSDN博客 Python从入门到精通之基本数据类型和变量-CSDN博客 Python从入门到精通之集合&#xff08;List列表、Tuple元组、Dict字典、Set&#xff09;-CSDN博客 Python从入门到精通之条件语句、循环语句和函数-CSDN博客 Python从…

【双指针算法】-- 左右指针

左右指针 前言一、双指针算法二、左右指针1.用于在已排序数组中找到两个数使其和为特定值2.在字符串中判断是否为回文 总结 前言 今天在刷Leetcode的时候觉得自己双指针掌握的还是不错的记录一下,写个学习笔记,也方便以后翻阅,如果也帮助到你了,那真是太好啦! 本篇介绍的是左右…

八大算法排序@希尔排序(C语言版本)

目录 希尔排序概念算法思想示例分析结论算法步骤选择增量序列按增量分组逐步缩小增量 算法优势 代码实现核心算法希尔排序代码实现&#xff1a; 时间复杂度空间复杂度特性总结 该排序会关联到直接插入排序的知识点&#xff0c;如果对于直接插入排序还有所疑惑&#xff0c;可以跳…

Stable Diffusion模型概述

Stable Diffusion 1. Stable Diffusion能做什么&#xff1f;2. 扩散模型2.1 正向扩散2.2 反向扩散 3. 训练如何进行3.1 反向扩散3.2 Stable Diffusion模型3.3 潜在扩散模型3.4 变分自动编码器3.5 图像分辨率3.6 图像放大 4. 为什么潜在空间是可能的&#xff1f;4.1 在潜在空间中…

uniapp:签字版、绘画板 插件l-signature

官方网站&#xff1a;LimeUi - 多端uniapp组件库 使用步骤&#xff1a; 1、首先从插件市场将代码下载到项目 海报画板 - DCloud 插件市场 2、下载后&#xff0c;在项目中的uni_modules目录 3、最后 没有其它步骤&#xff0c;直接官网代码复制到vue文件中就可以了&#xff0c…

挑战 ChatGPT 和 Google Bard 的防御

到目前为止&#xff0c;科学家已经创建了基于人工智能的聊天机器人&#xff0c;可以帮助内容生成。我们还看到人工智能被用来创建像 WormGPT 这样的恶意软件&#xff0c;尽管地下社区对此并不满意。但现在正在创建聊天机器人&#xff0c;可以使用生成人工智能通过即时注入活动来…

stable diffusion 基础教程-文生图

置顶大模型插件资源链接 你如果没有魔法上网,请自取 百度云盘链接:链接:https://pan.baidu.com/s/1_xAu47XMdDNlA86ufXqAuQ?pwd=23wi 提取码:23wi 界面介绍 参数解释 参数解释Sampling method扩散去噪算法的采样模式,不同采样模式会带来不一样的效果steps模型生成图片的迭…

OpenCV-Python(24):模板匹配

原理及介绍 模板匹配是一种常用的图像处理技术&#xff0c;它用于在一幅图像中寻找与给定模板最匹配的区域(在一副大图中搜寻查找模版图像位置的方法)。模板匹配的基本思想是将模板图像在目标图像上滑动&#xff0c;并计算它们的相似度&#xff0c;找到相似度最高的位置即为匹配…

Docsify:一款便捷的文档生成工具

一、产品介绍 Docsify是一个简单、易用的文档生成工具。它允许用户使用Markdown编写文档&#xff0c;然后一键生成静态网站。这样&#xff0c;我可以方便地将我的知识库和项目文档分享给他人&#xff0c;同时还能保持文档的更新和完整性。 二、应用场景 非常适合个人知识库、…

Redis缓存与数据库如何保证一致性

数据库和缓存如何保证一致性&#xff1f; 目录 数据库和缓存如何保证一致性&#xff1f;背景方案先更新数据库&#xff0c;还是先更新缓存&#xff1f;先更新数据库&#xff0c;再更新缓存先更新缓存&#xff0c;再更新数据库 先更新数据库&#xff0c;还是先删除缓存&#xff…