CAN总线(Controller Area Network,控制器局域网络)由德国博世公司于上世纪80年代提出,近20年来,随着CAN总线在工业测控与汽车领域的普及,CAN网络技术不断优化,取得了长足发展。如今CAN总线已经成为了汽车上不可或缺的重要环节,ECU内部的CAN总线开发也占到了ECU开发中的很大分量。在汽车中为了满足车载系统的不同要求,主要采用高速CAN和低速CAN。这两者以不同的总线速率工作以获得最佳的性价比,在两条总线之间采用CAN网关进行连接。

CAN 总线标准主要在ISO 11898这个文档里,此外还有 Bosch 的CAN 2.0。

CAN 是一种总线,所有的设备(称为节点,Node)都接在同一条线上。所有节点可以(尽管不应该)同时操作总线。

CAN 是串行的,一般只需要 3 根线:CAN_H、CAN_L、GND。CAN_H与CAN_L差分传送数据,物理上应该双绞,而 GND 做线壳。电压不定,一般来说 5V 电源时,要表示0,CAN_H和CAN_L都是 2.5V;表示 1,CAN_H是 3.5V,CAN_L是 1.5V。

CAN 线在物理上(不用在意如何)实现了“线与(wired-AND)”的连接方式——任何一个节点输出0,总线即为0。

CAN设备在Linux系统中以网络设备的形式呈现,通常设备名为can[n],n为从0开发的自然数。使用ifconfig命令可以查看到系统中的CAN设备。在LInux系统中提供SocketCAN接口来方便开发者操作CAN设备。

初始化CAN设备:

int can_fd; 
struct sockaddr_can addr; 
struct ifreq ifr;

can_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
strcpy(ifr.ifr_name, "can0");

/* determine the interface index */
ioctl(s, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
/* bind the socket to a CAN interface */
bind(s, (struct sockaddr *)&addr, sizeof(addr));

收发操作:

CAN设备收发数据是以Frame的结构,在Linux中表示如下:

struct can_frame { 
    canid_t can_id;//CAN 标识符 
    __u8 can_dlc;//数据场的长度 
    __u8 data[8];//数据 
};

发送数据:

struct can_frame frame;
int wsize;
frame.can_id = 0x123;//如果为扩展帧,那么 frame.can_id = CAN_EFF_FLAG | 0x123; 
frame.can_dlc = 1; //数据长度为 1 
frame.data[0] = 0xAB; //数据内容为 0xAB 

wsize = write(can_fd, &frame, sizeof(frame));

接收数据:

struct can_frame frame;
int rsize;
rsize = read(s, &frame, sizeof(frame));

过滤规则:

在接收的时,可以预先设置过滤规则,实现CAN帧报文的过滤。Linux提供了can_filter结构体来实现。

struct can_filter {
    canid_t can_id;
    canid_t can_mask;
};
作者:SteveChen  创建时间:2024-09-17 16:28
最后编辑:SteveChen  更新时间:2024-09-17 16:28
上一篇:
下一篇: