SocketCAN编程揭秘:Linux下CAN设备的高效数据收发与错误处理

SocketCan 应用编程 由于 Linux 系统将 CAN 设备作为网络设备进行管理,因此在 CAN 总线应用开发方面,Linux 提供了SocketCAN 应用编程接口,使得 CAN 总线通信近似于和以太网的通信,应用程序开发接口更加通用,也更加灵活。SocketCAN 中大部分的数据结构和函数在头文件 linux/can.h 中进行了定义,所以,在我们的应用程序中一定要包含头文件。 阅读详情

SocketCAN编程实战:Linux下高效数据收发与错误处理深度解析

引言

在嵌入式系统和汽车电子领域,CAN总线作为可靠的多主通信协议已经广泛应用超过30年。Linux系统通过SocketCAN子系统将CAN设备抽象为网络接口,为开发者提供了类似TCP/IP的编程接口。这种设计不仅简化了CAN应用的开发流程,还使得传统网络编程经验能够直接迁移到CAN总线开发中。无论是车载诊断系统、工业控制网络还是机器人通信,SocketCAN都展现出强大的灵活性和稳定性。本文将深入探讨SocketCAN的核心机制,从基础配置到高级错误处理,为开发者提供全面实用的技术指南。

1. SocketCAN环境配置与设备初始化

1.1 内核模块加载与接口配置

现代Linux内核通常已经内置了SocketCAN支持,但需要手动加载相关模块。对于大多数CAN控制器,首先需要加载can和can_raw模块:

sudo modprobe can
sudo modprobe can_raw

对于特定的CAN控制器驱动,如使用SJA1000芯片的设备:

sudo modprobe sja1000
sudo modprobe sja1000_isa io=0x300 irq=7

配置CAN接口参数是确保稳定通信的关键步骤。使用iproute2工具集可以方便地设置CAN接口:

sudo ip link set can0 type can bitrate 500000 sample-point 0.875
sudo ip link set can0 up

这里的bitrate设置为500kbps,这是工业控制中常用的速率,sample-point设置为87.5%能够优化总线时序容限。

1.2 硬件自检与状态监控

在正式通信前,建议对CAN接口进行健康状态检查:

ip -details link show can0

输出应类似:

3: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
    link/can  promiscuity 0 
    can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0 
    bitrate 500000 sample-point 0.875
    tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
    sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
    clock 8000000

重点关注can state应为ERROR-ACTIVE,且错误计数器(tx和rx)应为0或接近0。如果出现ERROR-PASSIVE或BUS-OFF状态,需要检查物理连接和终端电阻配置。

2. 核心编程接口与数据帧处理

2.1 Socket创建与绑定机制

SocketCAN使用标准BSD socket接口,但协议族指定为PF_CAN:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>

int create_can_socket(const char *ifname) {
    int s;
    struct sockaddr_can addr;
    struct ifreq ifr;
    
    /* 创建CAN RAW套接字 */
    if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
        perror("Socket creation failed");
        return -1;
    }
    
    /* 指定CAN接口 */
    strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
    ioctl(s, SIOCGIFINDEX, &ifr);
    
    /* 绑定到指定接口 */
    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);
        return -1;
    }
    
    return s;
}

注意:在多线程环境中,每个线程应创建自己的socket实例,避免共享socket导致的竞态条件。

2.2 数据帧构造与发送优化

CAN数据帧使用struct can_frame结构体封装:

struct can_frame {
    canid_t can_id;  /* 32位CAN ID + EFF/RTR/ERR标志 */
    __u8    can_dlc; /* 数据长度(0-8) */
    __u8    __pad;   /* 填充 */
    __u8    __res0;  /* 保留 */
    __u8    __res1;  /* 保留 */
    __u8    data[8] __attribute__((aligned(8))); /* 数据 */
};

高效的数据发送需要考虑总线负载和优先级。以下示例演示了带错误重传机制的发送函数:

int send_can_frame(int sock, struct can_frame *frame, int max_retries) {
    int ret;
    int retries = 0;
    
    while (retries <= max_retries) {
        ret = write(sock, frame, sizeof(struct can_frame));
        if (ret == sizeof(struct can_frame)) {
            return 0; /* 发送成功 */
        }
        
        if (errno == ENOBUFS) {
            /* 缓冲区满,短暂延迟后重试 */
            usleep(1000);
            retries++;
        } else {
            perror("CAN send error");
            return -1;
        }
    }
    
    fprintf(stderr, "CAN发送失败,超过最大重试次数%d\n", max_retries);
    return -1;
}

2.3 接收处理与性能优化

高效接收需要结合非阻塞IO和多路复用技术:

void can_receiver_loop(int sock) {
    struct can_frame frame;
    fd_set readfds;
    int nbytes;
    int max_fd = sock + 1;
    
    while (1) {
        FD_ZERO(&readfds);
        FD_SET(sock, &readfds);
        
        /* 设置1秒超时 */
        struct timeval timeout = {1, 0};
        
        int activity = select(max_fd, &readfds, NULL, NULL, &timeout);
        
        if (activity < 0) {
            perror("select error");
            continue;
        }
        
        if (activity == 0) {
            /* 超时,可在此处执行其他任务 */
            continue;
        }
        
        if (FD_ISSET(sock, &readfds)) {
            nbytes = read(sock, &frame, sizeof(struct can_frame));
            if (nbytes < 0) {
                perror("CAN read error");
                continue;
            }
            
            if (nbytes < sizeof(struct can_frame)) {
                fprintf(stderr, "读取不完整CAN帧: %d bytes\n", nbytes);
                continue;
            }
            
            process_can_frame(&frame); /* 处理接收到的帧 */
        }
    }
}

3. 高级过滤与错误处理机制

3.1 硬件过滤规则配置

SocketCAN支持在内核层面设置过滤规则,大幅减少用户空间的处理开销:

/* 设置只接收特定ID范围的帧 */
void setup_can_filters(int sock) {
    struct can_filter rfilter[4];
    
    /* 只接收ID为0x100-0x103的标准数据帧 */
    rfilter[0].can_id = 0x100;
    rfilter[0].can_mask = 0x7F0; /* 匹配前7位 */
    
    rfilter[1].can_id = 0x101;
    rfilter[1].can_mask = 0x7F0;
    
    rfilter[2].can_id = 0x102;
    rfilter[2].can_mask = 0x7F0;
    
    rfilter[3].can_id = 0x103;
    rfilter[3].can_mask = 0x7F0;
    
    setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FILTER, 
               &rfilter, sizeof(rfilter));
}

/* 禁用所有接收,仅发送模式 */
void disable_can_reception(int sock) {
    setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
}

3.2 错误帧检测与处理

CAN总线提供了完善的错误检测机制,SocketCAN允许应用程序接收和处理错误帧:

void enable_error_frames(int sock) {
    int recv_own_msgs = 0; /* 禁用接收自身发送的帧 */
    can_err_mask_t err_mask = CAN_ERR_MASK;
    
    setsockopt(sock, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
               &recv_own_msgs, sizeof(recv_own_msgs));
    
    setsockopt(sock, SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
               &err_mask, sizeof(err_mask));
}

/* 错误帧处理函数 */
void handle_error_frame(struct can_frame *frame) {
    if (frame->can_id & CAN_ERR_FLAG) {
        printf("检测到错误帧: 0x%08X\n", frame->can_id);
        
        if (frame->can_id & CAN_ERR_CRTL) {
            printf("控制器错误: ");
            if (frame->data[1] & CAN_ERR_CRTL_RX_OVERFLOW)
                printf("RX缓冲区溢出 ");
            if (frame->data[1] & CAN_ERR_CRTL_TX_OVERFLOW)
                printf("TX缓冲区溢出 ");
            printf("\n");
        }
        
        if (frame->can_id & CAN_ERR_PROT) {
            printf("协议违例: ");
            if (frame->data[2] & CAN_ERR_PROT_BIT)
                printf("位错误 ");
            if (frame->data[2] & CAN_ERR_PROT_FORM)
                printf("格式错误 ");
            if (frame->data[2] & CAN_ERR_PROT_STUFF)
                printf("位填充错误 ");
            printf("\n");
        }
        
        if (frame->can_id & CAN_ERR_BUSOFF) {
            printf("总线关闭状态\n");
            /* 需要手动重启CAN控制器 */
        }
    }
}

3.3 总线状态监控与恢复

实现自动总线状态监控和恢复机制:

typedef struct {
    int tx_errors;
    int rx_errors;
    int bus_off_count;
} can_bus_stats_t;

void monitor_bus_status(int sock, can_bus_stats_t *stats) {
    struct can_frame frame;
    int nbytes;
    
    while (1) {
        nbytes = read(sock, &frame, sizeof(struct can_frame));
        if (nbytes != sizeof(struct can_frame))
            continue;
            
        if (frame.can_id & CAN_ERR_FLAG) {
            if (frame.can_id & CAN_ERR_CRTL) {
                stats->tx_errors = frame.data[6];
                stats->rx_errors = frame.data[7];
            }
            
            if (frame.can_id & CAN_ERR_BUSOFF) {
                stats->bus_off_count++;
                printf("总线关闭检测到,尝试自动恢复...\n");
                
                /* 执行自动恢复流程 */
                if (auto_recover_bus(sock) == 0) {
                    printf("总线恢复成功\n");
                } else {
                    printf("总线恢复失败,需要人工干预\n");
                }
            }
        }
        
        /* 定期报告状态 */
        static time_t last_report = 0;
        time_t now = time(NULL);
        if (now - last_report >= 5) {
            printf("TX错误: %d, RX错误: %d, 总线关闭次数: %d\n",
                   stats->tx_errors, stats->rx_errors, stats->bus_off_count);
            last_report = now;
        }
    }
}

4. 实时性能优化与多线程处理

4.1 优先级调度与实时性保证

对于要求严格实时性的应用,需要配置线程调度策略:

#include <sched.h>

void set_realtime_priority(void) {
    struct sched_param param;
    
    param.sched_priority = sched_get_priority_max(SCHED_FIFO);
    if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
        perror("警告: 无法设置实时优先级,需要root权限");
        /* 降级到普通优先级 */
        param.sched_priority = 0;
        sched_setscheduler(0, SCHED_OTHER, &param);
    }
}

/* 内存锁定,避免页面交换延迟 */
void lock_memory(void) {
    if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
        perror("mlockall failed");
    }
}

4.2 多线程架构设计

合理的多线程设计可以充分利用多核处理器:

typedef struct {
    int can_sock;
    pthread_mutex_t tx_mutex;
    ring_buffer_t *rx_queue;
    ring_buffer_t *tx_queue;
} can_context_t;

void *can_tx_thread(void *arg) {
    can_context_t *ctx = (can_context_t *)arg;
    struct can_frame frame;
    
    set_realtime_priority();
    
    while (1) {
        if (ring_buffer_dequeue(ctx->tx_queue, &frame, sizeof(frame)) == 0) {
            pthread_mutex_lock(&ctx->tx_mutex);
            send_can_frame(ctx->can_sock, &frame, 3);
            pthread_mutex_unlock(&ctx->tx_mutex);
        } else {
            /* 队列空,短暂休眠 */
            usleep(1000);
        }
    }
    return NULL;
}

void *can_rx_thread(void *arg) {
    can_context_t *ctx = (can_context_t *)arg;
    struct can_frame frame;
    fd_set readfds;
    
    while (1) {
        FD_ZERO(&readfds);
        FD_SET(ctx->can_sock, &readfds);
        
        struct timeval timeout = {0, 1000}; /* 1ms超时 */
        
        if (select(ctx->can_sock + 1, &readfds, NULL, NULL, &timeout) > 0) {
            if (FD_ISSET(ctx->can_sock, &readfds)) {
                ssize_t nbytes = read(ctx->can_sock, &frame, sizeof(frame));
                if (nbytes == sizeof(frame)) {
                    ring_buffer_enqueue(ctx->rx_queue, &frame, sizeof(frame));
                }
            }
        }
    }
    return NULL;
}

4.3 零拷贝优化技术

对于高性能应用,可以考虑使用零拷贝技术减少数据复制:

/* 使用CAN_RAW_FD_FRAMES选项支持FD帧 */
void enable_can_fd(int sock) {
    int enable = 1;
    setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &enable, sizeof(enable));
}

/* 使用内存映射IO进行高效数据交换 */
int setup_mmap_io(int sock, void **tx_buf, void **rx_buf) {
    /* 获取socket发送缓冲区大小 */
    int sndbuf_size;
    socklen_t len = sizeof(sndbuf_size);
    getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sndbuf_size, &len);
    
    /* 创建内存映射区域 */
    *tx_buf = mmap(NULL, sndbuf_size, PROT_READ|PROT_WRITE, 
                  MAP_SHARED|MAP_ANONYMOUS, -1, 0);
    *rx_buf = mmap(NULL, sndbuf_size, PROT_READ|PROT_WRITE, 
                  MAP_SHARED|MAP_ANONYMOUS, -1, 0);
                  
    if (*tx_buf == MAP_FAILED || *rx_buf == MAP_FAILED) {
        perror("mmap failed");
        return -1;
    }
    
    return 0;
}

在实际项目中,SocketCAN的性能优化需要根据具体应用场景进行权衡。高吞吐量应用应优先考虑零拷贝和适当的过滤规则,而低延迟应用则需要关注实时性配置和高效的线程架构。通过合理组合这些技术,可以在Linux平台上构建出高性能、高可靠性的CAN总线应用系统。

CAN Linux C应用编程 阅读详情

相关推荐

CAN总线数据收发实战:从SocketCAN工具到协议帧解析

本文详细介绍了CAN总线数据收发的实战操作,从SocketCAN环境搭建到协议帧解析,涵盖了基础数据收发、高级过滤技巧、帧结构解剖及常见问题排查。通过实例代码和工具推荐,帮助开发者快速掌握CAN总线通信技术,提升工业控制和汽车电子系统的开发效率。

dichengyan0013的博客 368

socket can 编程

Socket can 文档原名称:can.txt,位于 linux-3.2.0-m3352/Documentation/networking/can.txt。 CAN 控制器局域网络协议族之 Readme 文件(aka Socket CAN)。另外在该文档的后边附加一个CAN收发测试程序,用于与下位机通信。 目录 1 概述 / 什么是 Socket CAN? 2 目的 / 为什么要使用 socket API? 3 socket can 概念 3.1 接收列表 3.2 数据发送的本地回环模式(loopback

Mr.W的博客 9072

Linux下Python CAN通信开发:SocketCAN与DBC解析实战

CAN总线是汽车电子与工业控制中广泛应用的可靠通信协议,其多主、仲裁与短帧校验机制满足了实时控制场景的严苛要求。在Linux环境下,基于内核SocketCAN协议栈的高层API,开发者无需购买专属硬件即可通过vcan虚拟接口进行链路调试。python-can库提供了统一的总线操作抽象,结合cantools对DBC数据库文件的解析,能实现从原始报文到物理信号的高效转换,降低车载网络开发门槛。该技术组合广泛适用于BMS报文采集、电机控制、诊断工具等场景。围绕SocketCAN、python-can与cantoo

weixin_34315485的博客 575

Linux CAN编程详解

原文博客地址  http://velep.com/archives/1181.html 通过读这篇博客是我搜索can通讯以来讲解的最详细的一篇,还有其自己写的一刻关于can控制的程序都是非常棒的, Linux 系统中CAN 接口配置 在 Linux 系统中, CAN 总线接口设备作为网络设备被系统进行统一管理。在控制台下, CAN 总线的配置和以太网的配置使用相同的命令。

lizhu_csdn的专栏 5万+

C++实现阻塞式SocketCAN通信:嵌入式Linux CAN总线同步编程指南

在嵌入式系统和汽车电子领域,CAN总线作为连接控制器、传感器和执行器的关键通信网络,其稳定可靠的数据交换至关重要。Linux内核提供的SocketCAN接口将CAN设备抽象为网络套接字,使得开发者能够使用熟悉的套接字API进行通信。阻塞I/O模型作为一种同步编程范式,其原理在于让`read`或`recv`系统调用在数据未就绪时挂起进程,直至数据到达或超时,这为事件驱动的应用提供了确定性的执行流程。该技术的核心价值在于简化了程序逻辑,降低了并发编程的心智负担,尤其适用于需要严格时序控制、状态机实现或UDS诊断

germmy-神一样的开发 387

Linux环境下SocketCAN框架及USB-CAN驱动源码分析

Linux内核中的SocketCAN框架提供了一个易于使用的API,用于操作CAN网络。它基于标准套接字编程模型,让开发者可以像处理TCP/IP网络一样处理CAN帧。SocketCAN将CAN设备抽象为网络接口,使得Linux下的CAN通信更加直观和高效。在深入探讨SocketCAN之前,我们需要先了解它在整个Linux内核中的定位以及它是如何架构的。本章将介绍SocketCAN框架的基本概念,包括它的设计目标、核心组件以及与传统CAN硬件接口的区别和优势。

weixin_28922227的博客 776

对Socket CAN的理解(2)——【Socket的原理及使用】

           转载请注明出处:http://blog.youkuaiyun.com/Righthek 谢谢!            为了能够对Socket CAN的深入理解,我们需要了解Socket的机制。...

u014286440的博客 4341

分布式存储系统关于GDPR条例中的数据清除原则

文章目录前言HDFS存储系统数据的完全删除基于加解密的输入输出流的数据保护方案 前言 关于GDPR是什么,可能许多同学之前并不太了解,至少笔者在之前也是不清楚的。GDPR全称为通用数据保护条例,General Data Protection Regulation。它是一项来自欧盟的关于计算机数据保护相关的条约,旨在规范系统如何收集,管控用户私人数据的种种行为。但是当前的一些存储系统并没有完全符合...

走在前往架构师的路上 3628

socket_can配置

socket_can配置介绍 1.打开can设备 int fd = -1; //打开can0设备 fd = open("/sys/devices/platform/FlexCAN.1/bitrate",O_CREAT | O_TRUNC | O_WRONLY,0600); if(fd < 0) { printf("CAN1 InitDevice Failed : Open confi...

weixin_43977249的博客 1981

Pipeline更多理解

Pipe 类型用途VIGVideo Image Generator:用于图层显示,支持 scaling、rotationRGB简单图层显示,较低优先级DMA主要用于 writeback / WFD / composition output,即从 framebuffer 输出到外部设备(或 memory)Cursor小图层,用于显示指针等很可能是:分别用于主屏、仪表、虚拟显示的输出路径或者用于不同的 display 去做 GPU_TARGET / writeback 的拷贝你看到的意思。

Damon_X的博客 1053

更换光猫的原理与方法

当你给装维打电话说你需要更换光猫时,对于装维来说,他并不需要知道怎么更换,他只需要生成一张工单,由后台进行业务操作后,在去用户家把新光猫给装好即可,此时装维到底起到了什么作用呢?我想可能只是运输员吧,把一个设备从一个地方运到另一个地方罢了,此时并不能指望装维做什么,因为本质上来说装维的能力真的很差很差,我是不知道那些装维哪来的勇气做视频,还说自己什么什么能力很强?很强吗?吹牛的技术确实很强。 更换光猫之前,需要先明白为什么要更换光猫,怎么更换光猫,更换后不能用怎么办?怎么才能更换成功,换光猫以后被限速了怎么

qq_34146290的博客 1万+

【CAN 应用编程】SocketCan实战

​ 由于 Linux 系统将 CAN 设备作为网络设备进行管理,因此在 CAN 总线应用开发方面,Linux 提供了SocketCAN 应用编程接口,使得 CAN 总线通信近似于和以太网的通信,应用程序开发接口更加通用,也更加灵活。 ​ SocketCAN 中大部分的数据结构和函数在头文件 linux/can.h 中进行了定义,所以,在我们的应用程序中一定要包含头文件。

Thmos_vader的嵌入式学习笔记 2379

NX二次开发(python)-坯料尺寸(一)

一般在产品制造过程中,往往要判断一个模型在出模方向上的最小包容盒尺寸,在NX中可以用坯料尺寸命令实现,当然也有相应的代码实现,这或许可以帮助我们实现一些产品的坯料尺寸批量输出,节省人力。

dasfanfan的博客 823

Unix/C/C++进阶--SocketCAN 编程

Unix/C/C++进阶--SocketCAN 编程

天道酬勤 5632

CAD图纸智能搜索三大突破:图纸秒搜技术、相似度匹配与AI语义搜索

CAD图纸作为核心资产,长期面临管理难题:传统全文检索需逐张打开图纸人工查找,效率低下;相似图纸匹配依赖人工比对,误差率高;非专业人员难以通过模糊描述精准定位图纸。针对这些问题,唯杰地图推出三项智能解决方案:一是基于现代化索引引擎的​​全文搜索​​,支持秒级检索图纸内的文字、图层、块名称等,并可多条件组合查询;二是​​相似度搜索​​,通过SIFT算法和深度学习提取几何特征与拓扑结构,实现高精度匹配;三是​​AI语义搜索​​,利用大模型解析自然语言指令(如“查找半径为10的红色圆”),直接定位目标图形。

vjmap的博客 1871

保姆级教程:用QSTEM和DrProbe搞定你的第一张STEM模拟图(附Fe3O4实例文件)

本文提供了一份详细的STEM模拟图像生成教程,涵盖从晶体结构获取到最终图像模拟的全过程。通过QSTEM和DrProbe软件的操作指南,帮助材料科学研究者快速掌握STEM模拟技术,特别适合初学者。教程包含Fe3O4实例文件,详细解析参数设置、计算优化和结果分析等关键步骤。

weixin_33730836的博客 525

linux can命令详解,Linux CAN编程详解

Linux 系统中CAN 接口配置在 Linux 系统中, CAN 总线接口设备作为网络设备被系统进行统一管理。在控制台下, CAN 总线的配置和以太网的配置使用相同的命令。在控制台上输入命令:ifconfig –a可以得到以下结果:在上面的结果中, eth0设备为以太网接口, can0和can1 设备为两个 CAN 总线接口。接下来使用 ip 命令来配置 CAN 总线的位速率:ip link ...

weixin_42510604的博客 5777

Linux ARM平台开发系列讲解(摄像头V4L2子系统) 2.12.5 V4L2 control的原理和实现

既然涉及到视频输入,就会有很多与 相关的效果,比如对比度、饱和度、色温、白平衡等等,这些都是通用的、必须的控制项,并且大多数仅需要设置一个整数值即可。 内核中已经为我们提供了这个控制类型的,我们只需要明确自己需要添加什么控制类型,然后将其添加进内核中即可。该部分摄像头代码一半厂家会提供驱动或者相对应的参数,否则没有图像处理知识很难开发出来。 返回总目录...

DSMGUOGUO的博客 1437

socketcan

参考<<Linux_Can编程详解>> CAN原理介绍: https://www.cnblogs.com/spoorer/p/6649303.html 一.初始化工作 SocketCAN 中大部分的数据结构和函数在头文件 linux/can.h 中进行了定义。 CAN 总线套接字的 创建采用标准的网络套接字操作来完成。网络套接字在头文件 sys/socket.h 中定义。...

KingOfMyHeart的博客 2267

mjlab & MimicKit 宇树 G1 人形机器人强化学习训练部署

基于mjlab框架训练Unitree G1人形机器人执行双旋踢的示例。参考动作源自Jason Peng的MimicKit项目。数据转换脚本(MimicKit pkl → mjlab csv)完整训练结果与超参数预训练ONNX检查点用于部署实体硬件部署指南⚠️ 免责声明仅用于教育目的。对于因尝试复现此处展示结果而导致的财产损失或人身伤害,我们概不负责。操作硬件时请谨慎行事并保持良好判断力。

2506_90492529的博客 1702

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

socketCan二次开发封装库:简化CAN通信的利器

socketCan二次开发封装库:简化CAN通信的利器 去发现同类优质开源项目:https://gitcode.com/ 在嵌入式开发和物联网领域,CAN(Controller Area Network)总线通信因其高可靠性和高抗干扰性而得到了广泛应用。今天,我们为您推荐一款优秀的开源项目——socketCan二次开发封装库,它将极大地简化Linux环境下的CAN通信开发工作。 项目介绍 sock...

gitblog_06745的博客 1106

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

CAN 是什么以及特点、协议 、使用方法

CAN 是什么以及特点、协议 、使用方法

hxw123aaa的博客 5724

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

贝叶斯统计 [韦来生编]

贝叶斯(Bayes)统计是近几十年来迅速发展起来的数理统计的一个重要分支。贝叶斯方法与经典统计方法的主要不同之处是进行统计推断时除了利用样本信息外,还要利用参数的先验信息,因此可以提高统计推断或统计决策的效果。它在经济、金融、生物、医学、自然科学和社会科学等许多领域具有广泛的应用。贝叶斯方法的研究已渗透到了统计学的几乎所有领域。作者在给中国科学技术大学概率论与数理统计专业本科生开设的“数理统计”课程中有一章专门讲授“贝叶斯方法和统计决策理论”,近十年来也给中国科学技术大学概率统计专业研究生开设过几次“贝叶斯分析”课。本书是在对过去讲稿的内容作了适当的增减和调整的基础上完成的。  本书共分六章。第1章是绪论,介绍了贝叶斯统计的若干基本概念,同时对必要的数理统计的基础知识有重点地作了回顾。第二章介绍了确定先验分布的若干可供选择的方法。第三章介绍了几类常见统计模型参数的后验分布的主要结果和计算方法。第四章和第五章分别介绍了“贝叶斯统计推断”和“贝叶斯统计决策”的内容。第六章介绍了贝叶斯统计计算的若干方法,包括蒙特卡洛方法和马尔可夫链蒙特卡洛(MCMC)方法以及相关统计软件的简介。本书的每一章附右大量的例题和习题,书末附有常用的几个表格和部分习题解答供读者查用。  大约可在54学时内讲授本书的第1章至第六章的主要内容,教师可根据学时需要选讲本书第1章至第六章的部分内容。书中标“*”号的章节可略去不讲,留给读者作为阅读材料。第六章例题中的R代码和部分例题的数据文件等可从作者个人主页下载。  作者在编写本书的过程中参考了J.O.Berger教授的《统计决策论及贝叶斯分析》和茆诗松教授编写的《贝叶斯统计》等书中的一些内容,以及《贝叶斯分析》一书中由张伟平博士编写的有关贝叶斯统计计算的一些内容。在此表示衷心感谢。  本书编写准备过程中,中国科学技术大学统计与金融系的几个研究生帮助完成了本书部分中文的录入和排版,作者对他们的辛勤工作表示真诚的感谢。高等教育出版社为本书的出版给予了大力支持。在此一并致谢。

Linux 树莓派 Can编程

参考博客地址:http://velep.com/archives/1181.html 《Linux CAN编程详解》是一篇百度文库上的文档,主要描述了以下内容: can总线介绍及其帧类型; Linux 系统中CAN 接口配置; Linux 系统中CAN 接口应用程序开发; Linux 系统中CAN 接口编程实例 总体来说,这篇文档,对于嵌入式linux can应用编程还是有很大的帮助。特别是里面关于“Linux 系统中CAN 接口应用程序开发”的介绍,总结的很全面,讲述的比较清楚。 原博主编写的linux

qq_38074673的博客 1580

socketcan-rs:实现Linux下CAN通信的Rust库

socketcan-rs:实现Linux下CAN通信的Rust库 在现代嵌入式系统与自动化领域,控制器局域网络(Controller Area Network,CAN)是一种广泛使用的通信协议。socketcan-rs 是一个Rust语言编写的库,它为Linux系统下的SocketCAN子系统提供了接口,使得CAN总线的通信变得简单而高效。 项目介绍 socketcan-rs 旨在提供一个稳定且易...

gitblog_00405的博客 1220
上一篇: 从差分信号到工业物联:RS485如何用电压差重塑通信可靠性
下一篇: LC/SC/MPO接口光模块选购避坑指南:从千兆到100G的实战经验分享
java5
博客等级 码龄22年 85粉丝 2103原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值