千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  技术干货  > SocketCAN详解

SocketCAN详解

来源:千锋教育
发布人:xqq
时间: 2023-11-21 18:17:30 1700561850

一、SocketCAN简介

SocketCAN是由Linux内核维护的CAN协议栈,可以使用Linux内核提供的Socket API进行CAN总线的读写操作,用户只需要使用C语言实现与Socket API通讯,就可以控制CAN总线上的节点,实现数据的发送与接收。

SocketCAN不需要安装额外的驱动程序,可以通过系统自带的套接字机制直接读写CAN总线,具有工作稳定、性能优异等优点,被广泛应用于各种工业自动化、汽车领域的CAN总线控制中。

二、SocketCAN的使用

1、Socket参数

在使用SocketCAN时,需要设置一些必要的Socket参数,以便实现CAN总线的正确读写。下面列出一些常用的Socket参数:

(1)CAN接口名称

struct ifreq ifr;
strcpy(ifr.ifr_name, "can0");
ioctl(sockfd, SIOCGIFINDEX, &ifr);

在使用SocketCAN时需要指定CAN总线的名称,一般都为can0,但根据实际情况而定,可以使用ioctl函数获取CAN总线的索引。

(2)CAN总线接收过滤器

struct can_filter rfilter;
rfilter.can_id = 0x123;
rfilter.can_mask = CAN_SFF_MASK;
setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

CAN总线上会出现大量的数据,但并非所有的数据都需要进行处理。使用CAN总线过滤器可以过滤掉一些不需要的数据,以免影响系统性能,使用setsockopt函数可以设置CAN总线的过滤器。

(3)CAN帧长度

setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &setsockopt_value, sizeof(setsockopt_value));

在使用SocketCAN读取CAN总线数据时,需要指定CAN帧的长度,使用setsockopt函数可以设置CAN帧的缓冲区长度。

2、Socket参数什么意思

SocketCAN使用的是一种基于内存映射的CAN协议栈,它将CAN帧映射到共享内存区域,以便用户可以直接访问数据。

SocketCAN提供了一系列Socket参数,用于控制CAN协议栈的数据访问方式,包括需要访问的内存地址、读写的方法、读写的长度、超时时间等等。

3、Socket参考文献

SocketCAN参考文献包括:

(1)Linux内核源代码中的文件

/include/linux/can.h
/include/uapi/linux/can/error.h
/include/uapi/linux/can/netlink.h
/include/uapi/linux/can/raw.h
/net/can/af_can.c
/net/can/bcm.c
/net/can/isotp.c
/net/can/raw.c

使用SocketCAN时需要引用这些头文件和源文件,它们包含了SocketCAN的API、数据结构、驱动程序等等相关信息

(2)SocketCAN的官方网站

http://www.pengutronix.de/software/libsocketcan/

SocketCAN的官方网站包含了SocketCAN的最新版本、API文档、教程、用户手册等等相关信息。

4、Socket参数大全

Socket参数大全包括:

(1)CAN接口名称

指定CAN总线的名称,一般为can0、can1等等

(2)CAN总线接收过滤器

过滤掉一些不需要的数据,提高系统性能

(3)CAN帧长度

指定CAN帧的缓冲区长度,以便读取数据

5、Socket参数详解

Socket参数详解包括:

(1)CAN接口名称

在使用SocketCAN时需要指定CAN总线的名称,一般都为can0,但根据实际情况而定,可以使用ioctl函数获取CAN总线的索引。

(2)CAN总线接收过滤器

CAN总线上的数据非常多,无法全部进行处理。使用过滤器可以屏蔽一些不需要的数据,以提高系统性能。可以使用setsockopt函数设置过滤器,对于过滤器的设置方法可以参考相关文献。

(3)CAN帧长度

SocketCAN需要设置CAN帧的缓冲区长度,以便读取数据。使用setsockopt函数可以设置CAN帧的缓冲区长度。

(4)读写方法

在CAN总线上进行读写操作时,需要选择正确的读写方法,通常可以使用recv函数进行数据接收,使用send函数进行数据发送,也可以使用read和write函数进行数据读写。

(5)读写的长度

对于不能保证读写长度的情况,用户需要显式地指定读写的长度。读取CAN总线数据时,需要指定读取数据的长度,写入CAN总线数据时,需要指定写入数据的长度。

(6)超时时间

SocketCAN需要一个超时时间,在CAN总线读写数据时,需要设置一个超时时间,以便在指定时间内完成数据读写。超时时间可以使用setsockopt函数进行设置。

6、Socket参数怎么设置

Socket参数的设置可以使用setsockopt函数进行设置,一般使用下面的格式:

setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

其中,sockfd变量为Socket文件描述符,SOL_CAN_RAW是SocketCAN协议的套接字类型,CAN_RAW_FILTER是套接字选项,rfilter是选项参数,sizeof(rfilter)表示选项参数的大小。

7、Socket参数无效

在使用Socket参数时,需要注意一些常见的问题,如参数无效。在设置Socket参数时,需要校验参数值是否正确,可以使用errno变量查看错误信息。

8、Socket参数对照表

CAN接口名称 SOL_CAN_RAW SIOCGIFINDEX
CAN总线接收过滤器 SOL_CAN_RAW CAN_RAW_FILTER
CAN帧长度 SOL_SOCKET SO_RCVBUF
读写方法 SOL_SOCKET recv/send
读写长度 / read/write
超时时间 SOL_SOCKET SO_RCVTIMEO/SO_SNDTIMEO

9、Socket参数说明

根据以上讲解,可以对Socket参数做以下简单说明:

(1)CAN接口名称

使用SocketCAN时需要指定CAN总线的名称,一般都为can0,但根据实际情况而定,可以使用ioctl函数获取CAN总线的索引。

(2)CAN总线接收过滤器

CAN总线上的数据非常多,无法全部进行处理。使用过滤器可以屏蔽一些不需要的数据,以提高系统性能。可以使用setsockopt函数设置过滤器,对于过滤器的设置方法可以参考相关文献。

(3)CAN帧长度

SocketCAN需要设置CAN帧的缓冲区长度,以便读取数据。使用setsockopt函数可以设置CAN帧的缓冲区长度。

(4)读写方法

在CAN总线上进行读写操作时,可以使用recv函数进行数据接收,使用send函数进行数据发送,也可以使用read和write函数进行数据读写。

(5)读写的长度

对于不能保证读写长度的情况,用户需要显式地指定读写的长度。读取CAN总线数据时,需要指定读取数据的长度,写入CAN总线数据时,需要指定写入数据的长度。

(6)超时时间

SocketCAN需要一个超时时间,在CAN总线读写数据时,需要设置一个超时时间,以便在指定时间内完成数据读写。超时时间可以使用setsockopt函数进行设置。

10、Socket参数指标选取

在使用SocketCAN时,需要根据具体情况选择合适的Socket参数指标,如CAN接口名称、CAN总线接收过滤器、CAN帧长度、读写方法、读写长度、超时时间等等。选择合适的Socket参数指标可以提高系统的性能,优化CAN总线的数据读写效率。

代码示例

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char **argv)
{
    int ret, s;
    struct sockaddr_can addr;
    struct ifreq ifr;
    struct can_frame frame;
    char *ifname = "can0";

    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (s < 0) {
        perror("socket error");
        return -1;
    }

    strcpy(ifr.ifr_name, ifname);
    ioctl(s, SIOCGIFINDEX, &ifr);

    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;

    ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
    if (ret < 0) {
        perror("bind error");
        return -1;
    }

    memset(&frame, 0, sizeof(frame));

    frame.can_id = 0x123;
    frame.can_dlc = 2;
    frame.data[0] = 0x11;
    frame.data[1] = 0x22;

    ret = write(s, &frame, sizeof(frame));
    if (ret != sizeof(frame)) {
        perror("write error");
        return -1;
    }

    ret = read(s, &frame, sizeof(frame));
    if (ret < 0) {
        perror("read error");
        return -1;
    }

    printf("CAN id: 0x%lX, length: %d\n", frame.can_id, frame.can_dlc);
    printf("Data: %02X %02X\n", frame.data[0], frame.data[1]);

    close(s);

    return 0;
}

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。
10年以上业内强师集结,手把手带你蜕变精英
请您保持通讯畅通,专属学习老师24小时内将与您1V1沟通
免费领取
今日已有369人领取成功
刘同学 138****2860 刚刚成功领取
王同学 131****2015 刚刚成功领取
张同学 133****4652 刚刚成功领取
李同学 135****8607 刚刚成功领取
杨同学 132****5667 刚刚成功领取
岳同学 134****6652 刚刚成功领取
梁同学 157****2950 刚刚成功领取
刘同学 189****1015 刚刚成功领取
张同学 155****4678 刚刚成功领取
邹同学 139****2907 刚刚成功领取
董同学 138****2867 刚刚成功领取
周同学 136****3602 刚刚成功领取
相关推荐HOT