CANopen中错误帧的制造和观测

本文讲述如何制造和观察CANopen中的错误帧(Error frame),以Linux下的"VCAN0"为CAN接口来做测试,所以事先要先创建vcan0


一 制造错误帧

首先安装python CAN,

bash 复制代码
pip3 install python-can

然后参考python can的文档编写如下代码,保存为error_frame.py,

python 复制代码
import can

# 连接vcan0
can_bus = can.Bus(channel='vcan0', interface='socketcan')

# 创建错误帧
err_frame = can.Message(arbitration_id=100, is_error_frame=True)

# 打印错误帧
print(err_frame)

# 向vcan0发送错误帧
can_bus.send(err_frame)

# 关闭连接
can_bus.shutdown()

二 观察错误帧

使用candump

candump是用来观察CAN消息的非常方便的工具,安装命令如下,

bash 复制代码
sudo apt install can-utils

通过查看candump的help信息,有如下这段话,

我们平时用candump可能只是执行candump vcan0这样,或者偶尔加个过滤,而其提供的例子里已经告诉我们如何观察错误帧。下面让我们来观察错误帧。

首先打开一个终端,然后执行下面命令,

bash 复制代码
candump any,0~0,#FFFFFFFF

接着打开另外一个终端运行第一节的python脚本,

python 复制代码
python3 error_frame.py

此时可以在candump所在终端观察到如下信息,

使用C代码

下面是一段典型的C代码,

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <linux/can/raw.h>
#include <linux/can/error.h>
#include <linux/can.h>
#include <net/if.h>

int main(void) {
    int s;
    struct sockaddr_can addr;
    struct ifreq ifr;
    struct can_frame frame;

    // 创建套接字
    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (s == -1) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 设置CAN设备
    strcpy(ifr.ifr_name, "vcan0"); // 使用vcan0作为设备名
    ioctl(s, SIOCGIFINDEX, &ifr);

    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));


    // 绑定套接字到CAN设备
    memset(&addr, 0, sizeof(addr));
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
        perror("Bind failed");
        close(s);
        exit(EXIT_FAILURE);
    }

    // 接收数据
    while (1) {
        int len = recvfrom(s, &frame, sizeof(frame), 0, NULL, NULL);
        if (len > 0) {
            // 检查是否为错误帧
            if ((frame.can_id & CAN_ERR_FLAG) != 0) {
                printf("Error Frame received!\n");
            } else {
                printf("Standard Frame: ID=0x%03X DLC=%d\n", frame.can_id & CAN_SFF_MASK, frame.can_dlc);
                for(int i = 0; i < frame.can_dlc; i++) {
                    printf("%02X ", frame.data[i]);
                }
                printf("\n");
            }
        }
    }

    close(s); // 不会执行到这里,因为上面的循环是无限的
    return 0;
}

代码里使用setsockopt()设置了观察的错误帧类型,即CAN_ERR_TX_TIMEOUT 和CAN_ERR_BUSOFF,意思就是出现这2种错误帧才会去处理,这2个宏定义的值分别是0x1和0x40,而前面python脚本里的设置错误帧id是0x64,与0x40相与后不是0,所以会被认为是CAN_ERR_BUSOFF

编译这段C代码,然后运行,接着执行python脚本,这样就可以在C程序这边观察到打印,

可以试着把python脚本里的id改成别的值,可以不触发错误帧检测。


三 小结

本文讲述如何使用python can来制造错误帧,以及如何使用candump和C代码来观察错误帧,了解了这些知识后就可以随意制造想要的错误帧来做测试,非常方便。

相关推荐
whcyhhh16 分钟前
头歌实践教学平台:数据科学与大数据技术导论(十六)
大数据·开发语言·python
宸津-代码粉碎机19 分钟前
AI工程化高阶实战|从Demo到生产落地核心架构、全套源码与避坑指南
java·大数据·开发语言·人工智能·python·架构
Zenova EdgeOS1 小时前
工业网关心跳机制:从 Keepalive 到健康判定的工程实战
大数据·网络·数据库·边缘计算·工业网关
郝学胜-神的一滴1 小时前
Effective Python 条款4:字符串格式化大乱斗
开发语言·网络·python·程序人生·软件工程
ynchyong2 小时前
Python 字符组合生成器:product 与 permutations 的实战对比
python·工具·字符串生产
benchmark_cc2 小时前
1000只ETF的5分钟K线如何批量获取?QuantDash分页策略与高性能Python实践
开发语言·人工智能·爬虫·python·算法·quantdash·量化数据源
sel_92 小时前
【PEFT】参数高效微调(PEFT)技术详解:从原理到 LoRA/QLoRA 实战
人工智能·python·深度学习·算法·机器学习·参数高效微调
月光船幽幽2 小时前
带刺反馈引擎:唤醒深层意图
人工智能·python
云絮.2 小时前
网络编程套接字
网络
大模型码小白3 小时前
AI 提示词专栏:使用系统指令(System Prompt)实现全局约束
java·大数据·运维·开发语言·人工智能·python·prompt