zoukankan      html  css  js  c++  java
  • bbb SOCKET CAN

         系统将CAN设备作为网络设备进行管理,因此在CAN总线应用开发方面,Linux提供了SocketCAN接口,使得CAN总线通信近似于和以太网的通信,应用程序开发接口更加通用,也更加灵活。

         我们使用原始套接字与BBB的can绑定,进行通信。

    1. 初始化

    SocketCAN中大部分的数据结构和函数在头文件linux/can.h 中进行了定义。CAN总线套接字的创建采用标准的网络套接字操作来完成。网络套接字在头文件sys/socket.h中定义。套接字的初始化方法如下:

    int s;  
    struct sockaddr_can addr;  
    struct ifreq ifr;  
    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);   //创建SocketCAN套接字  
    strcpy(ifr.ifr_name, "can0" );  
    ioctl(s, SIOCGIFINDEX, &ifr);      //指定can0设备  
    addr.can_family = AF_CAN;  
    addr.can_ifindex = ifr.ifr_ifindex;  
    bind(s, (struct sockaddr *)&addr, sizeof(addr));   //将套接字与can0绑定

    2. 数据发送

    在数据收发的内容方面,CAN总线与标准套接字通信稍有不同,每一次通信都采用can_ frame结构体将数据封装成帧。结构体定义如下:

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

    can_id为帧的标识符,如果发出的是标准帧,就使用can_id的低11位;如果为扩展帧,就使用0~28位。can_id的第29、30、31位是帧的标志位,用来定义帧的类型,定义如下:

    #define CAN_EFF_FLAG 0x80000000U    //扩展帧的标识  
    #define CAN_RTR_FLAG 0x40000000U    //远程帧的标识  
    #define CAN_ERR_FLAG 0x20000000U    //错误帧的标识,用于错误检查 

    数据发送使用write函数来实现。如果发送的数据帧(标识符为0x123)包含单个字节(0xAB)的数据,可采用如下方法进行发送:

    struct can_frame frame;  
    frame.can_id = 0x123;      //如果为扩展帧,那么frame.can_id = CAN_EFF_FLAG | 0x123;  
    frame.can_dlc = 1;     //数据长度为1  
    frame.data[0] = 0xAB;     //数据内容为0xAB  
    int nbytes = write(s, &frame, sizeof(frame)); //发送数据  
    if (nbytes != sizeof(frame))   //如果nbytes不等于帧长度,就说明发送失败  
      printf("Error
    !"); 

    如果要发送远程帧(标识符为0x123),可采用如下方法进行发送:

    struct can_frame frame;  
    frame.can_id = CAN_RTR_FLAG | 0x123;  
    write(s, &frame, sizeof(frame)); 

    3. 数据接收

    数据接收使用read函数来完成,实现如下:

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

    当然,套接字数据收发时常用的send、sendto、sendmsg以及对应的recv函数也都可以用于CAN总线数据的收发。

    4. 错误处理

    当帧接收后,可以通过判断can_id中的CAN_ERR_FLAG位来判断接收的帧是否为错误帧。如果为错误帧,可以通过can_id的其他符号位来判断错误的具体原因。

    错误帧的符号位在头文件linux/can/error.h中定义。

    5. 过滤规则设置

    在数据接收时,系统可以根据预先设置的过滤规则,实现对报文的过滤。过滤规则使用can_filter结构体来实现,定义如下:

    struct can_filter {  
    canid_t can_id;  
    canid_t can_mask;  
    }; 

    过滤的规则为:

    1. 接收到的数据帧的can_id & mask == can_id & mask 

    通过这条规则可以在系统中过滤掉所有不符合规则的报文,使得应用程序不需要对无关的报文进行处理。在can_filter结构的can_id中,符号位CAN_INV_FILTER在置位时可以实现can_id在执行过滤前的位反转。

    用户可以为每个打开的套接字设置多条独立的过滤规则,使用方法如下:

    1. struct can_filter rfilter[2];  
    2. rfilter[0].can_id   = 0x123;  
    3. rfilter[0].can_mask = CAN_SFF_MASK; //#define CAN_SFF_MASK 0x000007FFU  
    4. rfilter[1].can_id   = 0x200;  
    5. rfilter[1].can_mask = 0x700;  
    6. setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter)); //设置规则 

    在极端情况下,如果应用程序不需要接收报文,可以禁用过滤规则。这样的话,原始套接字就会忽略所有接收到的报文。在这种仅仅发送数据的应用中,可以在内核中省略接收队列,以此减少CPU资源的消耗。禁用方法如下:

    1. setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); //禁用过滤规则 

    通过错误掩码可以实现对错误帧的过滤,例如:

    1. can_err_mask_t err_mask = ( CAN_ERR_TX_TIMEOUT | CAN_ERR_BUSOFF );  
    2. setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, err_mask, sizeof(err_mask)); 

    在默认情况下,本地回环功能是开启的,可以使用下面的方法关闭回环/开启功能:

    1. int loopback = 0;  // 0表示关闭, 1表示开启(默认)  
    2. setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback)); 

    在本地回环功能开启的情况下,所有的发送帧都会被回环到与CAN总线接口对应的套接字上。默认情况下,发送CAN报文的套接字不想接收自己发送的报文,因此发送套接字上的回环功能是关闭的。可以在需要的时候改变这一默认行为:

    1. int ro = 1; // 0表示关闭(默认), 1表示开启  
    2. setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &ro, sizeof(ro));  

     

  • 相关阅读:
    codeforces C. Cows and Sequence 解题报告
    codeforces A. Point on Spiral 解题报告
    codeforces C. New Year Ratings Change 解题报告
    codeforces A. Fox and Box Accumulation 解题报告
    codeforces B. Multitasking 解题报告
    git命令使用
    shell简单使用
    知识束缚
    php 调用系统命令
    数据传输方式(前端与后台 ,后台与后台)
  • 原文地址:https://www.cnblogs.com/beaglebone/p/5856626.html
Copyright © 2011-2022 走看看