19. CAN总线¶
CAN是控制器局域网络(Controller Area Network)的简称, 它是由研发和生产汽车电子产品著称的德国BOSCH公司开发的, 并最终成为国际标准(ISO11519),是国际上应用最广泛的现场总线之一。
19.1. 使能CAN设备树插件¶
CAN总线的设备树插件和485总线设备树插件存在引脚冲突,因此在启用CAN总线设备树插件时需要关闭 485设备树插件。 修改 boot/uEnv.txt 文件,找到can、485相关设备树插件修改如下, 修改后并重启开发板。
1 2 3 4 5 | #dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-485r1-overlay.dtbo
#dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-485r2-overlay.dtbo
dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-can1.dtbo
dtoverlay=/usr/lib/linux-image-4.19.35-imx6/overlays/imx-fire-can2.dtbo
|
19.2. 简单测试CAN功能¶
将开发板中CAN总线的跳帽连接上, 接着将CAN接口按照下图所示的方法对接,CAN1H与CAN2H连接,CAN1L与CAN2L连接。

使用以下命令查看是否存在CAN总线设备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ifconfig -a
can0: flags=128<NOARP> mtu 16
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 10 (UNSPEC)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device interrupt 25
can1: flags=128<NOARP> mtu 16
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 10 (UNSPEC)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device interrupt 26
|
安装can测试工具
1 | sudo apt-get -y install can-utils
|
运行以下命令,设置can总线设备的波特率等信息,并且使能can总线设备。
1 2 3 4 5 | #设置can0
sudo ip link set can0 type can bitrate 1000000;sudo ip link set can0 up
#设置can1
sudo ip link set can1 type can bitrate 1000000;sudo ip link set can1 up
|
打开两个不同的终端,一个用于读取设备数据,一个用于发送设备数据
1 2 | #获取can数据
candump can0
|
1 2 | #发送数据
cansend can1 123#abcdabcd
|
此时在终端1中将会接收到终端2传来的数据。
19.3. CANopenNode简介¶
CANopen 协议是在 20 世纪 90 年代末在 CAL(CAN Application Layer)的基础上发展而来的, 由CiA301(或EN 50325-4)标准指定,是用于嵌入式控制系统的国际标准化的基于CAN的高层协议。 有很多代码可以实现这个标准协议,其中就有CANopenNode, CANopenNode是免费的开源CANopen协议栈,遵循Apache 2.0开源协议,这意味着你可以使用他进行商用, 闭源等,当然更具体的协议约束得具体看协议的内容,CANopenNode可以在任何Linux机器上运行, 代码仓库位于 https://github.com/CANopenNode/CANopenNode 。
除此之外CANopenNode以面向对象的方式用ANSI C语言编写, 它可以作为独立应用程序或与RTOS在不同的微控制器上运行。
19.3.1. CANopenNode实验¶
在拉取仓库源码前,需要先安装一些编译工具。
1 2 | sudo apt update
sudo apt install gcc make git can-utils
|
官方代码仓库位于: https://github.com/CANopenNode/CANopenNode.git。
也可从野火的代码仓库中拉取libmodbus源码,
1 2 | #gitee仓库地址
git clone https://gitee.com/Embedfire/CANopenNode.git
|
拉取下来后看到本地有CANopenNode文件夹,我们点进去, 可以看到CANopen源码相关的文件与文件夹,如下所示
1 2 3 | root@npi:/home/debian/CANopenNode# ls
301 309 CANopen.h doc example LICENSE README.md
305 CANopen.c codingStyle Doxyfile extra Makefile socketCAN
|
使用make命令编译源码
1 2 3 4 5 6 7 | make
# 编译输出的内容
···
cc -Wall -g -IsocketCAN -I. -Iexample -IsocketCAN -c example/CO_OD.c -o example/CO_OD.o
cc -Wall -g -IsocketCAN -I. -Iexample -IsocketCAN -c socketCAN/CO_main_basic.c -o socketCAN/CO_main_basic.o
cc -pthread socketCAN/CO_driver.o socketCAN/CO_error.o socketCAN/CO_Linux_threads.o socketCAN/CO_OD_storage.o 301/CO_SDOserver.o 301/CO_Emergency.o 301/CO_NMT_Heartbeat.o 301/CO_HBconsumer.o 301/CO_SYNC.o 301/CO_PDO.o 301/CO_TIME.o 301/CO_SDOclient.o 301/crc16-ccitt.o 301/CO_fifo.o 305/CO_LSSslave.o 305/CO_LSSmaster.o 309/CO_gateway_ascii.o extra/CO_trace.o CANopen.o example/CO_OD.o socketCAN/CO_main_basic.o -o canopend
|
编译完成之后在当前目录下生成了canopend可执行文件,
在其中一个终端上运行以下命令:
1 | candump can0
|
在另外一个终端上运行以下命令:
1 | ./canopend can1 -i 4 -s od4_storage -a od4_storage_auto
|
可以看到接收端的开发板收到了很多数据,其中包括心跳以及CANopen协议的其他数据内容。
1 2 3 4 5 6 7 8 9 10 11 | root@npi:~# candump can0
can0 704 [1] 00
can0 084 [8] 00 50 01 2F F3 FF FF FF
can0 704 [1] 7F
can0 704 [1] 7F
can0 704 [1] 7F
can0 704 [1] 7F
can0 704 [1] 7F
can0 704 [1] 7F
can0 704 [1] 7F
can0 704 [1] 7F
|
发送端终端打印消息如下
1 2 3 4 5 6 7 8 | debian@npi:~/CANopenNode$ ./canopend can1 -i 4 -s od4_storage -a od4_storage_auto
./canopend[662]: CANopen device, Node ID = 0x04, starting
./canopend[662]: CANopen device, Node ID = 0x04, communication reset
./canopend[662]: CAN Interface "can1" Buffer set to 367 messages (163840 Bytes)
./canopend[662]: CANopen NMT state changed to: "initializing" (0)
./canopend[662]: CANopen device, Node ID = 0x04, running ...
./canopend[662]: CANopen NMT state changed to: "pre-operational" (127)
./canopend[662]: CANopen Emergency message from node 0x04: errorCode=0x5000, errorRegister=0x01, errorBit=0x2F, infoCode=0xFFFFFFF3
|
19.4. CAN设备树¶
野火imx6ull提供了很多的设备树插件源码,若想要添加或修改不同的引脚作为CAN引脚, 可参考:
/arch/arm/boot/dts
仓库中提供了CAN1、CAN2的设备树插件, 其中CAN1的设备树插件文件为 imx-fire-can1-overlay.dts ,源码如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | /dts-v1/;
/plugin/;
#include "imx6ul-pinfunc.h"
#include "dt-bindings/gpio/gpio.h"
/ {
fragment@0 {
target = <&flexcan1>;
__overlay__ {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexcan1>;
status = "okay";
};
};
fragment@1 {
target = <&iomuxc>;
__overlay__ {
pinctrl_flexcan1: flexcan1grp{
fsl,pins = <
MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX 0x1b020
MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX 0x1b020
>;
};
};
};
};
|
can设备树插件修改相对简单,若想修改相对应的引脚,只需修改代码的22-23行即可。