STM32 USB使用记录:HID类设备(后篇)
文章目录
- 目的
- 基础说明
- 项目构建与代码调整
- 接收发送代码与测试
- 示例链接
- 报告描述符
- 总结
目的
接上篇: 《STM32 USB使用记录:HID类设备(前篇)》
USB HID 类的设备有个比较大的好处是大部分时候接入主机中都是可以免驱使用的。这篇文章将介绍下 STM32 中实现 USB HID 双向透传功能,结合免驱的特点,这在实际工作中是比较常用的。
基础说明
在上一篇文章中简单了解接触了下HID设备,了解了USB设备的各种描述符概念。在这篇文章追中我们要制作一个自定义的HID设备,实现双向透传功能,主要就是要调整配置描述符、端口、报告描述符等内容。
项目构建与代码调整
首先使用Cube工具来生成基础的项目,其它内容和上一篇文章一样,唯一不同的是 USB_DEVICE
这里选用 Custom Human Interface Device Class(HID)
:
生成的项目和上篇文章中差不多:
因为是自定义的HID设备,所以报告描述符需要自己准备,这里修改 usbd_custom_hid_if.c
中的报告描述符实现双向透传功能:
/** Usb HID report descriptor. */
__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
0x09, 0x00, // Usage (0x00)
0xA1, 0x01, // Collection (Application)
0x09, 0x01, // Usage (0x01)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x40, // Report Count (64)
0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x02, // Usage (0x02)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x40, // Report Count (64)
0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
// 34 bytes
};
然后需要修改 usbd_conf.h
中一些定义值:
/*---------- 接收缓冲区大小 -----------*/
/*---------- 对于全速设备收和发一个包最大都为64字节 -----------*/
#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 64U
/*---------- 报告描述符长度 -----------*/
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE 34U
/*---------- 端电查询时间间隔 -----------*/
/*---------- 对于全速设备该值为1表示最快可以每1ms通讯一次 -----------*/
#define CUSTOM_HID_FS_BINTERVAL 0x5U
/*---------- -----------*/
还需要修改 usbd_customhid.h
中的定义值:
// 接收一个包最大为64字节
#define CUSTOM_HID_EPIN_SIZE 0x40U
// 发送一个包最大为64字节
#define CUSTOM_HID_EPOUT_SIZE 0x40U
上面的定义值的调整也可以在Cube工具中直接进行配置。
接收发送代码与测试
在 usbd_custom_hid_if.c
文件中修改接收事件( OutEvent
)部分代码:
uint32_t size = 0;
uint8_t buff[64];// 收到来自主机的数据时会触发该事件
static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
{UNUSED(event_idx);UNUSED(state);size = USBD_LL_GetRxDataSize(&hUsbDeviceFS, CUSTOM_HID_EPOUT_ADDR); // 获取收到的数据长度USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)(hUsbDeviceFS.pClassData);for(int i=0; i<size; i++){buff[i]=hhid->Report_buf[i]; // 读取接收到的数据}USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, buff, size);// 开启下一次接收if (USBD_CUSTOM_HID_ReceivePacket(&hUsbDeviceFS) != (uint8_t)USBD_OK){return -1;}return (USBD_OK);
}
至此就可以进行测试了,这里用的工具下载地址如下:
https://pan.baidu.com/s/1i5QVmrN
测试时依据设备的VID和PID来分辨设备,这两个值定义在 usbd_desc.c
文件中(注意十进制和十六进制的差别):
#define USBD_VID 1155
#define USBD_PID_FS 22352
上面演示中接收部分代码有拷贝动作,这在高性能需求下其实是不太合适的,可以使用下面方式来处理:
uint32_t size = 0;
uint8_t buff[64]; // 接收缓冲区
static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
{size = USBD_LL_GetRxDataSize(&hUsbDeviceFS, CUSTOM_HID_EPOUT_ADDR); // 获取收到的数据长度USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, buff, size); // 发送数据// 开启下一次接收,设置接收缓冲区(默认的USBD_CUSTOM_HID_ReceivePacket方法中调用的其实也是这个)USBD_LL_PrepareReceive(&hUsbDeviceFS, CUSTOM_HID_EPOUT_ADDR, buff, USBD_CUSTOMHID_OUTREPORT_BUF_SIZE);return (USBD_OK);
}
需要注意的是上面方式第一次接到数据是用的还是默认设置的缓冲区。
示例链接
仓库地址: https://github.com/NaisuXu/STM32_MCU_Examples
本示例为仓库中 USBD_HID_FS_H750
。
报告描述符
上面演示中用的是 USB FS ,该规范下HID一包数据最大为64Bytes,如果使用 USB HS ,那么每包最大为1024Bytes,报告描述符可以使用下这个(未测试):
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
0x09, 0x00, // Usage (0x00)
0xA1, 0x01, // Collection (Application)
0x09, 0x01, // Usage (0x01)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x96, 0x00, 0x04, // Report Count (1024)
0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x09, 0x02, // Usage (0x02)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x96, 0x00, 0x04, // Report Count (1024)
0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
// 36 bytes
HID设备的报告描述符可以使用 HID Descriptor Tool
工具配置生成:
https://www.usb.org/document-library/hid-descriptor-tool
总结
总体来说 STM32 中实现 USB HID 双向透传功能并不复杂。
相关文章:

STM32 USB使用记录:HID类设备(后篇)
文章目录 目的基础说明项目构建与代码调整接收发送代码与测试示例链接报告描述符总结 目的 接上篇: 《STM32 USB使用记录:HID类设备(前篇)》 USB HID 类的设备有个比较大的好处是大部分时候接入主机中都是可以免驱使用的。这篇文…...

C# 快速写入日志 不卡线程 生产者 消费者模式
有这样一种场景需求,就是某个方法,对耗时要求很高,但是又要记录日志到数据库便于分析,由于访问数据库基本都要几十毫秒,可在方法里写入BlockingCollection,由另外的线程写入数据库。 可以看到,在…...
Pandas将对角线元素设为1
Pandas将对角线元素设为1 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 入门之pandas的使用 提示:np.fill_diagonal(df.values, 1)的用法 Pandas将对角线元素设为1 Pandas将对角线元素设为…...
WPF实战学习笔记28-登录界面
添加登录界面UI 添加文件loginview.xaml。注意本界面使用的是md内的图标。没有登录界面的图片 <UserControlx:Class"Mytodo.Views.LoginView"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsof…...
01背包
动态规划解题步骤: 动态规划问题,一般从三个步骤进行考虑。 步骤一:集合及集合的状态。 所谓的集合,就是一些方案的集合。 用 g[i][j] 表示从前 i 种物品中进行选择,且总体积不大于 j 的各个选法获得的价值的集合。注意&#…...

064、故障处理之OMM_TiDB
oom 内存溢出,内存泄漏,相当于TiDB不能用了 TiDB Server OOM对业务的影响 TiDB Server上的业务SQL会失败业务响应时间升高前端体验变差 诊断方法 客户端应用 ERROR 2013(HY000): Lost connection to MySQL Server during query日志 dmesg -T | gr…...

网络设备中的配置文件管理
建立强大网络的第一步是为灾难和网络中断做好准备,许多企业在中断期间遭受损失,因为他们缺乏备份计划并且配置管理不达标,使用配置文件管理工具进行适当的配置文件管理不仅有助于处理网络中断,还有助于优化网络性能。 使用配置文…...

HCIP BGP综合实验
题目 1、AS1存在两个环回,一个地址为192.168.1.0/24该地址不能在任何协议中宣告; 2、AS3中存在两个环回,一个地址为192.168.2.0/24该地址不能在任何协议中宣告,最终要求这两个环回可以互相通讯; 3、AS间的骨干链路I…...

【mysql学习篇】Order by与Group by优化以及排序算法详解
一、Order by与Group by优化 Case1: 分析: 利用最左前缀法则:中间字段不能断,因此查询用到了name索引,从key_len74也能看出,age索引列用在排序过程中,因为Extra字段里没有using filesort 注意…...

【业务功能篇60】Springboot + Spring Security 权限管理 【终篇】
4.4.7 权限校验扩展 4.4.7.1 PreAuthorize注解中的其他方法 hasAuthority:检查调用者是否具有指定的权限; RequestMapping("/hello")PreAuthorize("hasAuthority(system:user:list)")public String hello(){return "hello Sp…...

文章详情页 - 评论功能的实现
目录 1. 准备工作 1.1 创建评论表 1.2 创建评论实体类 1.3 创建 mapper 层评论接口和对应的 xml 实现 1.4 准备评论的 service 层 1.5 准备评论的 controller 层 2. 总的初始化详情页 2.1 加载评论列表 2.1.1 实现前端代码 2.1.2 实现后端代码 2.2 查询当前登录用户的…...

使用贝叶斯滤波器通过运动模型和嘈杂的墙壁传感器定位机器人研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

Day 69-70:矩阵分解
代码: package dl;import java.io.*; import java.util.Random;/** Matrix factorization for recommender systems.*/public class MatrixFactorization {/*** Used to generate random numbers.*/Random rand new Random();/*** Number of users.*/int numUsers…...

数据结构:树的存储结构
学习树之前,我们已经了解了二叉树的顺序存储和链式存储,哪么我们如何来存储普通型的树结构的数据?如下图1: 如图1所示,这是一颗普通的树,我们要如何来存储呢?通常,存储这种树结构的数…...

Vue前端渲染blob二进制对象图片的方法
近期做开发,联调接口。接口返回的是一张图片,是对二进制图片处理并渲染,特此记录一下。 本文章是转载文章,原文章:Vue前端处理blob二进制对象图片的方法 接口response是下图 显然,获取到的是一堆乱码&…...

Java的标记接口(Marker Interface)
Java中的标记接口(Marker Interface)是一个空接口,接口内什么也没有定义。它标识了一种能力,标识继承自该接口的接口、实现了此接口的类具有某种能力。 例如,jdk的com.sun.org.apache.xalan.internal.xsltc.trax.Temp…...

Kafka基础架构与核心概念
Kafka简介 Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作流数据。架构特点是分区、多副本、多生产者、多订阅者,性能特点主要是…...

观察者模式与观察者模式实例EventBus
什么是观察者模式 顾名思义,观察者模式就是在多个对象之间,定义一个一对多的依赖,当一个对象状态改变时,所有依赖这个对象的对象都会自动收到通知。 观察者模式也称为发布订阅模式(Publish-Subscribe Design Pattern)࿰…...

科普 | OSI模型
本文简要地介绍 OSI 模型 1’ 2’ 3。 更新:2023 / 7 / 23 科普 | OSI模型 术语节点链路协议网络拓扑 概念作用结构应用层表示层会话层传输层网络层数据链路层物理层 数据如何流动OSI 和TCP/IP 的对应关系和协议参考链接 术语 节点 节点( Node &#…...
redis相关异常之RedisConnectionExceptionRedisCommandTimeoutException
本文只是分析Letture类型的Redis 池化连接出现的连接超时异常、读超时异常问题。 1.RedisConnectionException 默认是10秒。 通过如下可以配置: public class MyLettuceClientConfigurationBuilderCustomizer implements LettuceClientConfigurationBuilderCusto…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...