hid自定义report 影响键盘_基于STM32CUBE的USB键盘例程.docx

2023-10-30

前面说了USB鼠标,这次趁热打铁,说一下USB键盘。依然只说如何修改,不说背后的原理。原因你懂的,涉及的知识点太多了。

会不会写成USB三部曲?    不知道

猜猜我下一步再写个啥?

1

 生成工程

首先,STM32CubeMX的配置部分不说了,和USB鼠标部分的一样。唯一需要注意的一点是,VID和PID这两个值要改一下,否则主机(也就是电脑)会以为你还是鼠标。

640

2

 修改usbd_hid.c文件

其次,生成工程后打开,修改usbd_hid.c文件。配置集合(USBD_HID_CfgFSDesc)要做一些改动,首先是长度:

640

这是个宏定义,之前是34,现在变成41.

然后是端点数,之前是1,现在改成2.

640

接着是接口协议,之前是2(鼠标),现在改成1(键盘)。

再接着是报告描述符长度:

640

之前是:HID_MOUSE_REPORT_DESC_SIZE,长度是74,现在改成:

HID_KEYBOARD_REPORT_DESC_SIZE,长度63.

还有就是端点每次发送的数据包长度:

640

之前是4,不够用了,现在改成16.

最后配置集合中增加一部分端点描述符,因为USB键盘对主机来说,不光有输入,还有输出。所以,增加的这部分端点描述符,用来描述输出。

/******************** Descriptor of Mouse Output endpoint ********************/  0x07,          /*bLength: Endpoint Descriptor size*/  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/  0x01,  0x03,          /*bmAttributes: Interrupt endpoint*/  0x10,  0x00,  HID_FS_BINTERVAL,          /*bInterval: Polling Interval */

3

 修改HID描述符

修改HID描述符中的报告描述符长度:

640

上面提到了,之前是鼠标描述符,长度74,现在改成键盘描述符,长度63.

4

 生成键盘的报告描述符

把USB鼠标的报告描述符删掉,换成USB键盘的报告描述符。

不会写USB键盘的报告描述符怎么办?

USB官方提供了一个USB报告描述符自动配置的工具,打开!里面有各种例程,我们直接复制一个USB键盘的报告描述符即可。

640

生成.h文件如下:

__ALIGN_BEGIN static uint8_t HID_KEYBOARD_ReportDesc[HID_KEYBOARD_REPORT_DESC_SIZE]  __ALIGN_END ={    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)    0x09, 0x06,                    // USAGE (Keyboard)    0xa1, 0x01,                    // COLLECTION (Application)    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)    0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)    0x75, 0x01,                    //   REPORT_SIZE (1)    0x95, 0x08,                    //   REPORT_COUNT (8)    0x81, 0x02,                    //   INPUT (Data,Var,Abs)    0x95, 0x01,                    //   REPORT_COUNT (1)    0x75, 0x08,                    //   REPORT_SIZE (8)    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)    0x95, 0x05,                    //   REPORT_COUNT (5)    0x75, 0x01,                    //   REPORT_SIZE (1)    0x05, 0x08,                    //   USAGE_PAGE (LEDs)    0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)    0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)    0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)    0x95, 0x01,                    //   REPORT_COUNT (1)    0x75, 0x03,                    //   REPORT_SIZE (3)    0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)    0x95, 0x06,                    //   REPORT_COUNT (6)    0x75, 0x08,                    //   REPORT_SIZE (8)    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)    0xc0                           // END_COLLECTION};

5

 修改函数USBD_HID_Setup

第五,函数USBD_HID_Setup中,需要修改一部分代码:

640

获取报告描述符的部分,之前这里是鼠标的报告描述符信息,现在换成了键盘的。

6

 修改main.c文件

main.c文件中,添加头文件,并定义相关的数组:

/* Private includes ----------------------------------------------------------*//* USER CODE BEGIN Includes */#include "usbd_hid.h"/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*//* USER CODE BEGIN PTD */uint8_t KeyBoard[8] = {0,0,4,0,0,0,0,0};uint8_t KeyBoard01[8] = {0,0,0,0,0,0,0,0};extern USBD_HandleTypeDef hUsbDeviceFS;

7

 修改主函数

第七,主函数中循环发送英文字母A~Z。

 while (1)  {    /* USER CODE END WHILE */    /* USER CODE BEGIN 3 */    if(KeyBoard[2] >= 29)    {      KeyBoard[2] = 4;    }    else    {      KeyBoard[2]++;    }    USBD_HID_SendReport(&hUsbDeviceFS,(uint8_t*)&KeyBoard01,sizeof(KeyBoard));    HAL_Delay(15);    USBD_HID_SendReport(&hUsbDeviceFS,(uint8_t*)&KeyBoard,sizeof(KeyBoard01));    HAL_Delay(15);    USBD_HID_SendReport(&hUsbDeviceFS,(uint8_t*)&KeyBoard01,sizeof(KeyBoard));    HAL_Delay(1000);  }

为什么4~29对应英文字母A~Z?

USB官网的文件hut1_12v2中,对键盘的每个按键对应的值,都有一个详细的定义,看第53页,我这里截一部分图:

640

最后,保存、编译、下载、上电!新建一个TXT文档,看键盘自动输出字母,爽不爽?

640

8

基于STM32CUBE的USB鼠标键盘二合一

首先,在5.3.0版本的STM32CubeMX上选择STM32F103C8T6芯片。具体操作和USB鼠标的操作一样,这里就不重复了。

同理,VID和PID要和之前的设备不一样。设置完成以后,直接生成工程。

23e7e6aab459c5e96099262b8a18fcda.png

第二,修改usbd_hid.c中的配置集合(USBD_HID_CfgFSDesc)。如下图所示,框住的地方是个宏定义。配置集合的长度,由之前的34,变为41.

d384b7feb1c83b4fb6f6339ed6081de8.png

端点个数,由1变成2.

接口协议,由2(鼠标)变成1(键盘)。

有的小伙伴会奇怪,我们不是鼠标键盘二合一吗?怎么还是键盘?

作为一个技术人员,我们要学会透过现象看本质。虽然表明上是鼠标与键盘二合一,但实际上是以键盘功能为主,而鼠标以一个附属功能加入到了键盘里。所以,这里虽然选的是键盘,但最终的效果是键盘鼠标功能都有。

5c9e237b7938ec26e63e5cc1cdee1741.png

好了,继续!

跟USB键盘的部分一样,配置集合最下面,增加一个输出端点的描述符:

/******************** Descriptor of Mouse Output endpoint ********************/  0x07,          /*bLength: Endpoint Descriptor size*/  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/  0x01,  0x03,          /*bmAttributes: Interrupt endpoint*/  0x10,  0x00,  HID_FS_BINTERVAL,          /*bInterval: Polling Interval */

第三,修改HID描述符中,报告描述符的长度:

3f4cc5faf00c6066aa15f6d1540eabd6.png

之前这里是鼠标的报告描述符,长度有74.现在变成了117.

为什么是117?

看下文!

第四,修改报告描述符。STM32CubeMX工具自动生成的工程里,报告描述符是鼠标的。现在我们要实现的是键盘与鼠标二合一,要修改的核心位置就是报告描述符这里。

简单来说,就是把前面两个例程中的报告描述符合二为一。一个数组里面,上面放键盘的报告描述符,下面放鼠标的报告描述符。

这样的话,对USB主机(也就是电脑)来说,它收到的数据,有可能是鼠标的数据,也有可能是键盘的数据。那,怎么区分?

方法就是分别在键盘与鼠标的报告描述符中放一个报告ID,键盘的报告ID是1,鼠标的报告ID是2.    两个报告描述符,一个长65,一个长62,加起来117.

向USB主机发送数据的时候,数组的第一个元素是报告ID,后面才是键盘数据或鼠标数据。实现前面两节的例程的时候,USB键盘我们定义了一个8元素的数组,USB鼠标我们定义了一个4元素的数组。现在我们只需要一个数组,它同一时间,只发送一种数据,所以大小为8,然后,还要包含报告ID,所以变成9.

在USB协议中,报告ID默认是数组的第一个元素。明白了这一点,我们可以去修改main.c文件了。

第五,添加头文件,并定义相关的数组。

/* Private includes ----------------------------------------------------------*//* USER CODE BEGIN Includes */#include "usbd_hid.h"/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*//* USER CODE BEGIN PTD */uint8_t KeyBoard[9] = {1,0,0,4,0,0,0,0,0};uint8_t KeyBoard01[9] = {1,0,0,0,0,0,0,0,0};uint8_t Mouse[9] = {2,0,0,0,0,0,0,0,0};extern USBD_HandleTypeDef hUsbDeviceFS;

KeyBoard 数组第一个元素是1,Mouse 数组第一个元素是2,这两个值分别对应键盘和鼠标的报告ID。KeyBoard01这个数组是为了表示键盘没有被按下的状态。

第六,修改主函数。循环输出a到z字母,同时,鼠标左键每隔1秒触发一下。

   /* USER CODE BEGIN 3 */    if(KeyBoard[3] >= 29)    {      KeyBoard[3] = 4;    }    else    {      KeyBoard[3]++;    }    USBD_HID_SendReport(&hUsbDeviceFS,(uint8_t*)&KeyBoard01,sizeof(KeyBoard));    HAL_Delay(15);    USBD_HID_SendReport(&hUsbDeviceFS,(uint8_t*)&KeyBoard,sizeof(KeyBoard));    HAL_Delay(15);    USBD_HID_SendReport(&hUsbDeviceFS,(uint8_t*)&KeyBoard01,sizeof(KeyBoard));    HAL_Delay(1000);    Mouse[1] = 0x01;    USBD_HID_SendReport(&hUsbDeviceFS,(uint8_t*)&Mouse,sizeof(Mouse));    HAL_Delay(1000);    Mouse[1] = 0x00;    USBD_HID_SendReport(&hUsbDeviceFS,(uint8_t*)&Mouse,sizeof(Mouse));    HAL_Delay(1000);

最后,保存、编译、下载、上电!新建一个TXT文档,可以看到字母自动输出,同时鼠标左键每隔1秒被触发一下。

本文授权转载自公众号“单片机爱好者”,作者MCU启航

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

hid自定义report 影响键盘_基于STM32CUBE的USB键盘例程.docx 的相关文章

  • C++ 模板函数、模板类:如果没有被使用就不会被实例化

    C 中如果一个模板函数没有使用过 那么其局部静态变量都不会被实例化 class A public A edward print A ctor template
  • 【2】浅析Vue组件

    组件的基本概念 Vue中有一个概念叫做组件化 就是把页面分成一个个小的部分 每个部分有自己的功能 且可以复用 最外层的组件即根组件 除此之外会有很多子组件 子组件分为两种 全局组件和局部组件 全局组件 用 Vue component 组件名
  • 基础学习——numpy与tensor张量的转换

    系列文章目录 Numpy学习 创建数组及常规操作 数组创建 切片 维度变换 索引 筛选 判断 广播 Tensor学习 创建张量及常规操作 创建 切片 索引 转换 维度变换 拼接 基础学习 numpy与tensor张量的转换 基础学习 关于l
  • 怎么用微信打开wifi连接到服务器,微信一键连wifi在哪里 微信一键连wifi怎么使用...

    类型 社交聊天大小 45 4M语言 中文 评分 5 0 标签 立即下载 微信这款软件使用可以不用流量了 这款软件推出了wifi一键连小程序 帮助用户走到哪里都有无线网 但是有很多伙伴不知道在哪里 怎么连接 想知道的伙伴可以在西西看看相关的教
  • fiddler设置网速模拟弱网络测试

    在测试过程中 经常会要求测试弱网络情况时的一些特殊情况 这时候IOS还好说 在开发者选项中调整网络模式即可 但android就只能通过别的方式了 这里整理了通过fiddler抓包工具来设置弱网模式 在fiddler可以设置自己想要的网速 或
  • CTF练题(3) jpg图片隐写 使用jphs05工具和stegslove

    题目一概述 解题过程 1 根据题目提示 判断为图片隐写 800度的眼镜 我理解为不同色通道下观看图片 由此打开stegslove分析该图片 2 点击右方向键调整不同的色通道 发现乱码隐约组成六个字 我好喜欢你 如图 可能这六个字为本题fla
  • java代码编译和运行在命令行中完成

    背景 集成开发环境用多了 最近想学一下 java 基础 用命令行来编译和运行一下 发现举步维艰 于是 创作这篇文章与大家共享 基础知识梳理 在写代码之前 我们先花点时间来了解一下 java 编译和运行的过程 如下图 里面涉及到 两个 命令符
  • CentOS安装PostgreSQL

    版本信息 CentOS版本 CentOS 7 x86 64 Minimal 1810 PostgreSQL版本 PostgreSQL 10 10 64 bit 第一部分 PostgresSQL的安装 1 安装rpm文件 yum instal
  • 华为云云耀云服务器L实例评测|轻松购买 快速使用 上云如此简单【详细版】

    华为云云耀云服务器L实例评测 轻松购买 快速使用 上云如此简单 详细版 轻量级云服务器 即开即用 轻松运维 开启简单上云第一步 文章目录 华为云云耀云服务器L实例评测 轻松购买 快速使用 上云如此简单 详细版 1 云耀云服务器介绍 2 购买
  • Stable Diffusion 硬核生存指南:WebUI 中的 GFPGAN

    本篇文章聊聊 Stable Diffusion WebUI 中的核心组件 强壮的人脸图像面部画面修复模型 GFPGAN 相关的事情 写在前面 本篇文章的主角是开源项目 TencentARC GFPGAN 和上一篇文章 Stable Diff
  • scrollview中使用recyclerview莫名自动上滑

    1 scrollview中加入 android descendantFocusability blocksDescendants 2 为scrollView中的根view加入android focusableInTouchMode true
  • USB详解

    转载自http blog 163 com zhsh email blog static 19786900200611259521640 usb作为一种串行接口 应用日益广泛 如同每个工程设计人员必须掌握I2C RS232这些接口一样 我们也
  • int最大值是多少

    int最大值 根据编译器类型不同而变化 具体如下 1 对于16位编译器 int占16位 2字节 int的最大值为32767 2 对于32位和64位编译器 int占32位 4字节 int的最大值为2147483647 java语言中 int最
  • SQL语句中case、when、then的使用

    使用语法为 select pro id AS id pro title AS title pro name AS name pro ltime AS ltime pro place AS place pro linkman AS linkm
  • 【100天精通Python】Day58:Python 数据分析_Pandas时间序列数据处理,创建和解析时间数据pd.to_datetime(),.loc[],resample() 用法示例

    目录 时间序列数据处理 1 解析日期和时间数据 2 创建时间索引 3 访问时间索引数据 3 1 按年 月 日等级别访问数据 loc 3 2 使用部分日期作为索引 loc loc 3 3 使用时间索引的属性 index 4 时间索引的切片 5
  • 51单片机入门教程(2)——实现流水灯

    51单片机入门教程 2 实现流水灯 一 搭建流水灯电路 二 流水灯程序 2 1 延时程序 2 2 延时函数 2 3 按字节寻址 2 4 逻辑移位 2 5 条件判断 一 搭建流水灯电路 在Proteus中搭建流水灯电路如图 二 流水灯程序 我
  • 为什么我这么累?

    本月十六日 我和媳妇喜爱的歌手姚贝娜去世了 你是个好歌手 真正的热爱音乐 希望你在天堂里面开心的唱歌 我是个参加工作不久的小程序员 过着家 地铁 公司三点一线的生活 每天早上七点二十出门 地铁上一个多小时 8点五十到公司 下午六点下班 一个
  • 【FreeRTOS 信号量】互斥信号量

    互斥信号量与二值信号量类似 但是互斥信号量可以解决二值信号量出现的优先级翻转问题 解决办法就是优先级继承 普通互斥信号量创建及运行 参阅安富莱电子demo 互斥信号量句柄 static SemaphoreHandle t xMutex NU
  • 卷积神经网络中卷积层、池化层、全连接层的作用

    1 卷积层的作用 卷积层的作用是提取输入图片中的信息 这些信息被称为图像特征 这些特征是由图像中的每个像素通过组合或者独立的方式所体现 比如图片的纹理特征 颜色特征 比如下面这张图片 蓝色框框住的地方就是脸部特征 这些特征其实是由一个个像素

随机推荐

  • 消息鉴别码的原理与应用

    消息鉴别码可以确认自己收到的消息是否就是发送者的本意 也就是说 使用消息鉴别码可以判断消息是否被篡改 以及是否有人伪装成发送者发送该消息 消息鉴别码实现鉴别的原理是 用公开函数和密钥产生一个固定长度的值作为认证标识 用这个标识鉴别消息的完整
  • uml活动图

    活动图与交互图的区别 交互图强调的是对象到对象的控制流 而活动图则强调的是从活动到活动的控制流 初始节点和活动终点 用一个实心圆表示初始节点 用一个圆圈内加一个实心圆来表示活动终点 活动节点 是活动图中最主要的元素之一 它用来表示一个活动
  • 基于CNN的人脸表情识别系统

    基于CNN的人脸表情识别系统 主要功能 1 图片识别 可以通过上传本地图片 进行表情识别 2 拍照识别 点击拍照识别按钮 可以调用摄像头实现拍照 并进 行表情识别 实现原理 1 表情库的建立 fer2013人脸数据集 可以从kaggle网站
  • 上/下采样的方法

    下采样方式一般使用池化 pooling 操作 上采样 upsampling 的三种方式 插值法 Interpolation 插值就是在周围像素色彩的基础上用数学公式计算补充插入像素点的色彩 但必须注意的是插值并不能增加图像信息 如双线性插值
  • 数字电子技术-逻辑门电路

    文章目录 一 理想开关 二 基本CMOS逻辑门电路 2 1 MOS管开关特性 2 2 CMOS反相器 2 3 常用CMOS逻辑门电路 2 4 CMOS传输门 2 5 CMOS漏极开路门和三态输出门电路 2 6 CMOS逻辑门电路的重要参数
  • 写一个GitHub图床

    刚刚完成一个作业 涉及到图片的上传服务 因为自己经常会有一些图片管理的需求 七牛云 阿里云的oos存储又是付费的 所以自己根据GitHub的官方API搭建一个自己的图床服务 以便后续自己开发使用 参考地址 GitHubAPI import
  • GoLang - colly爬虫框架

    大家好 我是TheWeiJun 很高兴又和大家见面了 国庆假期马上就要结束了 在国庆假期里小编看了下colly框架 故这篇文章中将提到colly的使用及分析 欢迎各位读者多多阅读与交流 特别声明 本公众号文章只作为学术研究 不作为其它不法用
  • 实践安装minio

    一 下载安装文件 1 在home目录下创建minio文件夹 mkdir home minio 2 进入 home minio 文件夹 cd home minio 3 下载文件 此处下载比较慢 建议手动下载 然后上传到目录中 wget htt
  • springboot集成nacos配置中心踩坑记录

    目录 1 下载安装 准备 下载地址 可以尝试选择最新版本 解压 2 添加数据库配置 特别注意 3 登陆nacos添加配置 4 springboot项目中获取配置中心配置 1 引入依赖 2 创建bootstrap yaml配置文件 3 启动注
  • 在嵌入式板子ARMv7 上利用neon对彩色图转换为灰度图进行加速

    RGB转GRAY公式如下 本实验通过对一张1920 1080 分辨率大小RGB彩色图进行灰度图转换测试耗时时间 测试条件为 嵌入式开发板ssc9381g A7 通过四种转换方式进行耗时对比 结果如下 方式1 通过opencv 库函数cvtC
  • 线程池异常java.util.concurrent.RejectedExecutionException

    问题及代码 使用 ThreadPoolExecutor 自定义线程池时 出现java util concurrent RejectedExecutionException的错误信息 源代码如下 public static void main
  • JVM系列(二) Java 堆内存分析

    Java 堆内存分析 堆是GC 垃圾收集器 执行垃圾回收的重点区域 所以今天我们着重讲下堆内存 自己的项目 如果出现OOM或者出现内存泄露 一定是出在堆内存上 因为堆是JVM中最大的一块内存空间 所有线程共享Java堆 物理上不连续的逻辑上
  • Vue/cli 3.0中使用百度地图api

    1 申请百度地图ak ak会在引入百度js的时候用到 你可以点击这里申请一个唯一ak 2 引入百度地图js 在public index html里面添加下面代码 注意把 你的ak 替换成你申请的ak 复制代码 3 配置webpack 由于c
  • 深度学习激活函数和权值初始化

    激活函数选择总结 尽量选择ReLU函数或者Leakly ReLU函数 相对于Sigmoid tanh ReLU函数或者Leakly ReLU函数会让梯度流更加顺畅 训练过程收敛得更快 权值初始化总结 好的初始化方法可以防止前向传播过程中的信
  • VB6反编译详解

    标 题 VB6反编译详解 一 作 者 kenmark时 间 2006 07 09 16 59 链 接 http bbs pediy com showthread php threadid 28715 详细信息 VB6反编译详解 by Ken
  • Juc04_阻塞队列概述、方法、实现类、Linked和Array区别、注意事项

    文章目录 什么是阻塞队列 BlockingQueue的主要方法 BlockingQueue的实现类 Linked和Array区别 不推荐使用快捷的线程池 什么是阻塞队列 阻塞队列 从名字可以看出 它也是队列的一种 那么它肯定是一个先进先出F
  • 在 Shell 中用 echo 输出变量丢失换行符的问题

    原文链接 http hi baidu com moligaloo item b404cf0736d085dd72e6765f 若 foo txt 是一个含有多行文本的文本文件 如 hello world 使用如下命令 foo cat foo
  • chrome浏览器如何避免network报错:ERR_CERT_AUTHORITY_INVALID并添加为例外或继续前往

    版权声明 转载请注明作者 独孤尚良dugushangliang 出处 https blog csdn net dugushangliang article details 101421339 本文接续https blog csdn net
  • 事务故障、系统故障和介质故障的恢复

    数据库系统 故障与恢复 事务故障 系统故障和介质故障的恢复 1 事务故障的恢复 2 系统故障的恢复 3 介质故障的恢复 重装数据库 然后重做已完成的事务 1 事务故障的恢复 1 反向扫描日志文件 查找该事务的更新操作 2 对该事务的更新执行
  • hid自定义report 影响键盘_基于STM32CUBE的USB键盘例程.docx

    前面说了USB鼠标 这次趁热打铁 说一下USB键盘 依然只说如何修改 不说背后的原理 原因你懂的 涉及的知识点太多了 会不会写成USB三部曲 不知道 猜猜我下一步再写个啥 1 生成工程 首先 STM32CubeMX的配置部分不说了 和USB