Linux系统CAN通讯开发-1

825 阅读4分钟
## 为什么选择Linux系统
- 内核集成CAN驱动
Linux内核从2.6.25开始加入了对CAN驱动的支持,这意味着在任何Linux发行版上连接CAN盒子,都直接适配支持。
笔者开发常用的PCAN-USB(Peak CAN),通过USB端口连接到上位机,在内核加载CAN模块,就可以像普通网络设备一样使用。淘宝上可以买到的
ZLG(周立功)和兼容ZLG的CAN卡,理论上也都可以适配。
- 遵循Socket的编程模型
Linux CAN完全照搬了以太网网络开发的模式,采用基于Socket的编程模型,所以Linux的CAN编程接口又称为SocketCAN
编程接口。这样,熟悉Linux网络开发的工程师可以很容易地上手处理CAN报文的发送接收和解析。以下处理CAN报文监听和接收的代码是不是很熟悉。
```c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int s;
struct sockaddr_can addr;
struct ifreq ifr;
s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
/* can0 is the CAN interface */
strcpy(ifr.ifr_name, "can0" );
ioctl(s, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
bind(s, (struct sockaddr *)&addr, sizeof(addr));
struct can_frame frame;
nbytes = read(s, &frame, sizeof(struct can_frame));
if (nbytes < 0) {
perror("can raw socket read");
return 1;
}
/* paranoid check ... */
if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "read: incomplete CAN frame\n");
return 1;
}
/* do something with the received CAN frame */
```
基于统一的Socket模型,可以直接和select,epoll等高级IO并发通讯模型适配,方便处理多通道CAN并发的场景。
- 易于使用脚本做二次开发
随着python 3.3增加了对SocketCAN的支持,开源社区涌现了不少优秀的CAN开发和测试的基础库,支持诸如CAN报文dump分析、DBC文件处理转换、诊断协议处理和应用,FOTA等等常见的汽车电子开发任务。只要熟悉基本python的开发知识,在这些基础库之上,进行配置定制或者进行二次开发,解决实际工作中的问题,难度大大降低了。
- Windows下的CANoe平台很贵
以前汽车电子开发,一般都要在Vector的CANoe软硬件专业平台进行。这套平台目前只支持Windows操作系统,而且价格昂贵。如果要同时采集六个CAN口的设备,就至少需要两个VN1640的设备,价格至少要十几万起。而笔者使用PCAN-USB X6和SocketCAN搭建的开发测试系统,成本在一万元上下。除了在少数专业领域(之后会介绍),它能覆盖大多数常见的开发需求。另外,SocketCAN还能支持虚拟CAN设备(vcan),即使没有物理CAN卡,也可以使用模拟CAN设备,进行开发。这种vcan设备对于某些开发场景,有特别的价值(TODO)。
总结下来,基于SocketCAN开发汽车电子应用,从软件开发角度来说,知识迁移成本低,特别是对于Linux系统工程师接近零成本。硬件部署成本相对于Vector CANoe显著降低。不管是软硬件都是很有潜力的选择。
## CAN通讯简介
- CAN信号
CAN使用两条差分信号线,分别称为CAN-H和CAN-L,保持在2.5V。传输隐形信号时,代表0,CAN-H拉高到5V,CAN-L拉低到0V;传输显性信号时,代表1,CAN-H和L保持不变在2.5V。
- 通信方式
CAN节点接入总线,发送和接收不能同时进行,一帧报文包含ID,标示报文的优先级,数字越小,优先级越高。仲裁机制可以保证,多个报文同时发往总线时,优先级高被传输,低的停止传输(1)。
- 帧格式
这里不详细介绍每个数据段的内容,对于CAN标准帧来说,最重要的段包括起始帧、ID、数据长度(DLC)、8个字节的数据载体、CRC校验、ACK和EOF结束段。
## SocketCAN模型介绍
SocketCAN是集成到Linux kernel内的一整套开源的CAN驱动和网络协议栈,由大众汽车研究所开发。在它出现之前,Linux的CAN驱动和协议栈存在一个问题,就是多个进程无法并发的访问同一个CAN设备,一个进程也无法同时访问多个CAN设备。而SocketCAN将CAN抽象成一种网络设备,而不是字节设备。请看下图,它在Socket层和物理设备间增加了CAN驱动和新的CAN协议族(protocol family),和其他网络设备处于平行的地位。这样,应用层访问CAN设备,就像访问以太网设备一样,多个进程通过传统的socket API就可以并发的访问每个CAN设备。每个CAN设备在系统中也注册为独立的网络接口(network interface),每个进程都可以通过多个socket绑定不同的CAN网络接口来访问多个设备。
![Image of SocketCAN layer](./Socketcan.png)
- 载入CAN驱动和注册CAN设备
```shell
$ modprobe can_dev
$ modprobe can
$ modprobe can_raw
$ sudo ip link set can0 type can bitrate 500000
$ sudo ip link set up can0
```
- 虚拟CAN网络
Linux通过SocketCAN可以支持虚拟CAN设备,可以用来模拟基于CAN协议的ECU组件,对逻辑进行一些初步的测试。
注册虚拟设备也很类似物理设备的流程
```shell
$ modprobe can
$ modprobe can_raw
$ modprobe vcan
$ sudo ip link add dev vcan0 type vcan
$ sudo ip link set up vcan0
$ ip link show vcan0
```