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代码来观察错误帧,了解了这些知识后就可以随意制造想要的错误帧来做测试,非常方便。

相关推荐
独好紫罗兰5 分钟前
洛谷题单3-P2669 [NOIP 2015 普及组] 金币-python-流程图重构
开发语言·python·算法
跳跳糖炒酸奶9 分钟前
第四章、Isaacsim在GUI中构建机器人(3):添加摄像头和传感器
人工智能·python·算法·ubuntu·机器人
凯强同学17 分钟前
第十四届蓝桥杯大赛软件赛省赛Python 研究生组:4.互质数的个数
python·职场和发展·蓝桥杯
Double Point23 分钟前
(三十三)Dart 中使用 Pub 包管理系统与 HTTP 请求教程
网络·网络协议·http
utmhikari2 小时前
【日常随笔】万字长文,如何用pyside6开发一个python桌面工具
前端·python·pyqt
小杨4044 小时前
python入门系列十四(多进程)
人工智能·python·pycharm
用户277844910499319 小时前
借助DeepSeek智能生成测试用例:从提示词到Excel表格的全流程实践
人工智能·python
JavaEdge在掘金21 小时前
ssl.SSLCertVerificationError报错解决方案
python
我不会编程5551 天前
Python Cookbook-5.1 对字典排序
开发语言·数据结构·python
老歌老听老掉牙1 天前
平面旋转与交线投影夹角计算
python·线性代数·平面·sympy