CAN 总线与嵌入式通信

2.1k 词

CAN(Controller Area Network)是机器人中最常用的现场总线之一。本文涵盖 CAN 协议基础、SocketCAN 编程及常用调试工具。

CAN 总线基础

特点

  • 多主模式:任意节点可在总线空闲时发送
  • 仲裁机制:ID 越小优先级越高(非破坏性仲裁)
  • 差分信号:CAN_H 和 CAN_L,抗干扰强
  • 错误检测:CRC 校验、位错误、填充错误等

帧格式

帧类型 用途
数据帧 发送数据(标准帧 11bit ID,扩展帧 29bit ID)
远程帧 请求数据
错误帧 检测到错误
过载帧 通知需要延时

CAN 命令速查

1
2
3
4
5
6
7
8
9
10
11
12
# 查看 CAN 接口
ip link show

# 设置波特率并启动
sudo ip link set can0 type can bitrate 1000000
sudo ip link set up can0

# 发送数据
cansend can0 123#11223344AABBCCDD

# 接收数据
candump can0

SocketCAN

Linux 内核提供的 CAN 编程接口,将 CAN 设备抽象为网络设备。

基本编程流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <linux/can.h>
#include <linux/can/raw.h>
#include <sys/socket.h>
#include <net/if.h>
#include <sys/ioctl.h>

// 创建 socket
int s = socket(PF_CAN, SOCK_RAW, CAN_RAW);

// 绑定到 can0
struct sockaddr_can addr;
addr.can_family = AF_CAN;
addr.can_ifindex = if_nametoindex("can0");
bind(s, (struct sockaddr*)&addr, sizeof(addr));

// 发送
struct can_frame frame;
frame.can_id = 0x123;
frame.can_dlc = 8;
write(s, &frame, sizeof(frame));

// 接收
read(s, &frame, sizeof(frame));

can-utils 工具集

1
2
3
4
5
cansend can0 123#AABBCCDD     # 发送
candump can0 # 监听
cangen can0 # 生成随机数据(测试用)
canplayer # 回放 candump 记录
cansniffer can0 # 可视化嗅探

CMake 常用技巧

基本结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cmake_minimum_required(VERSION 3.0)
project(MyProject)

# 查找包
find_package(catkin REQUIRED COMPONENTS roscpp std_msgs)

# 包含头文件
include_directories(${catkin_INCLUDE_DIRS})

# 编译可执行文件
add_executable(my_node src/my_node.cpp)
target_link_libraries(my_node ${catkin_LIBRARIES})

# 安装
install(TARGETS my_node
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})

常用变量

1
2
3
4
${PROJECT_NAME}          # 项目名
${PROJECT_SOURCE_DIR} # 源码根目录
${CMAKE_INSTALL_PREFIX} # 安装路径
${catkin_INCLUDE_DIRS} # catkin 头文件路径

Cmake install

1
2
3
install(TARGETS my_node DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
install(DIRECTORY launch/ DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch)
install(DIRECTORY config/ DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/config)

常用调试命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 系统日志
journalctl -u my_service # 查看服务日志
journalctl -f # 实时跟踪

# GPU
sudo prime-select query # 查看当前显卡
nvidia-smi # GPU 状态

# 进程
htop # 交互式进程查看
ps aux | grep ros # 查找 ROS 进程

# 网络
ip addr # 网络接口
ping 192.168.1.1 # 连通性测试