Unix/C/C++进阶--SocketCAN 编程

news2024/11/28 12:44:40

Unix/C/C++进阶--SocketCAN 编程

  • 1 介绍
    • 1.1 socketcan 简介
    • 1.2 can 发展历程
    • 1.3 can总线优点
  • 2 知识点
    • 2.1 CAN详解--书籍、网站
    • 2.2 CAN详解--CAN与com口介绍
    • 2.3 CAN详解--各家CAN分析仪与软件的比较
    • 2.4 转载:CAN总线终端电阻
    • 2.5 如何破解汽车--CAN协议(can协议是明文)
    • 2.6 can--测试(收发、是否回传、网络状态)
    • 2.7 CAN详解--协议详解
    • 2.8 机器人开发--CanOpen
  • 3 SocketCAN 编程
    • SocketCAN 开发用到的头文件
    • 定义命令宏(建议放入开机命令中)
    • 初始化
    • 数据发送
    • 数据接收
    • 错误处理
    • 过滤规则设置
    • 回环功能设置
  • 参考

1 介绍

1.1 socketcan 简介

socketcan子系统是在Linux下CAN协议(Controller Area Network)实现的一种实现方法。 CAN是一种在世界范围内广泛用于自动控制、嵌入式设备和汽车领域的网络技术。Linux下最早使用CAN的方法是基于字符设备来实现的,与之不同的是Socket CAN使用伯克利的socket接口和linux网络协议栈,这种方法使得can设备驱动可以通过网络接口来调用。Socket CAN的接口被设计的尽量接近TCP/IP的协议,让那些熟悉网络编程的程序员能够比较容易的学习和使用。

1.2 can 发展历程

1、CAN ( Controller Area Network ) 即控制器局域网络。由于其高性能、高可靠性、及独特的设计,CAN越来越受到人们的重视。CAN最初是由德国的BOSCH公司为汽车监测、控制系统而设计的。现代汽车越来越多地采用电子装置控制,如发动机的定时、注油控制,加速、刹车控制(ASC)及复杂的抗锁定刹车系统(ABS)等。由于这些控制需检测及交换大量数据,采用硬接信号线的方式不但烦琐、昂贵,而且难以解决问题,采用CAN总线上述问题便得到很好地解决。
2、1983-1986年 大众与Bosch制定 软件协议,由Intel 生产控制器。
3、1990年 首次应用于汽车 奔驰 S级 12 缸发动机的汽车。
4、1991年9月,NXP半导体公司制定并发布CAN技术规范CAN2.0A/B,其中CAN2.0A协议规范定义了标准帧格式,CAN2.0B协议规范定义了扩展帧格式。
5、1993年11月,ISO组织正式颁布CAN国际标准ISO11898(高速应用,数据传输速率小于1Mbps)和ISO11519(低速应用,数据传输速率小于125Kbps)。
6、1996年 用于奥迪 A8 D2自动变速器 3.7升 V8 01V AG5的汽车。
7、1997年 用于帕萨特 B5 AG。
8、1998年 用于宝来、高尔夫 A4 AG。
9、VAN Bus 用于标志、雷诺、雪铁龙等,菲利普公司产品。
10、J1850-HBCC 用于福特,莫托罗拉公司产品。
11、J1850-DLC 用于通用,莫托罗拉公司产品。

1.3 can总线优点

1、数据传递更安全可靠;
2、低成本(通信介质可采用双绞线,同轴电缆和光导纤维,一般采用廉价的双绞线即可,无特殊要求);
3、高速实时传递;
4、有条件实现单线功能;
5、适用于各种汽车;
6、开放的标准。

2 知识点

2.1 CAN详解–书籍、网站

链接:CAN详解–书籍、网站

2.2 CAN详解–CAN与com口介绍

链接:CAN详解–CAN与com口介绍

在这里插入图片描述
在这里插入图片描述

2.3 CAN详解–各家CAN分析仪与软件的比较

链接:CAN详解–各家CAN分析仪与软件的比较

2.4 转载:CAN总线终端电阻

链接:转载:CAN总线终端电阻

在这里插入图片描述

2.5 如何破解汽车–CAN协议(can协议是明文)

链接:如何破解汽车–CAN协议

在这里插入图片描述

在这里插入图片描述

2.6 can–测试(收发、是否回传、网络状态)

链接:can–测试

  • can 收发数据
can-utils
candump can0 
cansend can0 123#DEADBEEF 
  • 设置回传
ifconfig can0 down
ip link set can0 type can bitrate 50000 loopback on
ip link set can0 up

terminal1 接收:
candump can0 
terminal2 发送
cansend can0 123#DEADBEEF 
  • 不回传
ifconfig can0 down
ip link set can0 type can bitrate 50000 
ip link set can0 up

terminal1 接收:
candump can0 
terminal2 发送
cansend can0 123#DEADBEEF 
  • 查看can网络状态
ip -d -s link show can0
  • 是否打开3次采样
ip link set can0 type can bitrate 125000 triple-sampling on
triple-sampling on:表示打开3次采样,在较低波特率下,建议使用该参数。
如果波特率较高,例如达到500Kbps,建议将其关闭:triple-sampling off,如果需要,也可打开
  • 是否重启
ip link set can0 type can bitrate 500000 restart-ms 100 triple-sampling on
restart-ms 100 设置总线 bus-off 时延时100ms自动重启;
  • 传输队列长度 Transmit Queue Length (txqueuelen)
设置过大,响应慢,可能会增加网络时延;设置过小,响应快,不过对于大量数据,可能丢包率较高
ip link set can0 txqueuelen 1023 type can bitrate 500000

2.7 CAN详解–协议详解

链接:CAN详解–协议详解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.8 机器人开发–CanOpen

链接:机器人开发–CanOpen

CANopen由非营利组织CiA(CAN in Automation)进行标准的起草及审核工作,基本的 CANopen 设备及通讯子协定定义在 CAN in Automation (CiA) draft standard 301中。针对个别设备的子协定以 CiA 301 为基础再进行扩充。如针对 I/O 模组的 CiA401 及针对运动控制的 CiA402。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • COB-ID
    在这里插入图片描述

3 SocketCAN 编程

SocketCAN 开发用到的头文件

#include <linux/can.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/can/raw.h>
#include <unistd.h>

定义命令宏(建议放入开机命令中)

#define ip_cmd_set_can0_params "ip link set can0 txqueuelen 1023 type can bitrate 500000 restart-ms 100 triple-sampling on"
#define ip_cmd_can0_up         "ifconfig can0 up"
#define ip_cmd_can0_down       "ifconfig can0 down"

// 使用系统调用函数运行以上命令,也可以自行在终端中运行,建议写shell脚本,开机运行
system(ip_cmd_set_can0_params); // 设置参数
system(ip_cmd_can0_up);  // 开启can0接口

初始化

int can_fd;
struct sockaddr_can addr;
struct ifreq ifr;
can_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW); // 创建 SocketCAN 套接字
strcpy(ifr.ifr_name, "can0" );
ioctl(can_fd, SIOCGIFINDEX, &ifr); // 指定 can0 设备
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
bind(can_fd, (struct sockaddr *)&addr, sizeof(addr)); // 将套接字与 can0 绑定
int socket (int domain, int type, int protocol)
在 SocketCan 中,第一个参数通常将其设置为PF_CAN ,指定为 CAN 通信协议

原始套接字两种协议:RAW,BCM
int can_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)
int can_fd = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);

使用 ioctl() 函数 将套接字与 can 设备绑定
ioctl(can_fd, SIOCGIFINDEX, &ifr); // 指定 can0 设备,并获取设备索引

struct sockaddr_can addr;
addr.can_family = AF_CAN;  // 指定协议族
addr.can_ifindex = ifr.ifr_ifindex;  // 设备索引
// 将套接字与 can0 绑定
int bind_res = bind(can_fd, (struct sockaddr *)&addr, sizeof(addr));

数据发送

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

struct can_frame {
	canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
	__u8    can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */
	__u8    __pad;   /* padding */
	__u8    __res0;  /* reserved / padding */
	__u8    __res1;  /* reserved / padding */
	__u8    data[CAN_MAX_DLEN] __attribute__((aligned(8)));
};

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

/* special address description flags for the CAN_ID */
// 扩展帧的标识
#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
// 远程帧的标识
#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
// 错误帧的标识,用于错误检查
#define CAN_ERR_FLAG 0x20000000U /* error message frame */

使用 write() 函数和 can_frame 结构体发送数据

struct can_frame frame;  // 声明 can 帧结构体,can_frame 定义在头文件 can.h 中
 
frame.data[0] = 0xFF;  // 要发送的(最多)8个字节的数据
frame.data[1] = 0xFF;
frame.data[2] = 0xFF;
frame.data[3] = 0xFF;
frame.data[4] = 0xFF;
frame.data[5] = 0xFF;
frame.data[6] = 0xFF;
frame.data[7] = 0xFC;
 
/************ 写数据 ************/
frame.can_dlc = 8;  // 设置数据长度(CAN协议规定一帧最多有八个字节的有效数据)
frame.can_id = 1; 	// 设置 ID 号,假设这里 ID 号为1
// 实际的 ID 号要根据是标准帧(11位)还是拓展帧(29)位来设置
// eg: frame.can_id = CAN_EFF_FLAG | 0x1;
write(can_fd, &frame, sizeof(frame));  // 写数据

数据接收

使用 read() 函数和 can_frame 结构体接收数据

struct can_frame frame;   // can_frame 结构体定义在头文件 can.h 中
read(can_fd, &frame, sizeof(frame));  // 读取数据,读取到的有效数据保存在 frame.data[] 数组中

错误处理

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

过滤规则设置

过滤规则使用 can_filter 结构体来实现,定义如下:

/**
 * struct can_filter - CAN ID based filter in can_register().
 * @can_id:   relevant bits of CAN ID which are not masked out.
 * @can_mask: CAN mask (see description)
 *
 * Description:
 * A filter matches, when
 *
 *          <received_can_id> & mask == can_id & mask
 *
 * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
 * filter for error message frames (CAN_ERR_FLAG bit set in mask).
 */
struct can_filter {
	canid_t can_id;
	canid_t can_mask;
};

#define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */
#define CAN_RAW_FILTER_MAX 512 /* maximum number of can_filter set via setsockopt() */

通过这条规则可以在系统中过滤掉所有不符合规则的报文,使得应用程序不需要对无关的报文进行处理。
其中 can_id 的作用是过滤器 filter ,can_mask 用来做 filter 的掩码,匹配过滤器的规则如下:

<received_can_id> & mask == can_id & mask

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

static struct can_filter filterCan0[3] = {
    {0, 0x07FFF800},
    {1, 0x07FFF801},
    {2, 0x07FFF802}
};

setsockopt(_fd0, SOL_CAN_RAW, CAN_RAW_FILTER, filterCan0, 3 * sizeof(struct can_filter ))
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); // 禁用过滤规则

通过错误掩码可以实现对错误帧的过滤, 例如:
can_err_mask_t err_mask = ( CAN_ERR_TX_TIMEOUT | CAN_ERR_BUSOFF );
setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, err_mask, sizeof(err_mask));

回环功能设置

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

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

参考

1、can-utils 工具套件
2、can–测试
3、CAN详解–书籍、网站
4、CAN详解–CAN与com口介绍
5、CAN详解–各家CAN分析仪与软件的比较
6、转载:CAN总线终端电阻
7、如何破解汽车–CAN协议
8、CAN详解–协议详解
9、机器人开发–CanOpen
10、Linux SocketCAN 编程(C++,启用多线程接收)
11、Linux CAN编程详解
12、linux+v2.6.34/Documentation/networking/can.txt
13、tx2 can通信之开机自动加载can模块
14、Linux上使用CAN通信的方法
15、嵌入式Linux中的CAN(FD)总线——驱动配置

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/607504.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3.8 电路布线

博主简介&#xff1a;一个爱打游戏的计算机专业学生博主主页&#xff1a; 夏驰和徐策所属专栏&#xff1a;算法设计与分析 1.最优子结构的证明&#xff1a; 我的理解&#xff1a; 对于电路布线问题的最优子结构性质&#xff0c;我们可以通过数学推导进行证明。下面是对证明的…

conda在 powershell下不能激活虚拟环境

这里写自定义目录标题 问题原因解决办法增加环境变量修改PowerShell 策略初始化conda环境安装或更新conda 结果 问题原因 powershell正常是不行的&#xff0c;但是在cmd中是可以的 问题产生的原因有很多&#xff1a; 必须无法识别activate.bat激活无反应 解决办法 增加环…

【JavaSE】Java基础语法(四十六):枚举

文章目录 1. 概述2. 定义格式3. 枚举的特点4. 枚举的方法 1. 概述 枚举是一种特殊的数据类型&#xff0c;它列出了一组预定义的常量&#xff0c;并使用标识符来引用这些常量。枚举的用途很广泛&#xff0c;下面列举了几个常见的应用场景&#xff1a; 管理常量&#xff1a;如果您…

计算机组成原理---第三章存储系统 习题详解版

&#xff08;一&#xff09;精选课内习题 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 &#xff08;二&#xff09;精选课后习题 1.设有一个具有20位地址和32位字长的存储器&#xff0c;问&#xff1a; (1)该存储器能存储多少个字节的信息&#xff1f; (2)如果存储器由512k8位的SR…

Linux :: vim 编辑器:详解:文本复制/粘贴/剪切/删除 与 撤销普通操作及撤销撤销操作

前言&#xff1a;本篇是 Linux 基本操作篇章的内容&#xff01; 笔者使用的环境是基于腾讯云服务器&#xff1a;CentOS 7.6 64bit。 学习集&#xff1a; C 入门到入土&#xff01;&#xff01;&#xff01;学习合集Linux 从命令到网络再到内核&#xff01;学习合集 前文&#x…

chatgpt赋能python:Python去掉None:提高代码效率,优化SEO

Python去掉None&#xff1a;提高代码效率&#xff0c;优化SEO 作为一名有10年Python编程经验的工程师&#xff0c;我发现Python中会频繁出现None类型的变量。这种情况在代码中一旦过多&#xff0c;就会影响程序的效率&#xff0c;同样也会影响SEO的排名。因此&#xff0c;为提…

【数据仓库架构】什么是 Azure Synapse,它与 Azure Data Bricks 有何不同?

Azure Synapse Analytics 是一项针对大型公司的无限信息分析服务&#xff0c;它被呈现为 Azure SQL 数据仓库 (SQL DW) 的演变&#xff0c;将业务数据存储和宏或大数据分析结合在一起。 在处理、管理和提供数据以满足即时商业智能和数据预测需求时&#xff0c;Synapse 为所有工…

Hive学习---5、文件格式和压缩、企业级调优

1、文件格式和压缩 1.1 Hadoop压缩概述 由于Hive是相当于与Hadoop的客户端&#xff0c;所以hadoop会啥压缩&#xff0c;Hive基本就会啥压缩。 压缩格式算法文件扩展名是否可切分DEFLATEDEFLATE.deflate否GzipDEFLATE.gz否bzip2bzip2.bz2是LZOLZO.lzo是SnappySnappy.snappy否…

word恢复和粘贴按钮变灰色,不可用怎么办?

如果 Word 中的恢复和粘贴按钮变成灰色&#xff0c;可能是由于以下原因之一&#xff1a; 1. 文档处于只读模式。 2. 与 Office 相关的某些组件已损坏或缺失。 3. Word 的文件权限被配置为只读。 以下是一些可能的解决方法&#xff1a; 1. 检查文档是否处于只读模式。 如果是…

随机数发生器设计(三)

随机数发生器设计&#xff08;三&#xff09;- 熵估计和健康测试 熵估计健康测试 熵估计 考虑都熵源的多样性&#xff0c;建立一个通用的熵估计模型比较困难。本文采用nist.sp.800-90B推荐的Markov评估。详见 https://doi.org/10.6028/NIST.SP.800-90B。 执行Markov评估时&am…

chatgpt赋能python:用Python向手机发送信息是如何实现的?

用Python向手机发送信息是如何实现的&#xff1f; 在今天的信息时代&#xff0c;随时随地保持联系已经成为生活不可或缺的一部分。随着技术的发展&#xff0c;我们可以使用各种方式发送和接收信息&#xff0c;而使用Python向手机发送短信是其中一种非常方便的方式。 Python的…

I.MX6ull EPIT定时器

一 简介 EPIT定时器是一种增强的周期中断定时器&#xff0c;完成周期性中断定时的功能。 具有以下特点 EPIT定时器是一个32位的定时器 时钟源可选的向下计数器 EPIT 共有 3 个时钟源可选择&#xff0c;ipg_clk、ipg_clk_32k 和 ipg_clk_highfreq 当计数值和比较值相等的时候…

兼顾性能+实时性处理缓冲数据解决方案

我们经常会遇到这样的数据处理应用场景&#xff1a;我们利用一个组件实时收集外部交付给它的数据&#xff0c;并由它转发给一个外部处理程序进行处理。考虑到性能&#xff0c;它会将数据存储在本地缓冲区&#xff0c;等累积到指定的数量后打包发送&#xff1b;考虑到实时性&…

ChatGPT与软件架构(3) - 软件架构提示工程

高效利用ChatGPT辅助研发的关键是在研发生命周期的不同阶段采用对应提示获取有益的帮助。原文: Leveraging Prompt Engineering in Software Architecture with ChatGPT 软件架构开发生命周期转型。 Beth Smith Unsplash 简介 作为解决方案架构师&#xff0c;有必要掌握软件架构…

【分布式架构】资源与事务:可观测性的基本二重性

西格曼&#xff1a;我叫本西格曼。我是Lightstep的联合创始人兼首席执行官。我在这里讨论的是资源和事务&#xff0c;这是可观察性的一个基本的二元性。我职业生涯的大部分时间都在研究可观察性。在我职业生涯之初&#xff0c;我在谷歌工作了九年&#xff0c;致力于谷歌的分布式…

SLAM实战项目(1) — ORB-SLAM2稠密地图重建

目录 1 整体思路 2 功能实现 3 结果运行 (1) TUM数据集下载 (2) associate.py用于RGB和Depth匹配 (3) 运行数据集 4 CMakeLists.txt文件修改 5 完整PointCloudMapping.h和PointCloudMapping.cc 6 报错分析 7 思考扩展 文章参考部分开源代码和报错文章 1 整体思路 利…

【微信小程序开发】第 3 节 - 安装开发者工具

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、缘起 2、微信开发者工具 3、下载 4、安装 5、扫码登录 6、设置外观和代理 7、总结 1、缘起 开发微信小程序从大的方…

吊打面试官的16000字JVM专属秘籍,又一个Java面试神器!终于可在简历写上精通JVM了!

前言 吊打面试官的16000字JVM专属秘籍&#xff0c;总共包含三部分的内容&#xff0c;从基础到进阶带大家一步步深入理解JVM&#xff01; 学完就可以在简历上面直接写上精通JVM&#xff01; 因为篇幅限制这里只给大家做简单的一个介绍&#xff0c;也就是进行一个大点的梳理&a…

记录--手把手教你Vue+ECharts+高德地图API实现天气预报数据可视化

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 前言 所谓数据可视化&#xff0c;我们可以理解为从宏观角度来看一眼就能看出来整个数据的占比&#xff0c;走向。对于数据可视化&#xff0c;很多互联网公司是很看重这一块的&#xff0c;包括大厂&…

基于wireshark打造安全分析师工具--解析suricata中的分析结果

从本篇文章开始&#xff0c;我将通过若干篇文章陆续介绍在实际安全运营的过程中&#xff0c;基于wireshark打造安全分析师趁手的流量威胁分析工具&#xff0c;帮助安全分析人员在面对网络数据包取证和分析时候达到事半功倍的效果。本篇文件介绍使用在使用iwreshark分析数据包事…