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

相关推荐
m0_547486664 分钟前
计算机网络名词解释汇总
网络·计算机网络
麻瓜也要学魔法6 小时前
链路状态路由协议-OSPF
网络
Estar.Lee6 小时前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
傻啦嘿哟6 小时前
代理IP在后端开发中的应用与后端工程师的角色
网络·网络协议·tcp/ip
湫ccc7 小时前
《Python基础》之字符串格式化输出
开发语言·python
Red Red7 小时前
网安基础知识|IDS入侵检测系统|IPS入侵防御系统|堡垒机|VPN|EDR|CC防御|云安全-VDC/VPC|安全服务
网络·笔记·学习·安全·web安全
mqiqe7 小时前
Python MySQL通过Binlog 获取变更记录 恢复数据
开发语言·python·mysql
AttackingLin7 小时前
2024强网杯--babyheap house of apple2解法
linux·开发语言·python
玛哈特-小易7 小时前
玛哈特矫平机:精密制造中的平整大师
制造·微信公众平台·1024程序员节·矫平机