当前位置: 首页 > ds >正文

【RP2350】香瓜树莓派RP2350之USB HID

本文最后修改时间:2025年05月10日 01:57

一、本节简介

本节以树莓派pico2开发板为例,举例如何写一个USB HID驱动加进工程里。本例程实现可修改树莓派识别到的名称。

二、实验平台

1、硬件平台

1)树莓派pico2开发板

①树莓派pico2开发板(作为仿真器)

②micro usb数据线

2)电脑

3)香瓜RP2350目标板

4)树莓派5

2、软件平台

1)VS CODE

三、版权声明

1)作者:甜甜的大香瓜

2)声明:喝水不忘挖井人,转载请注明出处。

3)纠错/业务合作:897503845@qq.com

4)香瓜嵌入式之树莓派群:512598061

5)本文出处:原创连载资料《简单粗暴学树莓派》

6)完整开源资料下载地址(电脑端打开):

opengua.taobao.com

四、实验前提

1、在进行本文步骤前,请先阅读以下章节:

1)《简单粗暴学树莓派》的“第一章至第二章”章节

2、在进行本文步骤前,请先实现以下章节:

1)《简单粗暴学树莓派》的《香瓜树莓派RP2350之搭建开发环境(windows)》

2)《简单粗暴学树莓派》的《香瓜树莓派RP2350之新建工程》

五、基础知识

1HID是什么?

答:HID(Human Interface Device人机接口设备)是USB协议的一种,键盘、鼠标都是USB HID设备。电脑里预装了HID的驱动,所以HID设备可实现在电脑上即插即用。

六、硬件原理

1、硬件连接

实际只接了4根线,3.3V、GND、CLK、DIO

注意: 给pico2供电时接VSYS,是因为pico2会再经过稳压到3.3v供电给pico2目标板的rp2350。而香瓜使用的板子仿真接口是直接供电给rp2350的,所以需要直连3.3v。

2、原理图

RP2350的USB信号连接到板载的USB接口上

七、实验步骤

1、在VS CODE工程文件夹下,添加驱动GUA_USBtoUart.c(VS CODE会自动加载)

//**********************************************************************

//name:         GUA_USBtoUart.c

//introduce:    USB转串口驱动

//author:       opengua     

//email:        897503845@qq.com  

//QQ group:     香瓜嵌入式之树莓派群(512598061)

//shop:         opengua.taobao.com

//changetime:   2025.05.22

//**********************************************************************

#include "pico/stdlib.h"

#include "GUA_USBtoUart.h"

#include "main.h"

/*********************全局变量************************/

uint8_t gaGUA_USBtoUART_Rx_Buff[GUA_USB_TO_UART_RX_SIZE] = {0};

volatile uint8_t gGUA_USBtoUART_Rx_Length = 0;       //必须加volatile,否则会被优化

/*********************内部函数************************/

static void GUA_USBtoRx_CDC_Rx_Callback(void);

//**********************************************************************

//name:         GUA_USBtoUart_Send

//introduce:    初始化

//parameter:    pGUA_Data:发送数据缓冲区

//              nGUA_Len:数据长度

//return:       none

//author:       opengua

//email:        897503845@qq.com

//QQ group:     香瓜嵌入式之树莓派群(512598061)

//shop:         opengua.taobao.com

//changetime:   2025.05.22

//**********************************************************************

void GUA_USBtoUart_Send(uint8_t *pGUA_Data, uint8_t nGUA_Len)

{

    //如果当前USB连接中

    if(tud_cdc_connected())

    {

        //通过usb的cdc发出数据

        tud_cdc_write(pGUA_Data, nGUA_Len);

        //清空cdc传输通道数据

        tud_cdc_write_flush();

    }

}

//**********************************************************************

//name:         GUA_USBtoRx_CDC_Rx_Callback

//introduce:    接收数据

//parameter:    none

//return:       none

//author:       opengua

//email:        897503845@qq.com

//QQ group:     香瓜嵌入式之树莓派群(512598061)

//shop:         opengua.taobao.com

//changetime:   2025.05.22

//**********************************************************************

static void GUA_USBtoRx_CDC_Rx_Callback(void)

{

    gGUA_USBtoUART_Rx_Length = tud_cdc_read(gaGUA_USBtoUART_Rx_Buff, sizeof(gaGUA_USBtoUART_Rx_Buff));

    if(gGUA_USBtoUART_Rx_Length > 0)

    {

        //清空cdc传输通道的数据

        tud_cdc_write_flush();

        //到对应的数据处理

        gnGUA_Function = FUNC_GUA_COMMUNICAION_PROCESS_EVT;

    }

}

//**********************************************************************

//name:         tud_hid_get_report_cb

//introduce:    电脑读报告时的回调

//parameter:    none

//return:       none

//author:       opengua   

//email:        897503845@qq.com  

//QQ group:     香瓜嵌入式之树莓派群(512598061)

//shop:         opengua.taobao.com

//changetime:   2025.02.18

//**********************************************************************

uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)

{

    (void) instance;

    return 0;

}

//**********************************************************************

//name:         tud_hid_set_report_cb

//introduce:    电脑写报告时的回调

//parameter:    none

//return:       none

//author:       opengua   

//email:        897503845@qq.com  

//QQ group:     香瓜嵌入式之树莓派群(512598061)

//shop:         opengua.taobao.com

//changetime:   2025.02.18

//**********************************************************************

void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)

{

  (void) instance;

}

//**********************************************************************

//name:         GUA_USBtoUart_Poll

//introduce:    轮询 CDC 数据

//parameter:    none

//return:       none

//author:       opengua

//email:        897503845@qq.com

//QQ group:     香瓜嵌入式之树莓派群(512598061)

//shop:         opengua.taobao.com

//changetime:   2025.05.22

//**********************************************************************

void GUA_USBtoUart_Poll(void)

{

    //处理USB任务 

    tud_task();

    //检测缓冲区是否有可读数据

    if(tud_cdc_available())

    {

        //CDC 接收回调函数

        GUA_USBtoRx_CDC_Rx_Callback();

    }

    //定期清空发送缓冲区

    tud_cdc_write_flush();

}

//**********************************************************************

//name:         GUA_USBtoUart_Init

//introduce:    初始化

//parameter:    none

//return:       none

//author:       opengua

//email:        897503845@qq.com

//QQ group:     香瓜嵌入式之树莓派群(512598061)

//shop:         opengua.taobao.com

//changetime:   2025.02.18

//**********************************************************************

//需要在CMakeLists.txt文件中打开usb(同时关闭串口为0):pico_enable_stdio_usb(ArgonOne_RP2350 1)

void GUA_USBtoUart_Init(void)

{

    //初始化usb转串口 这条不能被调用两次,避免低功耗唤醒后被再次初始化,所以本函数得放到GUA_Init函数外

    stdio_init_all(); 

    //初始化板上外设如端口和USB

    board_init();

    //初始化USB设备栈,端口0

    tud_init(BOARD_TUD_RHPORT);

    //不确定是否需要,例程有,不过好像有它没它都一样

    if(board_init_after_tusb)

    {

    board_init_after_tusb();

    }

}

注意USB的回调函数里有香瓜的项目变量,添加后需要增删一些报错内容。

2、在VS CODE工程文件夹下,添加驱动GUA_USBtoUart.h(VS CODE会自动加载)

//**********************************************************************

//name:         GUA_USBtoUart.h

//introduce:    USB转串口驱动头文件

//author:       opengua     

//email:        897503845@qq.com  

//QQ group:     香瓜嵌入式之树莓派群(512598061)

//shop:         opengua.taobao.com

//changetime:   2025.02.18

//**********************************************************************

#ifndef _GUA_USB_TO_UART_H_

#define _GUA_USB_TO_UART_H_

/*********************头文件************************/

#include <stdio.h>

#include "usb_descriptors.h"

#include "tusb.h"

#include "pico/stdio.h"

#include "bsp/board_api.h"

/*********************宏定义************************/

//串口缓冲区大小

#define GUA_USB_TO_UART_RX_SIZE     128

/*********************全局变量************************/

extern uint8_t gaGUA_USBtoUART_Rx_Buff[GUA_USB_TO_UART_RX_SIZE];

volatile extern uint8_t gGUA_USBtoUART_Rx_Length;

/*********************外部函数************************/

extern void GUA_USBtoUart_Send(uint8_t *pGUA_Data, uint8_t nGUA_Len);

extern void GUA_USBtoUart_Poll(void);

extern void GUA_USBtoUart_Init(void);

#endif

3、在VS CODE工程文件夹下,添加驱动usb_descriptors.c(VS CODE会自动加载)

#include "bsp/board_api.h"

#include "tusb.h"

#include "usb_descriptors.h"

#define HID_PD_IPRODUCT              0x01 // FEATURE ONLY

#define HID_PD_SERIAL                0x02 // FEATURE ONLY

#define HID_PD_MANUFACTURER          0x03 // FEATURE ONLY

#define IDEVICECHEMISTRY             0x04

#define IOEMVENDOR                   0x05

#define HID_PD_RECHARGEABLE          0x06 // FEATURE ONLY

//#define HID_PD_PRESENTSTATUS         0x07 // INPUT OR FEATURE(required by Windows)

#define HID_PD_REMAINTIMELIMIT       0x08

#define HID_PD_MANUFACTUREDATE       0x09

#define HID_PD_CONFIGVOLTAGE         0x0A // 10 FEATURE ONLY

#define HID_PD_VOLTAGE               0x0B // 11 INPUT (NA) OR FEATURE(implemented)

//#define HID_PD_REMAININGCAPACITY     0x0C // 12 INPUT OR FEATURE(required by Windows)

#define HID_PD_RUNTIMETOEMPTY        0x0D

#define HID_PD_FULLCHRGECAPACITY     0x0E // 14 FEATURE ONLY. Last Full Charge Capacity

#define HID_PD_WARNCAPACITYLIMIT     0x0F

#define HID_PD_CPCTYGRANULARITY1     0x10

#define HID_PD_REMNCAPACITYLIMIT     0x11

#define HID_PD_DELAYBE4SHUTDOWN      0x12 // 18 FEATURE ONLY

#define HID_PD_DELAYBE4REBOOT        0x13

#define HID_PD_AUDIBLEALARMCTRL      0x14 // 20 INPUT OR FEATURE

#define HID_PD_CURRENT               0x15 // 21 FEATURE ONLY

#define HID_PD_CAPACITYMODE          0x16

#define HID_PD_DESIGNCAPACITY        0x17

#define HID_PD_CPCTYGRANULARITY2     0x18

#define HID_PD_AVERAGETIME2FULL      0x1A

#define HID_PD_AVERAGECURRENT        0x1B

#define HID_PD_AVERAGETIME2EMPTY     0x1C

#define HID_PD_IDEVICECHEMISTRY      0x1F // Feature

#define HID_PD_IOEMINFORMATION       0x20 // Feature

#define IPRODUCT 0x02

#define ISERIAL 0x03

#define IMANUFACTURER 0x01

/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.

 * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.

 *

 * Auto ProductID layout's Bitmap:

 *   [MSB]         HID | MSC | CDC          [LSB]

 */

#define _PID_MAP(itf, n)  ( (CFG_TUD_##itf) << (n) )

#define USB_PID           (0x4001 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \

                           _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )

#define USB_VID   0xCafe

#define USB_BCD   0x0200

//--------------------------------------------------------------------+

// Device Descriptors

//--------------------------------------------------------------------+

tusb_desc_device_t const desc_device =

{

#if 0

    .bLength            = sizeof(tusb_desc_device_t),

    .bDescriptorType    = TUSB_DESC_DEVICE,

    .bcdUSB             = USB_BCD,

    .bDeviceClass       = 0x00,

    .bDeviceSubClass    = 0x00,

    .bDeviceProtocol    = 0x00,

    .bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE,

    .idVendor           = USB_VID,

    .idProduct          = USB_PID,

    .bcdDevice          = 0x0100,

    .iManufacturer      = 0x01,

    .iProduct           = 0x02,

    .iSerialNumber      = 0x03,

    .bNumConfigurations = 0x01

#else

    // .bLength = sizeof(tusb_desc_device_t),

    // .bDescriptorType = TUSB_DESC_DEVICE,

    // .bcdUSB = 0x0200, // USB 2.0

    // .bDeviceClass = 0x00,

    // .bDeviceSubClass = 0x00,

    // .bDeviceProtocol = 0x00,

    // .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, // 通常为 64

    // .idVendor = 0x1D6B, // Linux Foundation

    // .idProduct = 0x0104, // HID UPS

    // .bcdDevice = 0x0100,

    // .iManufacturer = 0x01,

    // .iProduct = 0x02,

    // .iSerialNumber = 0x03,

    // .bNumConfigurations = 0x01

    .bLength            = sizeof(tusb_desc_device_t),

    .bDescriptorType    = TUSB_DESC_DEVICE,

    .bcdUSB             = 0x0200,

    .bDeviceClass       = TUSB_CLASS_MISC,  // 复合设备类

    .bDeviceSubClass    = MISC_SUBCLASS_COMMON,

    .bDeviceProtocol    = MISC_PROTOCOL_IAD, // 使用IAD

    .bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE,

    .idVendor           = 0x1D6B,          // Linux Foundation VID

    .idProduct          = 0x0104,          // HID UPS PID

    .bcdDevice          = 0x0100,

    .iManufacturer      = 0x01,

    .iProduct           = 0x02,

    .iSerialNumber      = 0x03,

    .bNumConfigurations = 0x01

#endif

};

//当接收到GET DEVICE DESCRIPTOR请求时,它会返回设备描述符的指针。

uint8_t const * tud_descriptor_device_cb(void)

{

  return (uint8_t const *) &desc_device;

}

//--------------------------------------------------------------------+

// HID Report Descriptor

//--------------------------------------------------------------------+

//每种类型的设备都有自己特定的HID报告布局。

#if 0

uint8_t const desc_hid_report[] =

{

  TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD         )),

  TUD_HID_REPORT_DESC_MOUSE   ( HID_REPORT_ID(REPORT_ID_MOUSE            )),

  TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL )),

  TUD_HID_REPORT_DESC_GAMEPAD ( HID_REPORT_ID(REPORT_ID_GAMEPAD          ))

};

#else

uint8_t const desc_hid_report[] =

{

  0x05, 0x84, // USAGE_PAGE (Power Device)

  0x09, 0x04, // USAGE (UPS)

  0xA1, 0x01, // COLLECTION (Application)

  0x09, 0x24, //   USAGE (Sink)

  0xA1, 0x02, //   COLLECTION (Logical)

  0x75, 0x08, //     REPORT_SIZE (8)

  0x95, 0x01, //     REPORT_COUNT (1)

  0x15, 0x00, //     LOGICAL_MINIMUM (0)

  0x26, 0xFF, 0x00, //     LOGICAL_MAXIMUM (255)

  0x85, HID_PD_IPRODUCT, //     REPORT_ID (1)

  0x09, 0xFE, //     USAGE (iProduct)

  0x79, IPRODUCT, //     STRING INDEX (2)

  0xB1, 0x23, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Nonvolatile, Bitfield)

  0x85, HID_PD_SERIAL, //     REPORT_ID (2)

  0x09, 0xFF, //     USAGE (iSerialNumber)

  0x79, ISERIAL, //  STRING INDEX (3)

  0xB1, 0x23, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Nonvolatile, Bitfield)

  0x85, HID_PD_MANUFACTURER, //     REPORT_ID (3)

  0x09, 0xFD, //     USAGE (iManufacturer)

  0x79, IMANUFACTURER, //     STRING INDEX (1)

  0xB1, 0x23, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Nonvolatile, Bitfield)

  0x05, 0x85, //     USAGE_PAGE (Battery System) ====================

  0x85, HID_PD_RECHARGEABLE, //     REPORT_ID (6)

  0x09, 0x8B, //     USAGE (Rechargable)                 

  0xB1, 0x23, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Nonvolatile, Bitfield)

  0x85, HID_PD_IDEVICECHEMISTRY, //     REPORT_ID (31)

  0x09, 0x89, //     USAGE (iDeviceChemistry)

  0x79, IDEVICECHEMISTRY, //     STRING INDEX (4)

  0xB1, 0x23, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Nonvolatile, Bitfield)

  0x85, HID_PD_IOEMINFORMATION,  //     REPORT_ID (32)

  0x09, 0x8F, //     USAGE (iOEMInformation)

  0x79, IOEMVENDOR, //     STRING INDEX (5)

  0xB1, 0x23, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Nonvolatile, Bitfield)

#if 0 

  0x85, HID_PD_CAPACITYMODE, //     REPORT_ID (22)

  0x09, 0x2C, //     USAGE (CapacityMode)

  0xB1, 0x23, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Nonvolatile, Bitfield)

#else

  0x85, HID_PD_CAPACITYMODE, // REPORT_ID (22)

  0x09, 0x2C, // USAGE (CapacityMode)

  0x15, 0x00, // LOGICAL_MINIMUM (0)

  0x25, 0x01, // LOGICAL_MAXIMUM (1) <- 0表示mAh,1表示百分比

  0x75, 0x08, // REPORT_SIZE (8)

  0x95, 0x01, // REPORT_COUNT (1)

  0xB1, 0x22, // FEATURE (Data, Variable, Absolute)

#endif

  0x85, HID_PD_CPCTYGRANULARITY1, //     REPORT_ID (16)

  0x09, 0x8D, //     USAGE (CapacityGranularity1)

  0x26, 0x64,0x00, //     LOGICAL_MAXIMUM (100)   

  0xB1, 0x22, //     FEATURE (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Nonvolatile, Bitfield)

  0x85, HID_PD_CPCTYGRANULARITY2, //     REPORT_ID (24)

  0x09, 0x8E, //     USAGE (CapacityGranularity2)

  0xB1, 0x23, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Nonvolatile, Bitfield)

  0x85, HID_PD_FULLCHRGECAPACITY, //     REPORT_ID (14)       

  0x09, 0x67, //     USAGE (FullChargeCapacity)

  0xB1, 0x83, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x85, HID_PD_DESIGNCAPACITY, //     REPORT_ID (23)

  0x09, 0x83, //     USAGE (DesignCapacity)

  0xB1, 0x83, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

#if 0

  0x85, HID_PD_REMAININGCAPACITY, //     REPORT_ID (12)

  0x09, 0x66, //     USAGE (RemainingCapacity)

  0x81, 0xA3, //     INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x66, //     USAGE (RemainingCapacity)

  0xB1, 0xA3, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

#else

  0x85, HID_PD_REMAININGCAPACITY, //     REPORT_ID (12)

  0x09, 0x66, //     USAGE (RemainingCapacity)

  0x15, 0x00, //     LOGICAL_MINIMUM (0)

  0x25, 0x64, //     LOGICAL_MAXIMUM (100)

  0x75, 0x08, //     REPORT_SIZE (8)

  0x95, 0x01, //     REPORT_COUNT (1)

  0x81, 0x02, //     INPUT (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x66, //     USAGE (RemainingCapacity)

  0xB1, 0x02, //     FEATURE (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

 

#endif

  0x85, HID_PD_WARNCAPACITYLIMIT, //     REPORT_ID (15)

  0x09, 0x8C, //     USAGE (WarningCapacityLimit)

  0xB1, 0xA2, //     FEATURE (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x85, HID_PD_REMNCAPACITYLIMIT, //     REPORT_ID (17)

  0x09, 0x29, //     USAGE (RemainingCapacityLimit)

  0xB1, 0xA2, //     FEATURE (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x85, HID_PD_MANUFACTUREDATE, //     REPORT_ID (9)

  0x09, 0x85, //     USAGE (ManufacturerDate)

  0x75, 0x10, //     REPORT_SIZE (16)

  0x27, 0xFF, 0xFF, 0x00, 0x00, //     LOGICAL_MAXIMUM (65534)

  0xB1, 0xA3, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x85, HID_PD_AVERAGETIME2FULL, //     REPORT_ID (26)

  0x09, 0x6A, //     USAGE (AverageTimeToFull)

  0x27, 0xFF, 0xFF, 0x00, 0x00, //     LOGICAL_MAXIMUM (65534)

  0x66, 0x01, 0x10, //     UNIT (Seconds)

  0x55, 0x00, //     UNIT_EXPONENT (0)

  0xB1, 0xA3, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x85, HID_PD_AVERAGETIME2EMPTY, //     REPORT_ID (28)

  0x09, 0x69, //     USAGE (AverageTimeToEmpty) 

  0x81, 0xA3, //     INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x69, //     USAGE (AverageTimeToEmpty)

  0xB1, 0xA3, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x85, HID_PD_RUNTIMETOEMPTY, //     REPORT_ID (13)   

  0x09, 0x68, //     USAGE (RunTimeToEmpty) 

  0x81, 0xA3, //     INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x68, //     USAGE (RunTimeToEmpty)

  0xB1, 0xA3, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)     

  0x85, HID_PD_REMAINTIMELIMIT, //     REPORT_ID (8)

  0x09, 0x2A, //     USAGE (RemainingTimeLimit)

  0x75, 0x10, //     REPORT_SIZE (16)

  0x27, 0x64, 0x05, 0x00, 0x00, //     LOGICAL_MAXIMUM (1380)

  0x16, 0x78, 0x00, //     LOGICAL_MINIMUM (120)

  0x81, 0x22, //     INPUT (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x2A, //     USAGE (RemainingTimeLimit)

  0xB1, 0xA2, //     FEATURE (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x05, 0x84, //     USAGE_PAGE (Power Device) ====================

  0x85, HID_PD_DELAYBE4SHUTDOWN, //     REPORT_ID (18)

  0x09, 0x57, //     USAGE (DelayBeforeShutdown)

  0x16, 0x00, 0x80, //     LOGICAL_MINIMUM (-32768)

  0x27, 0xFF, 0x7F, 0x00, 0x00, //     LOGICAL_MAXIMUM (32767)

  0xB1, 0xA2, //     FEATURE (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x85, HID_PD_DELAYBE4REBOOT, //     REPORT_ID (19)

  0x09, 0x55, //     USAGE (DelayBeforeReboot)

  0xB1, 0xA2, //     FEATURE (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x85, HID_PD_CONFIGVOLTAGE, //     REPORT_ID (10)

  0x09, 0x40, //     USAGE (ConfigVoltage)

  0x15, 0x00, //     LOGICAL_MINIMUM (0)

  0x27, 0xFF, 0xFF, 0x00, 0x00, //     LOGICAL_MAXIMUM (65535)

  0x67, 0x21, 0xD1, 0xF0, 0x00, //     UNIT (Centivolts)

  0x55, 0x05, //     UNIT_EXPONENT (5)

  0xB1, 0x23, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Nonvolatile, Bitfield)

  0x85, HID_PD_VOLTAGE, //     REPORT_ID (11)

  0x09, 0x30, //     USAGE (Voltage)

  0x81, 0xA3, //     INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x30, //     USAGE (Voltage)

  0xB1, 0xA3, //     FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x85, HID_PD_AUDIBLEALARMCTRL, //     REPORT_ID (20)

  0x09, 0x5A, //     USAGE (AudibleAlarmControl)

  0x75, 0x08, //     REPORT_SIZE (8)

  0x15, 0x01, //     LOGICAL_MINIMUM (1)

  0x25, 0x03, //     LOGICAL_MAXIMUM (3)

  0x65, 0x00, //     UNIT (0)

  0x55, 0x00, //     UNIT_EXPONENT (0)

  0x81, 0x22, //     INPUT (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x5A, //     USAGE (AudibleAlarmControl)

  0xB1, 0xA2, //     FEATURE (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x09, 0x02, //     USAGE (PresentStatus)

  0xA1, 0x02, //     COLLECTION (Logical)

  0x85, HID_PD_PRESENTSTATUS, //       REPORT_ID (7)

  0x05, 0x85, //       USAGE_PAGE (Battery System) =================

  0x09, 0x44, //       USAGE (Charging)

  0x75, 0x01, //       REPORT_SIZE (1)

  0x15, 0x00, //       LOGICAL_MINIMUM (0)

  0x25, 0x01, //       LOGICAL_MAXIMUM (1)

  0x81, 0xA3, //       INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x44, //       USAGE (Charging)

  0xB1, 0xA3, //       FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x09, 0x45, //       USAGE (Discharging)

  0x81, 0xA3, //       INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x45, //       USAGE (Discharging)

  0xB1, 0xA3, //       FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x09, 0xD0, //       USAGE (ACPresent)

  0x81, 0xA3, //       INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0xD0, //       USAGE (ACPresent)

  0xB1, 0xA3, //       FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x09, 0xD1, //       USAGE (BatteryPresent)

  0x81, 0xA3, //       INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0xD1, //       USAGE (BatteryPresent)

  0xB1, 0xA3, //       FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x09, 0x42, //       USAGE (BelowRemainingCapacityLimit)

  0x81, 0xA3, //       INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x42, //       USAGE (BelowRemainingCapacityLimit)

  0xB1, 0xA3, //       FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x09, 0x43, //       USAGE (RemainingTimeLimitExpired)

  0x81, 0xA2, //       INPUT (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x43, //       USAGE (RemainingTimeLimitExpired)

  0xB1, 0xA2, //       FEATURE (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield) 

  0x09, 0x4B, //       USAGE (NeedReplacement)

  0x81, 0xA3, //       INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x4B, //       USAGE (NeedReplacement)

  0xB1, 0xA3, //       FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)   

  0x09, 0xDB, //       USAGE (VoltageNotRegulated)

  0x81, 0xA3, //       INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0xDB, //       USAGE (VoltageNotRegulated)

  0xB1, 0xA3, //       FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x09, 0x46, //       USAGE (FullyCharged)

  0x81, 0xA3, //       INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x46, //       USAGE (FullyCharged)

  0xB1, 0xA3, //       FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x09, 0x47, //       USAGE (FullyDischarged)

  0x81, 0xA3, //       INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x47, //       USAGE (FullyDischarged)

  0xB1, 0xA3, //       FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)   

  0x05, 0x84, //       USAGE_PAGE (Power Device) =================

  0x09, 0x68, //       USAGE (ShutdownRequested)

  0x81, 0xA2, //       INPUT (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x68, //       USAGE (ShutdownRequested)

  0xB1, 0xA2, //       FEATURE (Data, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x09, 0x69, //       USAGE (ShutdownImminent)

  0x81, 0xA3, //       INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x69, //       USAGE (ShutdownImminent)

  0xB1, 0xA3, //       FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x09, 0x73, //       USAGE (CommunicationLost)

  0x81, 0xA3, //       INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x73, //       USAGE (CommunicationLost)

  0xB1, 0xA3, //       FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x09, 0x65, //       USAGE (Overload)

  0x81, 0xA3, //       INPUT (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Bitfield)

  0x09, 0x65, //       USAGE (Overload)

  0xB1, 0xA3, //       FEATURE (Constant, Variable, Absolute, No Wrap, Linear, No Preferred, No Null Position, Volatile, Bitfield)

  0x95, 0x02, //       REPORT_COUNT (2) // padding bits to make the report byte aligned

  0x81, 0x01, //       INPUT (Constant, Array, Absolute)

  0xB1, 0x01, //       FEATURE (Constant, Array, Absolute, No Wrap, Linear, Preferred State, No Null Position, Nonvolatile, Bitfield)

  0xC0,       //     END_COLLECTION

  0xC0,       //   END_COLLECTION

  0xC0        // END_COLLECTION

};

#endif

//当接收到GET HID报告描述符时调用

//应用返回指向描述符的指针

//描述符内容必须存在足够长的时间以完成传输

uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance)

{

  (void) instance;

  return desc_hid_report;

}

//--------------------------------------------------------------------+

// Configuration Descriptor

//--------------------------------------------------------------------+

enum

{

  ITF_NUM_CDC = 0,

  ITF_NUM_CDC_DATA,

  ITF_NUM_HID,

  ITF_NUM_TOTAL

};

// 修改配置描述符

enum {

    EPNUM_CDC_NOTIF = 1,  // 0x81 (IN端点)

    EPNUM_CDC_OUT    = 2, // 0x02 (OUT端点)

    EPNUM_CDC_IN     = 3, // 0x83 (IN端点)

    EPNUM_HID_IN     = 4  // 0x84 (IN端点)

};

#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_DESC_LEN)

#define EPNUM_HID   0x81

//定义了配置描述符

uint8_t const desc_configuration[] =

{

    // 配置描述符头

    TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0,

        TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_DESC_LEN,

        TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 500),

    // CDC接口描述符(使用IAD)

    TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4,

        0x81, 8,      // EP1 (通知), 8字节大小

        0x02, 0x83, 64), // EP2 (OUT), EP3 (IN)

    // HID接口描述符

    TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0,

        HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report),

        0x84, 64, 10) // EP4 (IN)

 

};

#if TUD_OPT_HIGH_SPEED

// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration

// other speed configuration

uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];

// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed

tusb_desc_device_qualifier_t const desc_device_qualifier =

{

  .bLength            = sizeof(tusb_desc_device_qualifier_t),

  .bDescriptorType    = TUSB_DESC_DEVICE_QUALIFIER,

  .bcdUSB             = USB_BCD,

  .bDeviceClass       = 0x00,

  .bDeviceSubClass    = 0x00,

  .bDeviceProtocol    = 0x00,

  .bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE,

  .bNumConfigurations = 0x01,

  .bReserved          = 0x00

};

// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request

// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.

// device_qualifier descriptor describes information about a high-speed capable device that would

// change if the device were operating at the other speed. If not highspeed capable stall this request.

uint8_t const* tud_descriptor_device_qualifier_cb(void)

{

  return (uint8_t const*) &desc_device_qualifier;

}

// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request

// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete

// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa

uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)

{

  (void) index; // for multiple configurations

  // other speed config is basically configuration with type = OHER_SPEED_CONFIG

  memcpy(desc_other_speed_config, desc_configuration, CONFIG_TOTAL_LEN);

  desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;

  // this example use the same configuration for both high and full speed mode

  return desc_other_speed_config;

}

#endif // highspeed

// Invoked when received GET CONFIGURATION DESCRIPTOR

// Application return pointer to descriptor

// Descriptor contents must exist long enough for transfer to complete

uint8_t const * tud_descriptor_configuration_cb(uint8_t index)

{

  (void) index; // for multiple configurations

  // This example use the same configuration for both high and full speed mode

  return desc_configuration;

}

//--------------------------------------------------------------------+

// String Descriptors

//--------------------------------------------------------------------+

// String Descriptor Index

enum {

  STRID_LANGID = 0,   //语言ID

  STRID_MANUFACTURER, //制造商字符串索引

  STRID_PRODUCT,      //产品字符串索引。

  STRID_SERIAL,       //序列号字符串索引。

};

//指向字符串描述符的指针数组

char const *string_desc_arr[] =

{

  (const char[]) { 0x09, 0x04 },    // 0: 支持的语言是英语(0x0409)

  "Argon",                      // 1: 制造商

  "Argon_USB",                     // 2: 产品

  NULL,                             // 3: 如果可以的话,序列将使用唯一的ID

};

static uint16_t _desc_str[32 + 1];

//当接收到GET字符串描述符请求时调用

//应用程序返回指向描述符的指针,其内容必须存在足够长的时间以完成传输

uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {

  (void) langid;

  size_t chr_count;

  switch ( index )

  {

    //对于 STRID_LANGID(0),返回语言 ID。

    case STRID_LANGID:

      memcpy(&_desc_str[1], string_desc_arr[0], 2);

      chr_count = 1;

      break;

    //对于 STRID_SERIAL(3),调用 board_usb_get_serial 获取唯一序列号。

    case STRID_SERIAL:

      chr_count = board_usb_get_serial(_desc_str + 1, 32);

      break;

    将名字变成字符串,并转换为UTF-16格式返回

    default:

      if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;

      const char *str = string_desc_arr[index];

      // 最大长度

      chr_count = strlen(str);

      size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; //-1表示字符串类型

      if ( chr_count > max_count ) chr_count = max_count;

      // 将ASCII字符串转换UTF-16

      for ( size_t i = 0; i < chr_count; i++ ) {

        _desc_str[1 + i] = str[i];

      }

      break;

  }

  // 第一个字节是长度(包括头),第二个字节是字符串类型

  _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));

  return _desc_str;

}

4、在VS CODE工程文件夹下,添加驱动usb_descriptors.h(VS CODE会自动加载)

#ifndef USB_DESCRIPTORS_H_

#define USB_DESCRIPTORS_H_

enum

{

  REPORT_ID_KEYBOARD = 1,

  REPORT_ID_MOUSE,

  REPORT_ID_CONSUMER_CONTROL,

  REPORT_ID_GAMEPAD,

  HID_PD_REMAININGCAPACITY = 0x0C, // 电池剩余容量报告 ID

  HID_PD_PRESENTSTATUS = 0x07,     // 当前状态报告 ID

  REPORT_ID_COUNT

};

#endif /* USB_DESCRIPTORS_H_ */

5、添加对应驱动文件名称

6、打开USB开关、关闭串口开关(只能打开一个)

7、添加库

8、添加配置(CMakeLists.txt中)

# 添加TinyUSB配置

target_compile_definitions(ArgonOne_RP2350 PRIVATE

    CFG_TUD_CDC=1

    CFG_TUD_HID=1

    CFG_TUD_CDC_RX_BUFSIZE=256

    CFG_TUD_CDC_TX_BUFSIZE=256

)

9、在应用层中调用

1)添加驱动头文件(main.c中)

#include "GUA_USBtoUart.h"

2)添加驱动初始化代码1(main.c的main函数中)

    //串口转USB初始化

    GUA_USBtoUart_Init();

注意这个函数不能被调用两次,避免低功耗唤醒后被再次初始化,所以这条放到GUA_Init函数外

八、实验结果

用USB连接设备和树莓派,编译并仿真,全速运行。

因此实验成功。

http://www.xdnf.cn/news/9514.html

相关文章:

  • 《P1763 埃及分数》
  • Acrobat Reader 无法在 Windows 11及10 中打开的5种修复方法
  • 数据库表添加索引
  • STM32 Modbus RTU从机开发实战:核心实现与五大调试陷阱解析
  • 什么是Windows内存压缩? win10/11系统启用和禁用内存压缩的教程
  • HTB-Puppy
  • DAY 38 Dataset和Dataloader类
  • Linux网络编程(一)
  • 医疗影像检测系统设计与实现
  • open3d保存为pcl可以读取的ply点云
  • Windows 子系统 WSL 中宝塔安装 supervisor 启动失败解决方案
  • 《计算机组成原理》第 1 章 - 计算机系统概论
  • 工控安全审计与网络流量监控系统的协同防御
  • ‌CDGP|企业数据治理:莫让“打补丁”成为常态
  • STL容器使用中的常见问题解析
  • 辛格迪客户案例 | 博福-益普生实施YonSuite,同步开展计算机化系统验证(CSV)
  • Druid连接池使用和源码分析
  • 为Windows用户量身定制的监控方案
  • 通过 API 获取 1688 平台订单接口的技术实现
  • LeetCode 118 题解--杨辉三角
  • 软考 系统架构设计师系列知识点之杂项集萃(77)
  • 1435系列信号发生器
  • 2025年上半年软考系统架构设计师--案例分析试题与答案
  • python 生成复杂表格,自动分页等功能
  • 自动驾驶规划控制教程——不确定环境下的决策规划
  • 火柴INIBOX矿机实测850M算力即将改写Initverse挖矿规则
  • 模型可信度
  • 缩量资金迁徙下的短期博弈
  • phpstudy(1) -- 记录
  • Orpheus-TTS:AI文本转语音,免费好用的TTS系统