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

相关推荐
pele8 分钟前
Angular 表单中基于下拉选择动态启用字段必填校验的完整实现
jvm·数据库·python
HHHHH1010HHHHH9 分钟前
Redis怎样判断节点是否主观下线_哨兵基于down-after-milliseconds参数的心跳超时判定
jvm·数据库·python
被摘下的星星20 分钟前
网际协议(IP协议)
网络·tcp/ip
小白学大数据23 分钟前
现代Python爬虫开发范式:基于Asyncio的高可用架构实战
开发语言·爬虫·python·架构
qq_6543669843 分钟前
CSS如何处理@import样式表的嵌套加载_评估递归对加载的影响
jvm·数据库·python
weixin_3812881844 分钟前
苹果微软双修党福音:Navicat如何跨系统平滑迁移配置
jvm·数据库·python
xcbrand1 小时前
政府事业机构品牌策划公司找哪家
大数据·人工智能·python
码界筑梦坊1 小时前
93-基于Python的中药药材数据可视化分析系统
开发语言·python·信息可视化
阿荻在肝了1 小时前
Agent学习六:LangGraph学习-持久化与记忆一
python·学习·agent
qingyulee1 小时前
python多进程、线程、协程
python