USB通信协议C++demo

C++Builder串口开发:PComm控件安装与实战应用指南 串口通信作为工业控制、仪器仪表和嵌入式系统开发中的基础技术,通过RS-232/485等物理接口实现设备间的可靠数据传输。其工作原理基于异步串行通信协议,通过配置波特率、数据位、停止位和校验位等参数确保数据准确交换。在C++Builder开发环境中,虽然自带串口组件功能有限,但借助第三方控件如PComm,开发者可以高效处理多线程数据收发、流量控制等复杂场景。PComm封装了底层API,提供了直观的属性、方法和事件驱动模型,显著提升开发效率和程序稳定性,尤其适用于工业自动化、数据采集和硬件调试等应用。本指南聚焦 阅读详情

USB(Universal Serial Bus)通信协议是一种广泛应用于计算机和外部设备之间的串行通信协议,具有热插拔、即插即用、高速传输等特点。

基本架构

  • 主机:通常是计算机或其他具有USB主机控制器的设备,负责管理和控制USB总线上的所有通信。
  • 设备:连接到USB总线上的各种外部设备,如鼠标、键盘、打印机、U盘等。每个设备都有唯一的地址和设备描述符,用于向主机标识自己的功能和特性。
  • 集线器:用于扩展USB接口数量,允许多个设备连接到同一个USB总线上。集线器可以是内置在主机中的,也可以是独立的外部设备。

数据传输类型

  • 控制传输:主要用于主机与设备之间的配置、命令和状态信息的传输。例如,当设备插入USB接口时,主机通过控制传输获取设备的描述符,了解设备的功能和需求,并对设备进行配置。
  • 批量传输:适用于大量数据的传输,如U盘的数据读写。这种传输类型具有较高的数据传输效率,但不保证实时性,数据会在总线上排队等待传输。
  • 中断传输:通常用于需要及时响应的设备,如鼠标和键盘。设备会定期向主机发送中断请求,主机在收到请求后会立即处理,以保证设备的实时性。
  • 等时传输:用于对时间要求严格的实时数据传输,如音频和视频数据。它以固定的时间间隔传输数据,保证数据的连续性和实时性,但不保证数据的准确性,可能会出现少量的数据丢失或错误。

传输过程

  • 建立连接:当设备插入USB接口时,主机通过检测USB总线上的电平变化来发现新设备,并通过一系列的控制传输来获取设备的描述符,进行设备枚举和配置,为设备分配地址和资源。
  • 数据传输:在设备配置完成后,主机和设备之间就可以进行数据传输了。根据不同的传输类型,数据会按照相应的协议格式进行打包和传输。例如,批量传输的数据会被分成多个数据包,每个数据包包含数据和相关的控制信息,然后通过USB总线发送到目标设备。
  • 传输结束:当数据传输完成后,主机或设备会发送相应的结束信号,通知对方传输结束。设备可以选择继续保持连接,等待下一次数据传输,也可以断开连接,节省能源。

数据包格式

  • 令牌包:用于标识数据传输的类型、方向和设备地址等信息,是数据传输的起始标志。常见的令牌包有输入令牌包(IN)、输出令牌包(OUT)和设置令牌包(SETUP)等。
  • 数据包:包含实际要传输的数据内容。根据传输类型和数据量的不同,数据包的大小和格式也有所不同。例如,批量传输的数据包可以包含多个字节的数据,而控制传输的数据包通常较小,只包含一些命令和参数。
  • 握手包:用于确认数据的接收和传输状态。常见的握手包有确认包(ACK)、否定确认包(NAK)和错误包(STALL)等。当设备成功接收到数据时,会发送ACK包给主机;如果数据接收错误或设备忙,则发送NAK包;如果设备出现严重错误,无法继续传输,则发送STALL包。

电源管理

  • USB总线为设备提供电源:设备可以从USB总线上获取电力,以满足其工作需求。根据USB标准,每个USB端口可以提供一定的电流,如USB 2.0端口通常可以提供500mA的电流,USB 3.0端口可以提供900mA的电流。
  • 设备的电源管理:设备可以根据自身的工作状态和需求,向主机请求不同的电源模式,如待机、睡眠和唤醒等。主机也可以通过发送电源管理命令来控制设备的电源状态,以节省能源。

以下是一个使用 libusb 库实现简单 USB 通信的 C++ 示例代码。libusb 是一个跨平台的库,用于访问 USB 设备。

代码示例

#include <iostream>
#include <libusb-1.0/libusb.h>

#define VENDOR_ID 0xXXXX  // 替换为实际的厂商 ID
#define PRODUCT_ID 0xXXXX // 替换为实际的产品 ID

int main() {
    libusb_context *ctx = NULL;
    libusb_device_handle *dev_handle = NULL;
    int r;

    // 初始化 libusb
    r = libusb_init(&ctx);
    if (r < 0) {
        std::cerr << "初始化 libusb 失败: " << libusb_error_name(r) << std::endl;
        return 1;
    }

    // 打开指定的 USB 设备
    dev_handle = libusb_open_device_with_vid_pid(ctx, VENDOR_ID, PRODUCT_ID);
    if (dev_handle == NULL) {
        std::cerr << "无法打开 USB 设备" << std::endl;
        libusb_exit(ctx);
        return 1;
    }

    // 检查设备是否已被内核驱动占用,如果是则释放
    if (libusb_kernel_driver_active(dev_handle, 0) == 1) {
        r = libusb_detach_kernel_driver(dev_handle, 0);
        if (r < 0) {
            std::cerr << "无法释放内核驱动: " << libusb_error_name(r) << std::endl;
            libusb_close(dev_handle);
            libusb_exit(ctx);
            return 1;
        }
    }

    // 声明接口
    r = libusb_claim_interface(dev_handle, 0);
    if (r < 0) {
        std::cerr << "无法声明接口: " << libusb_error_name(r) << std::endl;
        libusb_close(dev_handle);
        libusb_exit(ctx);
        return 1;
    }

    // 发送数据
    unsigned char data_to_send[] = {0x01, 0x02, 0x03, 0x04};
    int transferred;
    r = libusb_bulk_transfer(dev_handle, 0x01, data_to_send, sizeof(data_to_send), &transferred, 5000);
    if (r < 0) {
        std::cerr << "数据发送失败: " << libusb_error_name(r) << std::endl;
    } else {
        std::cout << "成功发送 " << transferred << " 字节数据" << std::endl;
    }

    // 接收数据
    unsigned char received_data[64];
    r = libusb_bulk_transfer(dev_handle, 0x81, received_data, sizeof(received_data), &transferred, 5000);
    if (r < 0) {
        std::cerr << "数据接收失败: " << libusb_error_name(r) << std::endl;
    } else {
        std::cout << "成功接收 " << transferred << " 字节数据: ";
        for (int i = 0; i < transferred; ++i) {
            std::cout << std::hex << static_cast<int>(received_data[i]) << " ";
        }
        std::cout << std::endl;
    }

    // 释放接口
    libusb_release_interface(dev_handle, 0);

    // 关闭设备
    libusb_close(dev_handle);

    // 退出 libusb
    libusb_exit(ctx);

    return 0;
}    

代码解释

  1. 初始化 libusb:调用 libusb_init 函数来初始化 libusb 库。
  2. 打开 USB 设备:使用 libusb_open_device_with_vid_pid 函数根据厂商 ID 和产品 ID 打开指定的 USB 设备。
  3. 释放内核驱动:检查设备是否被内核驱动占用,如果是,则使用 libusb_detach_kernel_driver 函数释放内核驱动。
  4. 声明接口:使用 libusb_claim_interface 函数声明要使用的 USB 接口。
  5. 数据传输:
    • 发送数据:使用 libusb_bulk_transfer 函数进行批量数据发送。
    • 接收数据:同样使用 libusb_bulk_transfer 函数进行批量数据接收。
  6. 释放资源:
    • 使用 libusb_release_interface 函数释放之前声明的接口。
    • 使用 libusb_close 函数关闭 USB 设备。
    • 使用 libusb_exit 函数退出 libusb 库。

注意事项

  • 你需要将 VENDOR_ID 和 PRODUCT_ID 替换为你实际要通信的 USB 设备的厂商 ID 和产品 ID。
  • 编译代码时需要链接 libusb 库,例如使用以下命令:
g++ -o usb_demo usb_communication_demo.cpp -lusb-1.0
  • 运行代码可能需要管理员权限,因为访问 USB 设备通常需要较高的权限。在 Linux 系统中,可以使用 sudo 来运行程序。
C++USB通信。使用hidapi库与控制板通信。C++与hid设备通信。hidapi库的配置与使用。 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、HID是什么?二、使用步骤1.引入库2.获取USB-HID设备3.打开和关闭USB-HID设备4.发送和接收报告5.发送和接收数据总结 前言 这篇文章主要是记录C++与USB-hid设备(即免驱动的usb设备,鼠标、键盘就是hid设备)进行通信,它也是一种USB设备,只不过不需要安装驱动,如果要与非USB-HID设备通信请参考libusb。 libusb首页 github地址 一、HID是什么? USB-HID是Uni 阅读详情

相关推荐

C语言实现串口(USB)的数据收发

C/C++语言实现串口(USB)的数据收发

XiaoCaiDaYong的博客 4732

USB设备通信(Win32, C++)

简单封装USB设备异步读写

FlameCyclone的博客 1510

C++ USB上位机通信开发:从设备枚举到协议解析的避坑指南

USB设备通信是嵌入式联调中绕不开的基础环节,而C++上位机开发往往面临设备枚举、管道管理、数据收发与协议解析等多重复杂问题。理解Windows下HID、CDC与WinUSB的选型差异,掌握SetupAPI设备枚举、环形缓冲接收和帧同步解析的原理,可以有效解决数据丢帧、UI卡死、句柄失效等常见故障。成熟的上位机方案不仅是简单读写,更需要在驱动接口、线程模型与校验策略上做系统设计。这类技术广泛适用于USB HID/CDC设备调试、自动化测试以及工具链集成等场景。本文围绕一套完整的C++ USB通信上位机源码,

weixin_33925615的博客 128

【C/C++】libusb实现ADB的USB通信功能

使用libusb库实现ADB的USB通信功能,方便对该功能进行移植时的调试,以及加深对其工作原理的理解。

牛顿的三棱镜的博客 7067

基于C++ MFC的RS485串口通信上位机Demo完整实现

工业控制现场,RS485总线凭借差分传输的抗干扰能力和长距离通信优势,至今仍是变频器、电表、PLC等设备的主流物理层接口。上位机与这些设备交互时,串口通信是最基础的数据通道,而Windows平台下用C++和MFC封装底层Win32 API,既能高效控制CreateFile、WaitCommEvent等关键函数,又能快速构建轻量级工具界面,尤其适合存量设备多、部署环境受限的工控场景。理解串口打开、DCB参数配置、超时处理及接收线程事件驱动模型,是保障收发稳定、不丢帧、不卡界面的核心。这类技术不仅用于RS485

weixin_29166013的博客 234

C8051F340 USB开发全流程:调试、ISP与C#上位机实战

在嵌入式开发中,USB通信与在线调试是常见需求。C8051F340作为经典的8051内核USB微控制器,集成了USB 2.0控制器与C2调试接口,通过JTAG/C2协议可实现程序下载与实时调试。ISP引导加载机制则让设备在没有调试器的情况下也能通过USB升级固件,大幅提升现场维护效率。结合C#上位机开发,工程师可以构建从设备端到PC端的完整数据交互链路,适用于数据采集、设备控制等场景。这些正是C8051F340 USB工程开发中的核心环节,值得深入掌握。

weixin_30607659的博客 999

STM32 C++开发填坑记:从USB枚举到看门狗的完整收尾实战

嵌入式固件开发中,从能跑的Demo到长期稳定运行的设备,往往需要经历漫长的收尾阶段。以STM32平台为例,开发者常面临外设初始化时序、通信协议健壮性、资源受限下的代码组织等多重挑战。C++语言为MCU开发提供了封装与模板等现代特性,能在不牺牲性能的前提下提升代码可维护性。本文从工程实践角度,梳理了USB设备枚举稳定性、SPI屏幕初始化、定时器捕获精度、看门狗喂狗策略以及掉电保存等高频技术难题的排查思路与解决路径。这些经验不仅适用于桌面环境监测小盒子,也适用于任何对可靠性和长期运行有要求的嵌入式项目,帮助开发

weixin_29165465的博客 2

STM32F103ZET6万年历软件1.0版本DEMO发布

在当今快速发展的信息技术领域,嵌入式系统扮演着至关重要的角色。嵌入式系统开发流程作为一项复杂而系统的工作,涵盖了从产品规划到最终部署的整个生命周期。开发者需要遵循一定的步骤,来确保项目的成功。本章将为读者简要概述嵌入式系统的开发流程,并为后续章节中对特定硬件(如STM32F103ZET6微控制器)和软件工具(如KEIL 4集成开发环境)的深入探讨奠定基础。STM32F103ZET6微控制器属于STMicroelectronics的STM32系列,广泛应用于需要高性能和低功耗的嵌入式系统中。

weixin_35879493的博客 763

STM32嵌入式C++实战:USB封装、超声波测距与CAN故障排查

嵌入式开发中,语言选型常被两类观点撕裂:C极致精简,C++强大但被认为不适合单片机。实际上,在STM32这类资源有限的MCU上,C++的类封装与模板机制可在编译期完成抽象,运行时开销几乎为零,同时显著提升代码可维护性。围绕真实工程中的高频场景——USB设备抽象、超声波测距输入捕获、CAN通信故障排查——可以看到C++如何把外设驱动组织成状态清晰的对象,让中断处理、数据流和错误定位更有条理。从寄存器映射到传感器驱动,再到链路层疑难杂症,C++带来的不是花哨语法,而是工程化确定性。对准备用C++开发STM32的

weixin_29189377的博客 268

C++ USB上位机源码实战:libusb设备枚举与批量传输

USB通信是嵌入式开发中设备联调的基础环节,其核心在于通过libusb等跨平台库实现设备枚举、接口声明与端点配置,进而完成控制传输和批量传输。掌握这些底层机制,能显著提升上位机开发效率,避免重复造轮子。在工业数据采集、自定义USB设备调试等场景中,一套可复用的C++代码骨架尤为关键。本文围绕一份基于libusb的USB上位机源码,拆解从设备枚举到批量传输的完整实现,并分享驱动冲突、传输超时等常见问题的排查经验。

weixin_30036289的博客 225

C++ MFC RS485串口通信Demo:从工程结构到二次开发全解析

串口通信是工控上位机开发的基础技术,通过RS485总线实现设备与计算机的数据交互。其核心原理涉及半双工方向控制、字节流帧解析和线程安全,技术价值在于稳定可靠地完成设备联调与数据采集。典型应用场景包括车间设备参数读取、工控系统集成和课程设计实践。本文基于C++ MFC框架,详细拆解一个完整的RS485串口通信Demo,涵盖端口配置、收发线程、协议解析及避坑经验,助力开发者快速上手二次开发。

weixin_29174141的博客 262

八界机器人C++ SDK实战指南:从架构原理到避障Demo开发

机器人开发中,硬件控制与上层算法的衔接往往被低估。八界机器人SDK(C++版)通过分层架构将底盘运动、传感器接入和任务调度封装为统一API,极大降低了开发门槛。其核心设计围绕线程模型与回调机制展开,开发者需理解数据在独立工作线程中的流转,避免阻塞或重入。在技术价值上,该SDK支持跨平台编译,提供了位移、速度两种运动控制模式和雷达、IMU等传感器订阅回调,使得状态机驱动的避障导航等复杂应用可以高效落地。本文从工程实践出发,结合真实踩坑经验,梳理从环境搭建、接口调用到完整Demo实现的路径,为机器人应用开发者提

weixin_29191669的博客 217

c++ 开发的usb 通信程序,简单易懂

用c++ 开发的usb 通信程序,简单易懂 用c++ 开发的usb 通信程序,简单易懂

基于MFC编写的读写USB_HID设备数据程序:掌握MFC与HID通信精髓

基于MFC编写的读写USB_HID设备数据程序:掌握MFC与HID通信精髓 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 基于MFC编写的读写USB_HID设备数据程序,旨在为开发者提供一个通过MFC框架与USB-HID设备进行数据交互的参考实例。该程序深度展示了如何枚举HID设备、与设备建立通信,以及读写数据的完整过程,为学习与研究USB-HID设备通信提供了宝贵的...

gitblog_06721的博客 1019

C++ USB数据接收与发送

C++ USB数据接收与发送,USB数据接收与发送,USB数据接收与发送

C/C++语言实现串口(USB)的数据收发

C/C++语言实现串口(USB)的数据收发 博客地址:https://blog.youkuaiyun.com/XiaoCaiDaYong/article/details/131828842

上一篇: 数据库的各个范式
下一篇: 泛型lambda表达式和普通lambda表达式的区别
越甲八千
博客等级 码龄11年 2959粉丝 553原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值