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