1、 History
1.1 CAN总线发展历史
控制器局域网(Controller Area Network)最早由Bosch公司于1985年研发,用于搭建车内网络。在此之前,汽车生产商使用点对点布线系统连接车内电子设备。但随着车内电子设备的增多,这种布线系统需要的连线也越来越多,使系统变得既笨重又昂贵。于是,生产商开始使用车内网络来替代点对点布线系统,以降低布线的成本、复杂度,以及系统重量。在此背景下,CAN作为一种构建智能设备网络的高集成度串行总线系统应运而生,成为车内网络的标准。由此,CAN在汽车业界迅速普及,于1993年成为国际标准(ISO 11898)。1994年后,数个CAN的高层协议标准形成,如CANopen和DeviceNet。这些新增协议也为其他市场广泛接受,现已成为工业通信标准的一部分。
1.2 从业经历中接触到的CAN总线的历史
1、aa 的分子诊断仪的加样针(Tecan)的通信
2、bb 的仪器里使用的优爱宝步进电机控制器
3、cc 的输液管理系统的通信
2、 CAN应用
CAN最初是在汽车领域诞生的,因此最常见的应用就是车内电子网络。然而在过去的二十年,越来越多的行业认识了CAN的可靠性和优势,将CAN总线应用在许多其他场合。例如有轨电车、地铁、轻轨及长途列车等都应用了CAN网络。在这些车辆中,均可发现发现多种CAN构建的网络,如连接车门单元、刹车控制器、客流计数单元等。在航空领域亦可发现CAN的应用,如飞行状态传感器、导航系统以及座舱中的计算机。此外,在航天应用中也能看到CAN总线的身影,如飞行数据分析和飞行器引擎控制系统(燃料系统、泵、线性执行器等)。
医疗设备制造商使用CAN构建医疗设备的嵌入式网络。部分医院已经使用CAN来管理整个手术室。医院通过基于CAN的系统管理手术室的各个部分,如灯光、手术台、X光机和病患床铺。升降电梯和电扶梯也采用CAN网络,通过CANopen协议连接电梯设备,如面板、控制器、电梯门和挡光器,并进行控制操作。
3、 CAN术语
3.1 隐性与显性电平
CAN控制器通过组成总线的2根线(CAN-H和CAN-L)的电位差来确定总线的电平,在任一时刻,总线上有2种电平:显性电平和隐性电平。
“显性”具有“优先”的意味,只要有一个单元输出显性电平,总线上即为显性电平,并且,“隐性”具有“包容”的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平。
总线上执行逻辑上的线“与”时,显性电平的逻辑值为“0”,隐性电平为“1”。
3.2 帧类型
类型 | 使用 | 备注 |
---|---|---|
数据帧 | 发送方通过此帧向接收方传送信息 | 用户发送 |
远程帧 | 接收方通过此帧向具有相同ID的发关方请示数据 | 用户发送 |
错误帧 | 当检测到错误时,向其它单元通知检测到错误 | 控制器发送 |
过载帧 | 接收方用来通知还末准备好接收一帧 | 控制器发送 |
帧间隙 | 用来将数据帧或远程帧与前面的帧隔开 | 控制器发送 |
3.3 数据帧格式
数据帧在结构上由7个段组成:
其中根据仲裁段ID码长度的不同,分为标准帧(CAN2.0A)和扩展帧(CAN2.0B)
3.4 远程帧格式
远程帧在结构上由6个段组成:
对于错误帧、过载帧、帧间隙攻城狮不需要知道太多的细节。
4、 Linux CAN
这里以IMX6Q,linux3.0.35为例,参考《i.MX 6Dual/6Quad Linux Reference Manual》文档中的 Chapter 32 FlexCAN Driver
首先在内核配置时,要把CAN给配置好,具体可以参考上述文档。
内核参考文档:
linux-3.0.35/Documentation/networking/can.txt
驱动源码:
linux-3.0.35/drivers/net/can/flexcan.c
4.1 主要的数据结构:
The basic CAN frame structure and the sockaddr structure are defined
in include/linux/can.h:
struct can_frame {
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
__u8 can_dlc; /* data length code: 0 .. 8 */
__u8 data[8] __attribute__((aligned(8)));
};
The sockaddr_can structure has an interface index like the
PF_PACKET socket, that also binds to a specific interface:
struct sockaddr_can {
sa_family_t can_family;
int can_ifindex;
union {
/* transport protocol class address info (e.g. ISOTP) */
struct { canid_t rx_id, tx_id; } tp;
/* reserved for future CAN protocols address information */
} can_addr;
};
4.2 第一步:
初始化CAN
ifconfig canX down
ip link set canX type can tq 250 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
ip link set canX type can bitrate 500000
ip link set canX type can restart-ms 100
ifconfig canX up
4.3 第二步:
建立socket连接
struct ifreq ifr;
sockaddr_can addr;
fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
ret = ioctl(fd, SIOCGIFINDEX, &ifr);
addr.can_family = PF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
bind(fd,(struct sockaddr *)&addr,sizeof(addr));
4.4 第三步:
接收
fd_set fdRead;
struct can_frame frame;
int nbytes;
struct timeval tv;
memset(&frame,0,sizeof(frame));
FD_ZERO(&fdRead);
FD_SET(fd, &fdRead);
tv.tv_sec = 0;
tv.tv_usec = 5; // 5us wait time
ret = select(fd+1, &fdRead, NULL, NULL, &tv);
if (ret <= 0)
{
return ;
}
bool selectForRead = FD_ISSET(fd, &fdRead);
if (selectForRead)
{
socklen_t len = sizeof(addr);
nbytes = recvfrom(fd, &frame, sizeof(struct can_frame), 0,
(struct sockaddr*)&addr, &len);
if( frame.can_dlc != 0)
{
// get one frame
}
}
发送
struct can_frame frame;
FD_ZERO(&fdWrite);
FD_SET(fd, &fdWrite);
tv.tv_sec = 0;
tv.tv_usec = 5; // 5us wait time
ret = select(fd+1, NULL, &fdWrite, NULL, &tv);
if (ret <= 0)
{
return;
}
bool selectForWrite = FD_ISSET(fd, &fdWrite);
if (selectForWrite)
{
sendto(fd, &frame, sizeof(struct can_frame), 0,
(struct sockaddr*)&addr, sizeof(addr));
}
文件系统
#ls /sys/class/net/can0/
addr_assign_type dormant link_mode statistics
addr_len duplex mtu subsystem
address features netdev_group tx_queue_len
broadcast flags operstate type
carrier ifalias power uevent
dev_id ifindex queues
device iflink speed
5、Tips
- 半双工通信,差分信号
- 终端电阻 100 欧姆
- ID越小发送优先级越高
- 速率越高传送距离越短,最高1Mbps
- 最多一帧能传8个字节
- 多主模式
6、 参考
https://en.wikipedia.org/wiki/CAN_bus
http://blog.csdn.net/maifansnet/article/details/48950615
http://www.cnblogs.com/pejoicen/p/3986587.html
http://blog.csdn.net/shanghaiqianlun/article/details/17794427
https://lwn.net/Articles/253425/
CAN2.0A/B 文档