【 libusb4java实战:跨平台USB设备通信完全指南】

有没有办法利用libusb读取usb设备数据 使用libusb枚举设备并找到你的遥控器。通过或其他适当的传输方式从设备中读取数据。分析数据包格式,查看摇杆操作是否能通过USB数据反映出来。如果设备使用的是HID协议,可以使用libusb与HID接口进行交互。如果遥控器通过USB传输操控数据且能被识别为libusb设备,那么理论上是可以通过libusb读取到数据的。不过,需要对数据格式进行分析,才能从中提取出摇杆等控制数据。希望如上措施及解决方案能够帮到有需要的你。 阅读详情

libusb4java实战:跨平台USB设备通信完全指南

前言

在现代嵌入式系统和游戏外设开发中,USB通信是设备与主机交互的主流方式。然而,直接操作USB协议栈是一项复杂的工作,需要处理设备枚举、端点配置、数据传输等诸多底层细节。libusb4java作为libusb的Java绑定,为开发者提供了一个跨平台的USB通信解决方案——无需编写任何C/C++代码,即可在Java中实现与USB设备的数据交换。

本文将通过一个实际的USB游戏按钮控制器项目,详细讲解如何使用libusb4java实现完整的USB通信。我们将覆盖从环境配置、设备初始化、数据传输到资源管理的完整流程,并分享在实际项目中的经验和最佳实践。

一、认识USB通信与libusb4java

1.1 USB通信基础

通用串行总线(USB)是计算机与外设通信最常用的接口标准。理解USB通信的几个核心概念,对于正确使用libusb4java至关重要:

**设备(Device)与端点(Endpoint)**是USB通信的基本单元。每个USB设备有一个或多个端点,端点是数据收发的最小单位,分为四种类型:控制传输(Endpoint 0)、等时传输(Isochronous)、中断传输(Interrupt)和批量传输(Bulk)。其中批量传输适用于数据量大但不需要实时保证的场景,本项目使用的就是批量传输。

Vendor ID和Product ID是USB设备的唯一标识符。每个USB设备在制造时会被分配一个16位的Vendor ID( VID)和16位的Product ID(PID),主机通过这两个ID来识别和定位目标设备。本项目使用的设备VID为0x31DB,PID为0x4C0A。

接口(Interface)和端点地址定义了设备的功能和通信通道。一个USB设备可以包含多个接口,每个接口对应一种功能。端点地址由端点号和传输方向组成,例如0x81表示IN端点1(0x80表示IN,0x01表示端点1),0x02表示OUT端点2。

1.2 libusb4java简介

libusb4java是libusb的Java绑定库,由Java-USB项目提供。它完全继承了libusb的跨平台特性,支持Windows、Linux、macOS等主流操作系统。与使用JNI直接调用libusb C库不同,usb4java同样采用JNI方式调用libusb原生库,但提供了更友好的Java API封装,纯Java即可使用,大大降低了开发门槛。

libusb4java的核心特点体现在三个方面。首先是跨平台支持,同一份Java代码可以在不同操作系统上运行,无需修改。其次是完整的功能覆盖,支持设备枚举、配置选择、接口声明、批量/中断传输等所有常用USB操作。第三是与JNA的无缝集成,可以与JNA配合使用,实现从USB通信到Windows API调用的完整解决方案。

二、环境配置与依赖管理

2.1 Maven依赖配置

在项目中引入libusb4java需要添加两个核心依赖:usb4java本身和对应的平台原生库:

<dependency>
    <groupId>org.usb4java</groupId>
    <artifactId>usb4java</artifactId>
    <version>1.3.0</version>
</dependency>

usb4java是核心库,提供了USB通信的Java API。而不同操作系统需要对应的原生库支持,示例:

<!-- Windows 64位 -->
<dependency>
    <groupId>org.usb4java</groupId>
    <artifactId>libusb4java</artifactId>
    <version>1.3.0</version>
    <classifier>win32-x86-64</classifier>
</dependency>

<!-- Windows 32位 -->
<dependency>
    <groupId>org.usb4java</groupId>
    <artifactId>libusb4java</artifactId>
    <version>1.3.0</version>
    <classifier>win32-x86</classifier>
</dependency>

2.2 项目中的完整依赖

本项目的pom.xml配置的依赖体系:

<dependencies>
    <!-- USB通信 -->
    <dependency>
        <groupId>org.usb4java</groupId>
        <artifactId>usb4java</artifactId>
        <version>1.3.0</version>
    </dependency>

    <!-- JNA(用于Windows API调用) -->
    <dependency>
        <groupId>net.java.dev.jna</groupId>
        <artifactId>jna</artifactId>
        <version>4.1.0</version>
    </dependency>

    <!-- 日志框架 -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.1.2</version>
    </dependency>
</dependencies>

这种依赖组合实现了从USB设备读取数据(usb4java通过JNI调用libusb原生库)到解析协议(commons-lang3)再到日志记录(logback)的完整技术栈。

三、核心实现分析

3.1 常量定义

在UsbButtonSpin类中,我们首先定义了USB通信所需的常量:

private static final byte OUT_ENDPOINT = 0x02;
private static final byte IN_ENDPOINT = (byte) 0x81;
private static final int TIMEOUT = 0;
private static final byte INTERFACE = 0;

这些常量定义了USB通信的基本参数:OUT_ENDPOINT(0x02)是主机向设备发送数据的端点;IN_ENDPOINT(0x81)是设备向主机发送数据的端点,注意0x80表示IN方向,加上端点号1得到0x81;TIMEOUT为0表示无限等待,即阻塞模式;INTERFACE指定要声明的接口编号。

实践要点:端点地址的定义取决于硬件设计,不同设备的端点配置可能不同。在开发时,需要参考设备的硬件规格书,具体协议规范或通过工具(如bushound)抓包分析确定正确的端点地址。

下面是我前面写过的总线抓包分析工具博客,仅供参考:
Bus Hound——强大的总线分析工具,抓USB转串口数据包如何使用

3.2 设备初始化流程

设备初始化是USB通信的关键步骤,涉及libusb上下文创建、设备枚举、打开设备和声明接口等多个环节:

private void init() {
    if (this.handle != null) {
        return;
    }

    // 1. 初始化libusb库
    int result = LibUsb.init(null);
    if (result != LibUsb.SUCCESS) {
        throw new LibUsbException("Unable to initialize libusb", result);
    }
    log.info("LibUsb.init SUCCESS");

    // 2. 获取设备列表
    DeviceList devices = new DeviceList();
    result = LibUsb.getDeviceList(null, devices);
    if (result < 0) {
        throw new LibUsbException("Unable to get device list", result);
    }
    log.info("getDeviceList Success");

    // 3. 遍历设备,查找目标设备
    for (Device device : devices) {
        DeviceDescriptor deviceDescriptor = new DeviceDescriptor();
        result = LibUsb.getDeviceDescriptor(device, deviceDescriptor);
        if (result != LibUsb.SUCCESS) {
            throw new LibUsbException("Unable to get device descriptor", result);
        }

        // 4. 通过VID/PID匹配目标设备
        if (deviceDescriptor.idVendor() == VENDOR_ID && 
            deviceDescriptor.idProduct() == PRODUCT_ID) {

            // 5. 打开设备
            DeviceHandle handle = new DeviceHandle();
            result = LibUsb.open(device, handle);
            if (result != LibUsb.SUCCESS) {
                throw new LibUsbException("Unable to open device", result);
            }
            log.info("Open Target Device SUCCESS");

            // 6. 声明接口
            result = LibUsb.claimInterface(handle, INTERFACE);
            if (result != LibUsb.SUCCESS) {
                throw new LibUsbException("Unable to claim interface", result);
            }
            log.info("ClaimInterface SUCCESS");

            // 7. 读取初始数据验证设备
            this.handle = handle;
            read(buttonResponseData);
            log.info("Receive ID {}", buttonResponseData[6] & 0xFF);

            // 8. 验证设备ID匹配(多设备场景)
            if (buttonResponseData[5] == (byte) 0x82 && 
                (buttonResponseData[6] & 0xFF) != buttonId) {
                // 设备不匹配,关闭并继续查找
                LibUsb.releaseInterface(handle, INTERFACE);
                LibUsb.close(handle);
                this.handle = null;
                continue;
            }

            log.info("All Init SUCCESS");
            this.isInitSuccess = true;
            break;
        }
    }

    // 9. 释放设备列表
    LibUsb.freeDeviceList(devices, true);
}

这个初始化流程遵循了USB通信的标准模式,每个步骤都可能抛出异常需要进行错误处理。值得注意的是第7-8步,我们读取设备返回的初始数据来验证设备ID是否匹配——这是因为同一个VID/PID可能连接了多个设备,需要通过设备内部的ID来区分。

安全提示:设备初始化可能因为驱动问题、权限问题或硬件连接问题而失败。在实际应用中,应该为用户提供明确的错误提示,并提供重试机制。LibUsbException包含了错误码,可以通过错误码查询具体的失败原因。

四、数据传输实现

4.1 发送数据(OUT传输)

向USB设备发送数据使用批量传输(Bulk Transfer),适用于数据量大但不需要实时保证的场景:

private void write(ByteBuffer buffer) {
    IntBuffer transferred = IntBuffer.allocate(1);
    int result = LibUsb.bulkTransfer(
        handle,           // 设备句柄
        OUT_ENDPOINT,    // OUT端点地址(0x02)
        buffer,           // 数据缓冲区
        transferred,      // 实际传输的字节数
        TIMEOUT           // 超时时间(0=无限等待)
    );

    if (result != LibUsb.SUCCESS) {
        throw new LibUsbException("Unable to send data", result);
    }

    // 每5秒打印一次日志,避免频繁输出
    long cur = System.currentTimeMillis();
    if (cur - preTime[0] > 5000) {
        preTime[0] = cur;
        log.info("send usb animation data is ok");
    }
}

bulkTransfer是libusb4java的核心传输方法。当TIMEOUT设为0时,调用会阻塞直到数据发送完成或发生错误。对于动画帧数据这类需要完整传输的场景,阻塞模式是合适的选择。

实践要点:使用ByteBuffer.allocateDirect创建直接缓冲区可以提高与原生代码交互的性能。在处理大量数据传输时,这一点尤为重要。

4.2 接收数据(IN传输)

从USB设备接收数据同样使用批量传输,但方向相反:

private void read(byte[] data) {
    ByteBuffer buffer = ByteBuffer.allocateDirect(data.length);
    IntBuffer transferred = IntBuffer.allocate(1);

    // 1. 发送读取请求到OUT端点
    int result = LibUsb.bulkTransfer(handle, OUT_ENDPOINT, buffer, transferred, TIMEOUT);
    if (result != LibUsb.SUCCESS) {
        throw new LibUsbException("Unable to send data", result);
    }

    // 2. 从IN端点接收数据
    result = LibUsb.bulkTransfer(handle, IN_ENDPOINT, buffer, transferred, TIMEOUT);
    if (result != LibUsb.SUCCESS) {
        throw new LibUsbException("Unable to get data", result);
    }

    // 3. 将缓冲区数据复制到字节数组
    buffer.get(data);
}

这个read方法的设计反映了某些USB设备的通信协议:首先向设备发送读取请求(OUT方向),设备收到请求后返回数据(IN方向)。这是一种"请求-响应"模式,常用于查询设备状态的场景。

安全提示:读取操作可能因为设备断开或通信错误而失败。在循环读取的场景中(如轮询按钮状态),应该捕获异常并决定是重试还是退出。

4.3 协议数据解析

接收到的原始数据需要按照协议规范进行解析。本项目使用的私有协议结构如下:

字段位置长度说明
同步头[0-4]5固定值 ‘LTTMD’
指令描述[5]10x82表示按键应答
按键ID[6]11-254有效
按键状态[7]10x81按下,0x84抬起
保持时间[8-9]2小端序,单位ms

解析代码:

private int handleButtonStatus() {
    read(buttonResponseData);

    // 验证指令标识
    if (buttonResponseData[5] == (byte) 0x82 && 
        (buttonResponseData[8] != 0 || buttonResponseData[9] != 0)) {

        // 解析按键ID(无符号转换)
        int buttonId = buttonResponseData[6] & 0xFF;

        // 解析按键状态
        byte buttonStatus = buttonResponseData[7];

        // 解析保持时间(小端序 × 5)
        int holdTime = (((buttonResponseData[9] & 0xFF) << 8) | 
                        (buttonResponseData[8] & 0xFF)) * 5;

        log.info("[USB Button Event] buttonId={}, status={}, holdTime={}ms",
                buttonId,
                buttonStatus == (byte) 0x81 ? "pressed" : "released",
                holdTime);

        // 根据状态触发相应逻辑
        if (buttonStatus == (byte) 0x84 && holdTime <= 4300) {
            startPlay();
        }
    }
    return 0;
}

五、资源管理与生命周期

5.1 设备关闭

正确的资源释放与初始化同样重要。USB设备资源如果不正确释放,可能导致设备锁定或其他应用无法访问:

public void closeDevice() {
    if (handle != null) {
        // 1. 释放接口声明
        int result = LibUsb.releaseInterface(handle, INTERFACE);
        if (result != LibUsb.SUCCESS) {
            throw new LibUsbException("Unable to release interface", result);
        }

        // 2. 关闭设备句柄
        LibUsb.close(handle);

        // 3. 退出libusb上下文
        LibUsb.exit(null);

        this.handle = null;
        this.isInitSuccess = false;
    }
}

资源释放的顺序很重要:先释放接口声明(claimInterface的对应操作),再关闭设备句柄,最后退出libusb上下文。这个顺序确保了设备状态的一致性。

安全提示:在程序异常退出时(如kill -9或系统崩溃),已声明的接口可能不会被正确释放。下次重新连接设备时,系统可能需要等待一段时间才能重新声明接口。如果频繁遇到"接口已被占用"的错误,可以在初始化前尝试调用LibUsb.setDebug查看详细的调试信息。

5.2 主程序中的优雅关闭

在Main类中,我们使用了ShutdownHook来确保程序退出时正确释放资源:

public static void main(String[] args) throws Exception {
    UsbButtonSpin usbButton = new UsbButtonSpin(VENDOR_ID, PRODUCT_ID, 1);

    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
        log.info("Received stop signal, setting running=false");
        running = false;
    }));

    while (running) {
        // 主循环
    }

    log.info("Program stopping, closing device");
    usbButton.closeDevice();
    log.info("Program exited");
}

这种方式确保了即使用户通过Ctrl+C或关闭窗口终止程序,USB设备资源也能被正确释放。

六、常见问题与调试

6.1 常见问题排查

问题现象可能原因解决方案
Native library not foundlibusb4java DLL未正确加载检查java.library.path设置,确保JAR在classpath中
Unable to claim interface接口被其他程序占用关闭占用程序,或使用Zadig重新安装驱动
设备列表为空USB设备未连接或驱动未安装检查设备管理器,确认设备正常识别
批量传输超时设备无响应或传输阻塞检查设备固件,确认端点配置正确
读取数据全为0通信协议不匹配验证同步头、指令ID等协议字段

6.2 调试技巧

启用libusb的调试输出可以获取详细的通信信息:

// 在初始化前设置调试级别
LibUsb.setDebug(null, 3);  // 3 = verbose

调试级别的含义:0=无输出,1=错误,2=警告,3=信息,4=调试。对于排查通信问题,设置为3可以获得足够的细节。

6.3 平台差异处理

不同操作系统的USB驱动机制不同,需要注意:

Windows平台:需要安装libusb驱动。可以使用Zadig工具将设备从默认驱动切换为libusbK或WinUSB驱动。这是libusb4java在Windows上工作的前提条件。

Linux平台:通常需要udev规则来赋予普通用户访问USB设备的权限。添加udev规则文件:

# /etc/udev/rules.d/99-usbbutton.rules
SUBSYSTEM=="usb", ATTR{idVendor}=="31db", ATTR{idProduct}=="4c0a", MODE="0666"

macOS平台:一般开箱即用,但可能需要批准系统扩展。macOS 10.15+对USB访问有更严格的限制。

七、扩展应用

7.1 与JNA结合实现完整功能

本项目的架构展示了libusb4java与JNA的完美配合:libusb4java负责底层USB通信,JNA负责调用Windows API发送模拟按键。这种组合可以构建完整的硬件-软件交互系统:

// 检测到按钮按下
if (buttonStatus == (byte) 0x84 && holdTime <= 4300) {
    // 通过JNA发送空格键
    WindowsKeyStroke.sendSpaceKey();
}

下面是我的博客应用示例:
【JNA实战:Java无缝调用Windows API模拟键盘输入】

7.2 支持多种设备

通过修改VID/PID和协议解析逻辑,可以快速支持其他USB设备:

// 扩展支持更多设备
private static final DeviceConfig[] SUPPORTED_DEVICES = {
    new DeviceConfig((short) 0x31DB, (short) 0x4C0A, "Game Button"),
    new DeviceConfig((short) 0x1234, (short) 0x5678, "Another Device"),
};

private static class DeviceConfig {
    short vendorId;
    short productId;
    String name;

    DeviceConfig(short vendorId, short productId, String name) {
        this.vendorId = vendorId;
        this.productId = productId;
        this.name = name;
    }
}

八、总结

通过本次博客总结,简单掌握了使用libusb4java实现跨平台USB通信的方法。核心要点包括:

  • libusb4java基础:理解USB端点、批量传输、设备枚举等核心概念
  • 设备初始化流程:从LibUsb.init到claimInterface的完整步骤
  • 数据传输实现:bulkTransfer方法的使用和ByteBuffer操作技巧
  • 资源管理:正确的设备关闭顺序和异常处理
  • 平台差异:Windows、Linux、macOS的不同配置要求

本文博客如有错误,还望斧正~

参考资料

附录:完整设备初始化代码

package org.usb.button;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.usb4java.*;

public class UsbDeviceManager {
    private static final Logger log = LoggerFactory.getLogger(UsbDeviceManager.class);

    private static final short VENDOR_ID = 0x31DB;
    private static final short PRODUCT_ID = 0x4C0A;
    private static final byte INTERFACE = 0;
    private static final byte OUT_ENDPOINT = 0x02;
    private static final byte IN_ENDPOINT = (byte) 0x81;
    private static final int TIMEOUT = 0;

    private DeviceHandle handle;
    private boolean isInitialized = false;

    public void initialize() {
        // 初始化libusb
        int result = LibUsb.init(null);
        if (result != LibUsb.SUCCESS) {
            throw new LibUsbException("Failed to initialize libusb", result);
        }

        // 获取设备列表并查找目标设备
        DeviceList devices = new DeviceList();
        result = LibUsb.getDeviceList(null, devices);
        if (result < 0) {
            throw new LibUsbException("Failed to get device list", result);
        }

        for (Device device : devices) {
            DeviceDescriptor descriptor = new DeviceDescriptor();
            LibUsb.getDeviceDescriptor(device, descriptor);

            if (descriptor.idVendor() == VENDOR_ID && 
                descriptor.idProduct() == PRODUCT_ID) {

                handle = new DeviceHandle();
                result = LibUsb.open(device, handle);
                if (result != LibUsb.SUCCESS) {
                    throw new LibUsbException("Failed to open device", result);
                }

                result = LibUsb.claimInterface(handle, INTERFACE);
                if (result != LibUsb.SUCCESS) {
                    throw new LibUsbException("Failed to claim interface", result);
                }

                isInitialized = true;
                log.info("USB device initialized successfully");
                break;
            }
        }

        LibUsb.freeDeviceList(devices, true);

        if (!isInitialized) {
            throw new RuntimeException("Target USB device not found");
        }
    }

    public void close() {
        if (handle != null) {
            LibUsb.releaseInterface(handle, INTERFACE);
            LibUsb.close(handle);
            LibUsb.exit(null);
            handle = null;
            isInitialized = false;
        }
    }

    public boolean isInitialized() {
        return isInitialized;
    }
}

附录:完整项目依赖库截图

在这里插入图片描述

在android中使用USB进行通信的4种方法 1. 使用skelton.c demo skelton.c 是linux内核自带的读写USB设备的demo,修改 VID&PID,编译成内核模块,成功加载后即可在用户空间使用open read write等函数。参考garmin_usb.c。 2. 使用native USB API(usbhost库) Android native API被上层android usb api调用...... 阅读详情

相关推荐

Java环境下的USB-HID设备通信实现详解

HID设备定义了一组设备类别,例如键盘、鼠标等,它们遵循特定的协议和数据格式,以便主机系统可以正确识别并处理这些设备发送的输入数据。输出设备类包括那些可以从主机接收数据并执行某些动作的设备。例如,某些LED灯可以配置为通过USB接收指令来改变颜色或亮度。输出设备需要能够接收特定格式的数据包,并能够解析这些数据以执行操作。集合设备类则包含了同时具备输入和输出功能的设备,最典型的例子是某些游戏控制器,它们可以接收游戏指令同时向主机发送按钮按下的信息。

weixin_35391606的博客 1441

嵌入式linux系统中,lsusb出现unable to initialize libusb: -99 解决办法 【转】

转自:http://cpbest.blog.163.com/blog/static/41241519201111575726966/ libusb是linux系统中,提供给用户空间访问usb设备的API,方便从linux内核中获取或设置usb设备的信息。lsusb这个用户空间程序,也正是依赖libusb提供的接口API来实现对系统当前的usb总线的扫描,从而显示当前系统存在的usb设备的。  ...

weixin_34381666的博客 1265

libusb4java:usb4java使用的本机JNI库

这是libusb的JNI包装器的源代码。 usb4java已经包括用于以下平台的预构建库: linux-x86 linux-x86-64 linux臂 linux-aarch64 的win32-x86的 的win32-x86-64 达尔文x86-64 达尔文臂64 如果您需要在其他平台上使用该库,则可以轻松地自己编译它。 在与Unix兼容的操作系统上,您仅需要Java JDK,最新的libusb库版本,GNU C编译器和cmake。 正确安装所有组件后,您应该可以使用以下命令构建库: $ mkdir build $ cd build $ cmake .. $ make 编译成功后,您可以在build/src目录中找到该库。 usb4java在CLASSPATH目录org/libusb4java/<OS>-<ARCH>/搜索该库。 例如,在32位x86 linux计算机上,

解决Error initializing USB support: Other errors[-99]

qq_40168905的博客 567

usb4java跨平台的基于 libusb1.0 开发的JavaUSB类库

usb4java跨平台的基于 libusb 1.0 开发的 Java USB 类库,通过 usb4java-javax extension 支持  javax-usb standard (JSR-80) 开发。 平台环境支持:  Linux (x86 32/64 bit, ARM 32 bit) OS X (x86 32/64 bit)  Windows (x86 32/64 bit)

手把手教你用ZLMediaKit搭建WebRTC直播:本地推流与播放实战

本文详细介绍了如何使用ZLMediaKit搭建WebRTC直播系统,涵盖从环境准备、编译部署、SSL证书配置到本地推流与播放的完整实战流程。通过一步步的指导,帮助开发者快速掌握基于ZLMediaKit的WebRTC推拉流技术,构建低延迟的实时音视频应用。

weixin_28842367的博客 346

libusb 返回值的意义,以及如何用C语言,打印出对应返回值表示的意义

最近在Android下jni 使用libusb,libusb返回值表示的意义,一直不知道是什么,特整理如下: /** Success (no error) */ LIBUSB_SUCCESS = 0, /** Input/output error */ LIBUSB_ERROR_IO = -1, /** Invalid parameter */ LIB...

fhplzh的专栏 3297

LabVIEW+数据库应用系列保姆级教程,第二篇增删查改

2021-7-2 先挖好坑

wwplh5520370的博客 7362

libusb与移动设备USB OTG通信:Android平台实现方案

你是否曾面临这样的开发困境:需要在Android设备上与USB外设通信,却受限于系统权限和平台差异?传统方案要么需要root权限,要么依赖厂商定制API,兼容性和安全性难以兼顾。本文将系统讲解如何基于libusb库,在非root的Android设备上通过USB OTG(On-The-Go)实现稳定可靠的USB通信,涵盖从环境搭建到数据传输的完整流程。 读完本文你将获得: - 理解Android ...

gitblog_01051的博客 1057

OLED的字模提取(保姆级)---基于PCtoLCD2013

做为一个刚刚开始接触编程不久的白菜,这个OLED想做一个信息显示,可是商家给我的例程里就是88,816两种字体的格式,我的屏幕是0.91寸的8*16的字体显示上感觉特别丢丢儿小,我就想整个大的,哎,只怪直接学习习惯不好,总是学一半,绕了好大一圈,才搞好,想写一篇博客,时刻提醒踏实学习,第一次写博客,小白一枚,勿喷。。 OLED屏幕驱动程序功能 我们对Markdown编辑器进行了一些功能拓展与语法支...

qq_44886611的博客 7781

FOC电机控制中电流采样延迟补偿的原理和方法

摘要: FOC电机控制中,电流采样、计算与PWM更新存在固有延迟(约1.5个PWM周期),导致相位滞后,限制电流环带宽。主流补偿方法包括: 一阶前向预测法:基于历史电流值预测未来电流,抵消延迟,工程应用广泛; 相位超前补偿:通过s/z域校正器设计实现等效预测; 状态观测器法(如龙伯格观测器):通过电机模型闭环估计状态,兼具噪声抑制和参数辨识能力,但复杂度高。实际需注意参数敏感性、离散化精度及延迟时间校准,避免过补偿风险。一阶预测法因平衡效果与复杂度成为工业首选。

jifengzhiling的博客 2231

基于usb4java或libusb使用Android Accessory

Google对于Android Accessory的应用端开发有详细的例子,我这里就不发代码。实在看不懂官方例子,再找我吧,我把代码贴上来。主要提几个要点: 1、activity配置的intent-filter,是在accessory通过AOA协议连接设备后,系统决定使用哪个应用的配置。例如我们配置的manufacturer、model、version,只有accessory连接时提供的信息一致,...

UFO_SERIESOFSOFT的博客 1952

PCB之AD层次化原理图设计

PCB之AD层次化(模块化)原理图设计 软件版本:AD17.1.9(bBuild 592) 先上效果图: 可以看到,图中有RS485和W5500这两个部分是复用了原理图,当项目中需要多个功能相同的电路时,这种设计就可以大大节约PCB布局布线的时间,方法后面介绍; 1.首先确定好项目中个部分电路的功能模块 不同功能的电路分开不同原理图画,然后给出输入输出端口,这样方便复用,下面是实例项目的功能划分 2.单个模块电路的接口设计 这里以W5500以太网接口电路为例说明: 主要就分为通讯接口和电源接口:

洋洋洋的博客 3万+

linux hid设备通讯,Linux 下使用libusb 与USB-HID 设备通信之控制传输

1、前言上一篇文章记录到如何在ubuntu 安装开源项目libusb,这篇将记录,以下使用libusb 提供的api 方便的与USB-HID 设备通信,通信方式为控制传输。java2、关于libusb 如何查找HID 设备,能够看观看一下个人Linux 下使用libusb 与USB-HID 设备通信之中断传输ubuntu这篇文章,里面有详细记载如何查找HID 设备。api3、libusb_cont...

weixin_35982673的博客 1264

2022年全国职业院校技能大赛高职组大数据技术与应用赛项赛卷⑩—解析答案

工业互联网是工业全要素、全产业链、全价值链的全面连接,是人、机、物、工厂互联互通的新型工业生产制造服务体系,是互联网从消费领域向生产领域、从虚拟经济向实体经济拓展的核心载体,是建设现代化经济体系、实现高质量发展和塑造全球产业竞争力的关键支撑。加快发展工业互联网产业,不仅是各国顺应产业发展大势,抢占产业未来制高点的战略选择,也是我国推动制造业质量变革、效率变革和动力变革,实现高质量发展的客观要求。 为完成工业大数据分析工作,你所在的小组将应用大数据技术,以Scala作为整个项目的基础开发语言,基于大数据平台综

我是网络安全兼技能大赛工程师,专注网络安全技术学习与技能大赛实战!持续分享最新的技术文章,帮你少走弯路,一起在技术赛道上进步~ 578

【数据同化第二期】数据同化中三大理论基础之一(最小方差估计)

【数据同化第二期】深入理解数据同化及经典案例(最小方差估计)

WW、forever的博客 1596

探索USB设备的无限可能:usb4java开源库全面解析

探索USB设备的无限可能:usb4java开源库全面解析 项目介绍 在Java开发的世界里,直接与USB设备交互曾是一项挑战。而今天,这一切因usb4java而改变。由Klaus Reimer和Luca Longinotti共同打造,usb4java是一个基于libusb 1.0的强大库,旨在让Java开发者能够轻松地在他们的应用中集成USB设备访问功能。该库提供了对低级libusb API的完...

gitblog_00452的博客 555

40、5G NR射频要求解析

本文详细解析了5G NR射频相关要求,包括参考灵敏度与动态范围的定义、接收机对干扰信号的抗扰性要求(如阻塞、邻道选择性等)、辐射射频要求在FR1和FR2频段的差异,以及多标准无线电基站(MSR)的发展及其对射频要求的影响。内容涵盖测试模型、干扰场景、具体指标和实现挑战,为理解和应用5G NR射频规范提供了全面指导。

qsc901234的博客 245

探索Java与USB的桥梁:usb4java

探索Java与USB的桥梁:usb4java 项目介绍 usb4java 是一个基于 libusb 1.0 的Java USB库,旨在为Java开发者提供一个高效、可靠的USB设备访问解决方案。该项目由Klaus Reimer和Luca Longinotti共同维护,自2011年以来,它已经成为Java社区中访问USB设备的优选工具之一。 项目技术分析 usb4java 的核心优势在于其对 lib...

gitblog_00029的博客 684

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

JNI里面用Libusb监听设备接入、拔出

背景:有些usb设备用Android通信不上或者检测不到。如hid usb设备 实现思路:在jni里面搞一个线程,让线程去检测。 以下是简单实现的代码: #include <jni.h> #include <android/log.h> // #include <stdlib.h> // standard lib functions #include...

我的专栏 1398

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

【亲测免费】 探索Java世界的USB访问利器:usb4java

探索Java世界的USB访问利器:usb4java 项目介绍 在Java开发领域,访问USB设备一直是一个具有挑战性的任务。然而,随着usb4java项目的出现,这一难题得到了有效解决。usb4java是一个基于libusb 1.0的Java库,旨在为Java开发者提供一个高效、可靠的USB设备访问解决方案。该项目由Klaus Reimer和Luca Longinotti共同开发,并遵循开源许可协...

gitblog_00034的博客 1008

老版QQ原生表情gif动态

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

usb4java开源项目使用教程

usb4java开源项目使用教程 项目介绍 usb4java 是一个用于Java平台的USB编程库,它提供了访问USB设备的能力,使Java开发者能够直接从Java应用程序中与USB设备交互。该项目基于libusb,实现了跨平台的支持,包括Windows、Linux和Mac OS X等操作系统。通过usb4java,开发者无需依赖本地代码即可实现USB通信功能,大大简化了Java应用在不同平台上...

gitblog_00809的博客 960

java 串口通信libusb_libusb 通信

1 #include "libusb.h"2 int main(int argc, char*argv[])3 {4 QCoreApplication a(argc, argv);56 //return a.exec();78 libusb_context *usb_context =nullptr;9 libusb_device **dev_list;10 libusb_...

weixin_32239523的博客 678

Flashtool技术深度解析:索尼Xperia设备刷机高级配置实战指南

Flashtool是一款专为索尼Xperia设备设计的专业级刷机工具,支持从早期Xperia X10系列到最新Xperia 1系列的全线设备固件刷写。作为开源刷机解决方案,它通过Java和SWT框架实现了跨平台支持,为技术爱好者和开发人员提供了完整的设备固件管理生态系统。 ## 技术架构与核心模块设计 Flashtool采用模块化架构设计,通过清晰的接口分离实现高内聚低耦合。核心技术栈基于Ja

gitblog_01166的博客 1041

告别驱动烦恼:用libusb-1.0在Windows/Linux/macOS上轻松读写USB设备(附C语言实战代码)

本文详细介绍了如何使用libusb-1.0库在Windows、Linux和macOS三大操作系统上轻松读写USB设备,避免驱动开发的烦恼。通过C语言实战代码演示了设备枚举、数据传输等核心功能,帮助开发者快速实现跨平台USB通信,特别适合嵌入式开发、硬件调试和自动化测试等场景。

506
上一篇: 【JNA实战:Java无缝调用Windows API模拟键盘输入】
下一篇: 【记一次诡异的USB设备开发,动画卡死问题排查:元凶竟是JPG文件】
Stream_Silver
博客等级 码龄5年 73粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值