7. CAN总线¶
CAN总线协议(Controller Area Network), 控制器局域网总线,是德国BOSCH(博世)公司研发的一种串行通讯协议总线, 它可以使用双绞线来传输信号,是世界上应用最广泛的现场总线之一。
支持CAN总线的鲁班猫板卡如下:
LubanCat-1HS
LubanCat-2、LubanCat-2(V1-V2)
LubanCat-2N、LubanCat-2N-V2
LubanCat-2IO
注意
野火2024.01.25修复can/canfd概率扩展帧变成标准帧以及填充位错误的问题,如果是旧镜像使用can/canfd请在线更新内核或者安装以下内核deb,或者刷比此日期更新的镜像。
1 2 3 | #在线更新内核
sudo apt update
sudo apt install linux-headers-4.19.232 linux-image-4.19.232
|
离线更新内核deb包:
将以上两个deb包传到板卡,使用命令 sudo dpkg -i linux*.deb 进行安装。
在线或者离线选其一即可。
7.1. CAN硬件连接¶
7.1.1. 板卡款¶
支持的板卡:
LubanCat-2、LubanCat-2(V1-V2)
LubanCat-2N、LubanCat-2N-V2
板卡款从40pin排针中引出CAN接口,查看 40pin引脚对照图 章节, 确认CAN具体的引脚。
注意
由于板卡款的CAN信号是从主控内部CAN控制器直接引出的信号,如果要外接CAN设备还需要先连接CAN收发器模块。
以板卡连接CAN分析仪为例,其中:
CAN收发器模块: 野火小智【CAN收发器】模块
CAN设备: CAN分析仪
板卡连接CAN分析仪接线如下:
1 2 3 4 5 6 | 板卡 对接 CAN收发器 CAN收发器 对接 USB CAN分析仪
CAN_TX ------ CAN_TX H ------ H
CAN_RX ------ CAN_RX L ------ L
5V ------ 5V
GND ------ GND
3.3V ------ EN
|
提示
如果是板卡自收发测试可不连接CAN收发器模块。
板卡自收发测试接线如下:
1 2 3 | 板卡 对接 板卡
CAN_TX ------ CAN_TX
CAN_RX ------ CAN_RX
|
7.1.2. 广告机款¶
支持的板卡:
LubanCat-1HS
广告机款底板已经板载CAN收发器,无需再接CAN收发器模块,板卡自收发测试以及和CAN设备通信接线如下:
1 2 3 4 5 6 7 8 9 | #板卡自收发测试
板卡 对接 板卡
CAN0_H ------ CAN1_H
CAN0_L ------ CAN1_L
#板卡接CAN设备
板卡 对接 设备
CANx_H ------ H
CANx_L ------ L
|
LubanCat-1HS对应的接口示意图如下:

7.1.3. 核心板底板款¶
支持的板卡:
LubanCat-2IO
核心板底板款底板已经板载CAN收发器,无需再接CAN收发器模块,板卡自收发测试以及和CAN设备通信接线如下:
1 2 3 4 5 6 7 8 9 | #板卡自收发测试
板卡 对接 板卡
CAN0_H ------ CAN1_H
CAN0_L ------ CAN1_L
#板卡接CAN设备
板卡 对接 设备
CANx_H ------ H
CANx_L ------ L
|
LubanCat-2IO对应的接口示意图如下:

7.2. CAN¶
7.2.1. can配置¶
开启和关闭can fd都需要重启才能生效
修改设备树插件上的时钟频率,
kernel/arch/arm64/boot/dts/rockchip/overlay/rk3568-lubancat-canX-mY-overlay.dts
(X,Y是各自的数字)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /dts-v1/;
/plugin/;
#include <dt-bindings/clock/rk3568-cru.h>
/ {
compatible = "rockchip,rk3568";
fragment@0 {
target = <&can1>;
__overlay__ {
status = "okay";
compatible = "rockchip,rk3568-can-2.0";
assigned-clocks = <&cru CLK_CAN1>;
assigned-clock-rates = <200000000>;
pinctrl-names = "default";
pinctrl-0 = <&can1m0_pins>;
};
};
};
|
assigned-clock-rates时钟频率可以修改,如果CAN的比特率1M建议修改CAN时钟到300M,信号更稳定。低于1M比特率的,时钟设置200M就可以,默认使用的是200M
修改设备树插件及替换请参考: 设备树插件
开启设备树插件(这里以打开CAN1为例)
1 2 | #修改配置文件
vi /boot/uEnv/uEnv.txt
|
把
#dtoverlay=/dtb/overlay/rk3568-lubancat-can1-m1-overlay.dtbo
前面的#删除,如下图

注意
can1和canfd1不能同时开启
关闭设备树插件(这里以打开CAN1为例)
在
dtoverlay=/dtb/overlay/rk3568-lubancat-can1-m1-overlay.dtbo
前面添加#,如下图

7.2.2. can通信测试¶
安装测试工具
1 2 | sudo apt update
sudo apt install can-utils
|
通信测试
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 30 31 32 | 查询当前网络设备:
ifconfig -a
CAN启动:
关闭CAN:
ip link set can0 down
设置比特率500KHz:
ip link set can0 type can bitrate 500000
打印can0信息:
ip -details link show can0
启动CAN:
ip link set can0 up
CAN发送:
发送(标准帧,数据帧,ID:123,date:DEADBEEF):
cansend can0 123#DEADBEEF
发送(标准帧,远程帧,ID:123):
cansend can0 123#R
发送(扩展帧,数据帧,ID:00000123,date:DEADBEEF):
cansend can0 00000123#12345678
发送(扩展帧,远程帧,ID:00000123):
cansend can0 00000123#R
CAN接收:
开启打印,等待接收:
candump can0
|
7.2.3. 更多指令¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 关闭can设备
ip link set canX down
开启can设备
ip link set canX up
显示can设备详细信息
ip -details link show canX
接收can总线发来数据
candump canX
关闭can设备,以便配置
ifconfig canX down
设置can波特率
ip link set canX up type can bitrate 250000
发送数据
cansend canX --identifier=ID+数据
使用滤波器接收ID匹配的数据
candump canX --filter=ID:mask
|
7.2.4. 简单的自收发脚本¶
将can1和can2对接起来,配置好波特率,然后执行以下脚本,收发日志保存在/home/cat/log.txt
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 | #!/bin/bash
#监控can0数据
candump can0 >> /home/cat/log.txt &
counter=0
while true; do
#can0发送can0 123#00000000~123#99999999数据
data=$(printf "%08d" $counter)
command="cansend can0 123#$data"
echo $command
$command
#can1发送can0 321#00000000~321#99999999数据
command2="cansend can1 321#$data"
echo $command2
$command2
if [ $counter -eq 99999999 ]; then
counter=0
else
counter=$((counter+1))
fi
sleep 0.01
done
|
7.2.5. C程序测试¶
代码较长复制粘贴容易乱序,可以下载我们提供的源码 can_send.c
以下使用system设置波特率,可自行修改,for循环中的延时影响帧率,如果需要更快速率可减小延时。
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
int main(int argc, char *argv[])
{
struct ifreq ifr = {0};
struct sockaddr_can can_addr = {0};
struct can_frame frame = {0};
unsigned char buffer[4] = {0};
int sockfd = -1;
unsigned int cnt = 0;
int ret;
// 设置CAN波特率为500000
system("ip link set can0 down");
system("ip link set can0 type can bitrate 500000");
system("ip link set can0 up");
sockfd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if(0 > sockfd) {
perror("socket error");
exit(EXIT_FAILURE);
}
/* 指定 can0 设备 */
strcpy(ifr.ifr_name, "can0");
ioctl(sockfd, SIOCGIFINDEX, &ifr);
can_addr.can_family = AF_CAN;
can_addr.can_ifindex = ifr.ifr_ifindex;
/* 将 can0 与套接字进行绑定 */
ret = bind(sockfd, (struct sockaddr *)&can_addr, sizeof(can_addr));
if (0 > ret) {
perror("bind error");
close(sockfd);
exit(EXIT_FAILURE);
}
setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
memcpy(frame.data, buffer, sizeof(buffer));
frame.can_dlc = sizeof(buffer);
frame.can_id = 0x123;
for (;;) {
frame.data[0] = (cnt >> 24) & 0xff;
frame.data[1] = (cnt >> 16) & 0xff;
frame.data[2] = (cnt >> 8) & 0xff;
frame.data[3] = cnt & 0xff;
cnt++;
ret = write(sockfd, &frame, sizeof(frame));
if (sizeof(frame) != ret) {
perror("write error");
break;
}
usleep(10 * 1000);
}
close(sockfd);
exit(EXIT_SUCCESS);
}
|
编译并运行:
1 2 3 4 5 | #编译程序
gcc can_send.c -o can_send
#运行
sudo ./can_send
|
测试效果如下,大概每秒发送100帧数据,数据ID号为0x0123,数据每帧递增。

7.3. CAN FD¶
7.3.1. can fd配置¶
开启和关闭can fd都需要重启才能生效
修改设备树插件上的时钟频率,
kernel/arch/arm64/boot/dts/rockchip/overlay/rk3568-lubancat-canfdX-mY-overlay.dts
(X,Y是各自的数字)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /dts-v1/;
/plugin/;
#include <dt-bindings/clock/rk3568-cru.h>
/ {
compatible = "rockchip,rk3568";
fragment@0 {
target = <&can1>;
__overlay__ {
status = "okay";
compatible = "rockchip,canfd-1.0";
pinctrl-names = "default";
assigned-clocks = <&cru CLK_CAN1>;
assigned-clock-rates = <100000000>;
pinctrl-0 = <&can1m0_pins>;
};
};
};
|
assigned-clock-rates时钟频率可以修改,如果CAN的比特率低于等于3M建议修改CAN时钟到100M,信号更稳定。高于3M比特率的,时钟设置200M就可以,默认为100M
修改设备树插件及替换请参考: 设备树插件
开启设备树插件(这里以打开CAN1 FD为例)
1 2 | #修改配置文件
vi /boot/uEnv/uEnv.txt
|
把
#dtoverlay=/dtb/overlay/rk3568-lubancat-canfd1-m1-overlay.dtbo
前面的#删除,如下图

注意
can1和canfd1不能同时开启
关闭设备树插件(这里以打开CANFD1为例)
在
dtoverlay=/dtb/overlay/rk3568-lubancat-canfd1-m1-overlay.dtbo
前面添加#,如下图

7.3.2. can fd通信测试¶
安装测试工具
1 2 | sudo apt update
sudo apt install can-utils
|
通信测试
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 | 查询当前网络设备:
ifconfig -a
CAN FD启动:
关闭CAN:
ip link set can0 down
设置仲裁段1M波特率,数据段3M波特率:
ip link set can0 type can bitrate 1000000 dbitrate 3000000 fd on
打印can0信息:
ip -details link show can0
启动CAN:
ip link set can0 up
CAN FD发送:
发送(标准帧,数据帧,ID:123,date:DEADBEEF):
cansend can0 123##1DEADBEEF
发送(扩展帧,数据帧,ID:00000123,date:DEADBEEF):
cansend can0 00000123##1DEADBEEF
CAN接收:
开启打印,等待接收:
candump can0
|
7.3.3. 更多指令¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 关闭can设备
ip link set canX down
开启can设备
ip link set canX up
显示can设备详细信息
ip -details link show canX
接收can总线发来数据
candump canX
关闭can设备,以便配置
ifconfig canX down
设置仲裁段1M波特率,数据段3M波特率:
ip link set can0 type can bitrate 1000000 dbitrate 3000000 fd on
发送数据
cansend canX --identifier=ID+数据
使用滤波器接收ID匹配的数据
candump canX --filter=ID:mask
|
7.4. 修改CAN缓冲区¶
执行下面命令可以查看CAN缓冲区大小:
1 | cat /sys/class/net/can0/tx_queue_len
|
默认缓冲区大小只有10,每秒最多发4000帧,如果帧率再高缓冲区将没有多余的空间,提示No buffer space available
修改缓冲区大小可以增加发送速率上限,执行以下命令:
1 | echo 4096 > /sys/class/net/can0/tx_queue_len
|
效果如下:
