CAN总线应用开发接口

CAN总线应用开发接口由于系统将CAN设备作为网络设备进行管理,因此在CAN总线应用开发方面,Linux提供了SocketCAN接口,使得CAN总线通信近似于和以太网的通信,应用程序开发接口更加通用,也更加灵活。此外,通过https://gitorious.org/linux-can/can-utils网站发布的基于SocketCAN的can-utils工具套件,也可以实现简易的CAN总线通信。下面具体

大家好,又见面了,我是你们的朋友全栈君。

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

此外,通过https://gitorious.org/linux-can/can-utils网站发布的基于SocketCAN的can-utils工具套件,也可以实现简易的CAN总线通信。

下面具体介绍使用SocketCAN实现通信时使用的应用程序开发接口。

1. 初始化

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

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

2. 数据发送

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

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

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

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

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

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

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

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

3. 数据接收

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

   
  1. struct can_frame frame;  
  2. 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结构体来实现,定义如下:

   
  1. struct can_filter {  
  2. canid_t can_id;  
  3. canid_t can_mask;  
  4. }; 

过滤的规则为:

   
  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));  
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/151112.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 圆柱体体积的计算公式圆柱体积的计算公式_圆的面积计算公式

    圆柱体体积的计算公式圆柱体积的计算公式_圆的面积计算公式圆柱体体积计算公式?长方形的周长=(长+宽)×2正方形的周长=边长×4长方形的面积=长×宽正方形的面积=边长×边长三角形的面积=底×高÷2平行四边形的面积=底×高梯形的面积=(上底+下底)×高÷2直径=半径×2半径=直径÷2圆的周长=圆周率×直径=圆周率×半径×2圆的面积=圆周率×半径×半径长方体的表面积=(长×宽+长×高+宽×高)×2长方体的体积=长×宽×高正方体的表面积=棱长×棱长×6正…

    2022年9月20日
    5
  • 实验设备管理系统C语言_实验室设备管理系统代码

    实验设备管理系统C语言_实验室设备管理系统代码这里写目录标题实验室设备管理系统题目要求源代码运行结果实验室设备管理系统题目要求实验设备管理系统设计实验设备信息包括:设备编号,设备种类(如:微机、打印机、扫描仪等等),设备名称,设备价格,设备购入日期,是否报废,报废日期等。主要功能:(1)能够完成对设备的录入和修改(2)对设备进行分类统计(3)设备的破损耗费和遗损处理(4)设备的查询要求:使用文件方式存储数据。源代码#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#i

    2022年10月13日
    3
  • Linux下的tar压缩解压缩命令使用

    Linux下的tar压缩解压缩命令使用tar参数:-c:建立压缩档案-x:解压-t:查看内容-r:向压缩归档文件末尾追加文件-u:更新原压缩包中的文件这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个。下面的参数是根据需要在压缩或解压档案时可选的。-z:有gzip属性的,通过gzip过滤归档-j:有bz2属性的,通过bzip2过滤归档-v:显示所有过程-Z:有compress属…

    2022年5月25日
    35
  • CockroachDB_DB商城

    CockroachDB_DB商城概述CockroachDB是一个分布式关系型数据库,主要设计目标是可扩展,强一致和高可靠。在无人干预情况下,能以极短的中断时间容忍磁盘、主机、机架甚至整个数据中心的故障。采用完全去中心化架构,

    2022年8月4日
    5
  • datax(10): 源码解读Communication(Datax通讯类)「建议收藏」

    datax(10): 源码解读Communication(Datax通讯类)「建议收藏」前面看了datax的通讯机制,继续看源码—具体的通讯类Communication。根据datax的运行模式的区别,数据的收集会有些区别,这篇文章都是讲的在standalone模式下。一、communication概述DataX所有的统计信息都会保存到Communication类里面。Communication支持下列数据的统计计数器,比如读取的字节速度,写入成功的数据条数/***所有的数值key-value对**/privateMap<String.

    2022年5月17日
    49
  • vue 二维码生成插件_vue生成二维码组件

    vue 二维码生成插件_vue生成二维码组件效果图1,下插件cnpmivue-qr–save2,在需要的页面引入,或者全局引入,我这里是局部引入,因为只有一个页面用到了。html<vue-qr:text=”text”:size=”200″:margin=”0″/>jsimportVueQrfrom’vue-qr’exportdefault{components:{VueQr},data(){ return{ text:”,//二维码内容 .

    2022年10月4日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号