Linux下的CAN通讯

CAN总线


CAN总线简介

CAN(Controller Area Network)总线是一种多主从式 <font color = red>异步半双工串行 </font> 通信总线,它最早由Bosch公司开发,用于汽车电子系统。CAN总线具有以下特点:

  • 多主从式:CAN总线允许多个节点同时进行通信,每个节点都可以发送和接收数据。
  • 工作频率:CAN总线的工作频率通常为40kHz到1MHz,具体取决于应用场景。
  • 通信距离:CAN总线可以在不同的通信距离下工作,最长可达1公里。
  • 通信速率:CAN总线支持多种通信速率,从10kbps到1Mbps不等。高速CAN的通信速率为125kbps到1Mbps。低速CAN的通信速率为低于125kbps。

CAN的硬件连接

1726464274793

一般没有can控制器的设备,可以靠使用SPI转CAN模块,再外接CAN收发器,实现can的数据收发

1726464704534

CAN总线两端的120欧姆为终端电阻,是为了消除总线上的信号反射

电器属性

1726464469095

在高速 CAN中:

  • 当 CANH 和 CANL 电压相同 (CANH= CANL=2.5V) 时为逻辑“1”(隐形状态)
  • CANH 和 CANL 电压相差 2V (CANH=3.5V,CANL= 1.5V) 时为逻辑“0”(显性状态)。

CAN协议

缩写含义解释
SOF(strat offrame):帧起始。表示一帧数据的起始
ID(identify):标识符
RTR(remote transmission request):远程请求标志位
IDE(identify extension):扩展标志位
SRR(substitute remote request):替代远程请求标志位
R0/R1(reserve):保留位
DLC(date length code) :表示数据字段有多少个字节
CRC(cyclic redundancy check):CRC校验
ACK(acknowledge):应答
EOF(end offrame):帧结束。表示一帧数据结束

1.数据帧

can通信是通过数据帧进行发送数据的,所以数据帧是:数据帧携带数据从发送设备到接收设备

1.2.数据帧格式

数据帧有 标准数据帧扩展数据帧

1.3.1标准数据帧格式

1726465394762

标准数据帧格式分析:

1726465435459

can的空闲电平是1(高电平,隐性),所以起始帧是0(低电平,显性)

  1. 帧起始和帧结束
    帧起始和帧结束表示一帧数据的起始和结束,帧起始由 1 个显性位组成,结束由 7 个连续
    的隐形位组成。
  2. 仲裁字段
    仲裁字段包括 11位ID 位,1位 RTR 位,共 12 位。D 位用可以用来区分数据的功能(不
    司功能的报数据帧,ID 是不同的),也可以用来区分优先级。根据仲裁规则,ID 小的数据帧
    优先发送。禁止高 7 位都为隐性(禁止设定: ID=1111111xXXX)。
    RTR 是远程请求标志位,用于区分数据帧还是遥控帧。数据帧 RTR 位必须为显性 0,遥控
    必须位隐性 1。(相同ID的数据和遥控,数据的优先级大干遥控帧)。
  3. 控制字段
    控制字段由 1位IDE 位,1位 RO 保留位,4 位 DLC共6 位组成。
  • IDE 位表示数据帧是标准数据帧还是扩展数组帧,标准格式固定为显示0,扩展格式固定为
    隐性 1。
  • RO 保留位,固定为显示 0。
  • DLC 位表示数据字段的数据字节数(数据段的长度)。
  1. 数据字段
    可以承载 0 到 64 位数据。
  2. CRC 校验字段
    CRC 校验字段由 15 位校验位和 1位 CRC 界定字符组成,前 15 位用于 CRC 校验。CRC 界定符
    必须为隐性 1
  3. ACK 字段
    ACK 字段由确定间隙位和确认界定符组成,确认界定符必须是隐性 1。

1.3.2扩展数据帧格式

1726486254683

相比于标准帧格式,扩展帧多了一个扩展ID,扩展ID由29位组成,标准帧的ID由11位组成
SRR替换了原有的RTR,IDE为扩展帧的标识符(低电平0),外加了18为扩展ID,其他的并无异样

2.遥控帧

遥控帧用于接收设备主动请求数据。发送方通过广播的形式发送数据,数据帧中通过ID 区分不同功能的数据帧,如果发送方没有广播这个数据,接收方可以广播发送一个遥控帧,有接收方想要的数据的发送方就会广播这个数据出来。接收方就可以接收到这个数据了。

1726486647771

2.1 遥控帧格式

数据帧去掉数据段就是遥控帧,所以遥控帧也有两种帧格式

1726486841125

3.错误帧

在发送或者接收时,总线上的设备发生错误的时候,可以通过发送错误帧的方式告知其他节点发生了错误。错误帧由俩个部分组成,分别是错误标志和错误界定符。错误标志:

  • 主动错误标志:6 个连续显性位
  • 被动错误标志:6 个连续隐性位
    错误界定符:8 个连续隐性位

1726487041603

4.过载帧

当某个接收节点没有做好接收下一帧数据的准备时,接收方将发送过载帧通知发送节点节点最多可产生俩条连续的过载顺来延迟一下次发送。过载标志的构成与主动错误标志的构成相同,过载界定符的构成与错误界定符的构成相同。

  • 过载标志:6个位的显行
  • 过载界定符:8个位的隐行

1726487097242

5.帧间隔

帧间隔是用于分隔数据帧和遥控帧的帧。数据帧和遥控帧可通过插入帧间隔将本帧与前面的任何帧(数据帧、遥控帧、错误帧、过载帧) 分开。
过载帧和错误帧前不能插入帧间隔。

1726487216832

6.位填充

CAN 总线上的数据是按照位来传输的,为了保证数据传输的可靠性,CAN 总线对数据进行了位填充。位填充是指在数据传输过程中,如果连续 5 个位都是显性位,那么就会插入一个隐形位。如果连续 5 个位都是隐形位,那么就会插入一个显性位。

1726487436502

仲裁机制

CAN 总线是一种多主从式总线,多个节点可以同时发送数据。为了防止多个节点同时发送数据导致冲突,CAN 总线采用了仲裁机制。仲裁机制是通过比较各个节点的 ID 来决定哪个节点可以发送数据。ID 小的节点优先发送数据。如果多个节点同时发送数据,那么 ID 小的节点会优先发送数据,其他节点会停止发送数据并进入监听状态,等待 ID 小的节点发送完数据后再发送数据。

在总线空闲态,最先开始发送消息的单元获得发送权。多个单元同时开始发送时,各发送单元从仲裁段的第一位开始进行仲裁。连续输出显性电平最多的单元可继续发送。
主要通过以下方法:

  1. 非破坏性仲裁:显性优先,即显性优先级大于隐性优先级(线与机制: 只有所有节点都发送隐性 1 时,总线才为 1,只要有一个节点发送显性 0,则总线就为显性 0)
  2. 载波侦听: 总线上各个节点在发送数据前要侦听总线的状态,只有在总线是空闲状态时才允许发送。
  3. 回读:节点在发送数据时要不停的检测要发送的数据。通过非破坏性仲裁判断是否与其他节点的数据发生冲突。

CAN的应用工具

iproute2 工具移植

下载路径:
https://mirrors.edge.kernel.org/pub/linux/utils/net/iproute2/

./configure
make CC=arm-linux-gcc
make install

CAN是作为网络设备存在的,所以查看CAN设备:

ifconfig -a

启动:

# 设置波特率
ip link set can0 type can bitrate 500000 
# 启动can0设备
ifconfig can0 up

CAN的应用编程

1726560568299

CAN被规划为网络设备,所以在通信中使用的是socket编程。

int sokcet(int domain, int type, int protocol);
参数解释
domain:协议域,通常为PF_CAN
type:指定协议类型,SOCK_RAW表示原始套接字,SOCK_DGRAM表示数据报套接字
protocol:指定协议,通常为CAN_RAW或CAN_BCM

domain的常用协议族:

  • PF_UNIX, PF_LOCAL: 本地通信
  • PF_INET: IPv4网络通信
  • PF_INET6: IPv6网络通信
  • PF_NETLINK: 内核套接字,
  • PF_CAN: CAN网络通信

type的常用协议类型:

  • SOCK_STREAM:面向连接、可靠的、双向的、基于字节流的通数据按顺序传输,不会丢失或重复。通常用于TCP 协议
  • SOCK_DGRAM:支持无连接、不可靠的、固定最大长度的消息据报传输。消息可能会丢失、重复或乱序。通常用于 UDP 协议
  • SOCK SEQPACKET:提供面向连接、可靠的、双向的、基于固定最度数据报的通信,接收者必须每次系统调用读个数据包
  • SOCK RAW:对原始网络协议的访问,允许应用程序直接发接收 IP 层的数据包,绕过传输层协议
  • SOCK RDM:提供一种可靠的数据报层,但不保证顺序
  • SOCK PACKET:提供对底层网络协议的直接访问,通常用于与设备驱动程序的通信
  • SOCK NONBLOCK:新打开的文件描述符的非阻塞标志
  • SOCK CLOEXEC:新文件描述符的在执行时关闭 (FD CLOEXEC)如果程序执行了一个新的程序,这个文件描将会被关闭,这有助于防止文件泄露到不受信程序中

SOURCE CODE

send CAN data:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
#include <sys/ioctl.h>int main(int argc, char *argv[]){int s = socket(AF_CAN, SOCK_RAW, CAN_RAW); // Create  CAN socketif(s < 0){printf("Error creating socket\n");return 1;}struct ifreq ifr; // Interface requeststrcpy(ifr.ifr_name, "can0"); // CAN interface nameif(ioctl(s, SIOCGIFINDEX, &ifr) < 0){ // Get CAN interface indexprintf("Error getting interface index\n");}struct sockaddr_can addr; // CAN socket addressaddr.can_family = AF_CAN;addr.can_ifindex = ifr.ifr_ifindex; // CAN interface index (0 for first interface)if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0){printf("Error binding socket\n");return 1;}struct can_frame frame[3]; // CAN frame 标准帧frame[0].can_id = 0x123; // CAN IDframe[0].can_dlc = 8; // Data length codefor(int i = 0; i < 8; i++){frame[0].data[i] = i; // Data}if(send(s, &frame[0], sizeof(frame[0]), 0) < 0){printf("Error sending frame\n");return 1;}frame[1].can_id = 0x456 | CAN_EFF_FLAG; // CAN ID with EFF flag 扩展帧frame[1].can_dlc = 2; // Data length codeframe[1].data[0] = 0x12;frame[1].data[1] = 0x34;if(send(s, &frame[1], sizeof(frame[1]), 0) < 0){printf("Error sending frame\n");return 1;}frame[2].can_id = 0x789 | CAN_RTR_FLAG; // CAN ID with RTR flag 远程帧frame[2].can_dlc = 0; // Data length codeif(send(s, &frame[2], sizeof(frame[2]), 0) < 0){printf("Error sending frame\n");return 1;}close(s);return 0;
}

recv CAN data:

  • 在接收时可以配置过滤规则,只接收符合过滤条件的帧。
 /* 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 */**/* valid bits in CAN ID for frame formats */#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */*

在配置时只需记得后缀为FLAG是要过滤的帧,后缀为MASK是要接收的帧。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
#include <sys/ioctl.h>int main(int argc, char *argv[]){int s = socket(AF_CAN, SOCK_RAW, CAN_RAW); // Create  CAN socketif(s < 0){printf("Error creating socket\n");return 1;}struct ifreq ifr; // Interface requeststrcpy(ifr.ifr_name, "can0"); // CAN interface nameif(ioctl(s, SIOCGIFINDEX, &ifr) < 0){ // Get CAN interface indexprintf("Error getting interface index\n");}struct sockaddr_can addr; // CAN socket addressaddr.can_family = AF_CAN;addr.can_ifindex = ifr.ifr_ifindex; // CAN interface index (0 for first interface)if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0){printf("Error binding socket\n");return 1;}struct can_frame frame; // CAN framechar buff[1024];struct can_filter filter[2]; // CAN filter 设置两条过滤规则// 设置过滤规则,只接收ID为0x123的标准帧filter[0].can_id = 0x123; // Filter IDfilter[0].can_mask = CAN_SFF_MASK; // Filter mask// 设置过滤规则,只接收ID为0x456的扩展帧和标准帧,但不要远程帧filter[1].can_id = 0x123; // Filter IDfilter[1].can_mask = CAN_SFF_MASK | CAN_EFF_MASK | CAN_RTR_FLAG; // Filter masksetsockopt(s,SOL_CAN_RAW, CAN_RAW_FILTER, &filter, sizeof(filter)); // 设置过滤规则while (1){int ret = read(s, &frame, sizeof(frame)); // Read CAN frameif(ret < 0){printf("Error reading frame\n");return 1;}else{if(frame.can_id & CAN_EFF_FLAG){printf("Extended ID: %x\n", frame.can_id & CAN_EFF_MASK);}else{printf("Standard ID: %x\n", frame.can_id & CAN_SFF_MASK);}printf("Data: ");for(int i = 0; i < frame.can_dlc; i++){printf("%02x ", frame.data[i]);}if(frame.can_id && CAN_RTR_FLAG){printf("Remote Transmission Request\n");}}}close(s);return 0;
}

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

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

相关文章

解决使用阿里云DataV Geo在线地图路径访问403问题

文章目录 1. DataV Geo在线地图路径访问403问题2. 解决方法3. 重启生效 1. DataV Geo在线地图路径访问403问题 最近在写一个省市下钻的demo&#xff0c;用到的是 阿里云DataV Geo在线地图 去动态获取GeoJSON 省市的数据&#xff0c;如下代码 axios.get("https://geo.dat…

Golang | Leetcode Golang题解之第414题第三大的数

题目&#xff1a; 题解&#xff1a; func thirdMax(nums []int) int {var a, b, c *intfor _, num : range nums {num : numif a nil || num > *a {a, b, c &num, a, b} else if *a > num && (b nil || num > *b) {b, c &num, b} else if b ! ni…

马匹行为识别系统源码分享

马匹行为识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

C语言程序设计(进阶)

行到水穷处&#xff0c;坐看云起时。 中秋快乐呀&#xff01; 数据在内存中的存储 1.数据类型的介绍 &#xff08;1&#xff09;基本的内置类型&#xff1a; char //字符数据类型 short //短整型 int //整型 long //长整型 …

说一说Zookeeper的应用场景及其原理

一 ZooKeeper简介 ZooKeeper是一个分布式的&#xff0c;开放源码的分布式应用程序协调服务&#xff0c;是Google的Chubby一个开源的实现&#xff0c;是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件&#xff0c;提供的功能包括&#xff1a;配置维护、域名…

K8S - Access Control 机制介绍

作为开发人员&#xff0c; 我们通常会直接用root 帐号操作 k8s master node 里的kubectl 命令&#xff0c;并不能感知k8s 多用户权限管理存在。 即使自动化&#xff0c; 我们也会考虑用ansible 来远程操作master node… 所以大部分开发人员默认上是不用深入研究k8s的Access c…

基于AlexNet实现猫狗大战

卷积神经网络介绍 卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;简称CNN&#xff09;&#xff0c;是一种深度学习模型&#xff0c;特别适用于处理图像、视频等数据。它的核心思想是利用卷积层&#xff08;Convolutional layers&#xff09;来提取输入数据…

[C语言]连子棋游戏

文章目录 一、前言二、游戏思路三、游戏方法1、初始化2、判断胜利3、交互4、电脑下棋 四、核心方法说明1、初始化游戏2、销毁棋盘3、显示游戏4、电脑下棋5、用户下棋6、判断游戏状态7、游戏交互 五、游戏效果展示与源码分享1、游戏效果2、源代码 一、前言 对于指针和数组理解尚…

关于std::swap原理

swap 操作交换两个相同类型容器的内容。调用swap之后&#xff0c;两个容器中的元素将会 交换&#xff1a; vector<striong> svec1(10); //10个元素的vector vector<string> svec2(24); //24个元素的vector swap(svec1,svec2); 调…

C++ | Leetcode C++题解之第413题等差数列划分

题目&#xff1a; 题解&#xff1a; class Solution { public:int numberOfArithmeticSlices(vector<int>& nums) {int n nums.size();if (n 1) {return 0;}int d nums[0] - nums[1], t 0;int ans 0;// 因为等差数列的长度至少为 3&#xff0c;所以可以从 i2 开…

一款免费开源且功能强大的思维导图软件-思绪思维导图

思绪思维导图是一款免费开源的思维导图软件&#xff0c;旨在帮助用户有效地组织和表达思想。它提供了丰富的功能&#xff0c;包括支持富文本、图片、图标、超链接、备注、标签等内容&#xff0c;以及关联线、概要等特性。 思绪思维导图下载&#xff1a;https://pan.quark.cn/s…

在STM32工程中使用Mavlink与飞控通信

本文讲述如何在STM32工程中使用Mavlink协议与飞控通信&#xff0c;特别适合自制飞控外设模块的项目。 需求来源&#xff1a; 1、增稳云台里的STM32单片机需要通过串口接收飞控传来的云台俯仰、横滚控制指令和相机拍照控制指令&#xff1b; 2、自制的有害气体采集器需要接收飞…

基于Springboot的医疗健康助手开题报告

文未可获取一份本项目的java源码和数据库参考。 一&#xff0e;选题意义, 研究现状,可行性分析 选题意义&#xff1a;随着科技的高速发展&#xff0c;人们的生活水平也正在稳步提高&#xff0c;解决温饱问题以后&#xff0c;广大人民群众也越来越注重自己的身体健康&#xff0…

[Redis][前置知识][下][高并发架构演进]详细讲解

目录 1.单机架构2.应⽤数据分离架构3.应⽤服务集群架构4.读写分离/主从分离架构5.引⼊缓存⸺冷热分离架构6.垂直分库/分表7.业务拆分⸺微服务8.总结 1.单机架构 只有一台服务器&#xff0c;这个服务器负责所有的工作 大部分公司的产品&#xff0c;都是这种单机架构 2.应⽤数…

自己建网站怎么建

自己建立一个网站可能听起来有点复杂&#xff0c;但实际上&#xff0c;有很多简单且免费的方法可以实现。下面将介绍一些基本步骤&#xff0c;帮助你开始自己建立一个网站。 首先&#xff0c;你需要明确你的网站目的是什么。是个人博客、商业网站&#xff0c;还是其他类型的网…

frp内网穿透功能使用教程

frp 是一款高性能的反向代理应用&#xff0c;专注于内网穿透。它支持多种协议&#xff0c;包括 TCP、UDP、HTTP、HTTPS 等&#xff0c;并且具备 P2P 通信功能。使用 frp&#xff0c;您可以安全、便捷地将内网服务暴露到公网&#xff0c;通过拥有公网 IP 的节点进行中转。 文档地…

深度学习----------------------文本预处理

目录 文本预处理读取数据集词源化词表该部分总代码该部分总代码 整合所有功能该部分总代码 文本预处理 文本预处理&#xff1a;把文本当作一个时序序列 将解析文本的常见预处理步骤。 这些步骤通常包括&#xff1a; ①将文本作为字符串加载到内存中。 ②将字符串拆分为词元&…

【数据结构篇】~链表算法题3(环形链表)

链表算法题3&#xff08;环形链表&#xff09; 环形链表的证明1. 环形链表I​1) 思路2&#xff09;代码实现 2. 环形链表II​1) 思路11) 思路22&#xff09;代码实现 环形链表的证明 1. 环形链表I​ https://leetcode.cn/problems/linked-list-cycle/description/ 1) 思路 判断…

Nginx搭建直播服务器,并用rtmp,http-flv,hls三种模式拉流观看直播的流程

一、首先搭建直播服务器 环境widows&#xff0c;并且已经集成了 &#xff1a;nginx-http-flv-module模块 nginx.conf配置如下&#xff1a; worker_processes 1;#error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #error…

计算机人工智能前沿进展-大语言模型方向-2024-09-15

计算机人工智能前沿进展-大语言模型方向-2024-09-15 1. Towards the holistic design of alloys with large language models Z Pei, J Yin, J Neugebauer, A Jain - Nature Reviews Materials, 2024 利用大型语言模型实现合金的全面设计 摘要 文章讨论了大型语言模型在材料…