STM32 USB HID复合设备 两个接口 键盘+数据传输 功能

#STM32 USB HID复合设备 两个接口 键盘+数据传输 功能

本人想要做一个USB设备,它能够模拟键盘给PC发数据,并且也能够和PC进行数据通信,这里键盘只做了发送功能,并不能接受PC端的大小写切换从而改变键盘灯的颜色。
具体逻辑如下:
在这里插入图片描述

这里的做法是,USB为复合设备,有两个接口,一个接口为:传输数据的自定义接口(两个端点,双向传输),另一个接口为:键盘(一个端点,只能键盘给PC发)
先使用STM32CUBEMX生成一个模板工程,并且将其修改为HID传输数据。
以下内容转载自:https://blog.csdn.net/weixin_30737433/article/details/99339824
https://www.cnblogs.com/xingboy/p/9913963.html
转载地址
转载地址
1、首先打开USB
  
  在这里插入图片描述
  2、接着把USB设置为下图HID模式
  在这里插入图片描述
  3、选择外部时钟
  在这里插入图片描述
  4、配置时钟树
  在这里插入图片描述
  5、配置USB设置
  在这里插入图片描述
  在这里插入图片描述
  下面的USB设置就有点讲究了,
  在这里插入图片描述
6、确认后,生成代码
  在这里插入图片描述
打开刚才建立的工程,在 usbd_custom_hid_if.c 文件里,找到 CUSTOM_HID_ReportDesc_FS 这个函数,把刚才生成的报文文件覆盖掉函数里面的文件,代码如下:

/** 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 Page 1)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Vendor Usage 1)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x95, 0x40,                    //   REPORT_COUNT (64)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x09, 0x01,                    //   USAGE (Vendor Usage 1)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x95, 0x40,                    //   REPORT_COUNT (64)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
    0xc0                           // END_COLLECTION
};

然后再修改将usbd_conf.h做对应修改:

 #define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE      64
 #define USBD_CUSTOM_HID_REPORT_DESC_SIZE       34

同时修改usbd_customhid.h文件中的发送与接收长度为64

#define CUSTOM_HID_EPIN_SIZE                  0x40
#define CUSTOM_HID_EPOUT_SIZE              0x40

到这里基本就算做出一个USB设备了,我们编译下载程序看看。
  如果电脑显示了这个USB设备,但是有黄色感叹号,说明USB枚举成功,可是驱动安装失败,这时我们可以libusb自带的inf-wizard工具生成USB驱动程序,要怎么安装驱动解决这个问题可以参考驱动安装:https://blog.csdn.net/niepangu/article/details/44984325,驱动安装成功的话,到这里我们就可以看到USB正常列举出来啦,下面我们就可以写USB数据收发代码了。

USB数据传输:参考http://www.stm32cube.com/article/138

关于数据传输,HID设备是采用轮询方式传输的,ST默认20ms速度实在不敢恭维,还得要改一下枚举时的声明,同样是usbd_customhid.c文件,

__ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_CfgDesc[USB_CUSTOM_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{
 ....
 ....
0x20,          /*bInterval: Polling Interval (20 ms)*/

  /* 34 */

 ....
 ....

  0x20,/* bInterval: Polling Interval (20 ms) */

  /* 41 */
}

这两个地方随心来改,最小可以改到0x01。这就快很多啦。(这里可以不做修改,我的电脑上生成的是5ms)到这里数据传输准备工作就做好了,下面我们先来说一下USB发送:
  先定义个发送BUFF:

uint8_t send_buf[64] = {//定义一个USB的发送BUFF
                         1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
                         17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,
                         40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64};

再包括发送函数头文件以及声明一个外部定义(main.c文件中):

#include "usbd_customhid.h" //包括发送函数头文件
extern USBD_HandleTypeDef hUsbDeviceFS; //外部声明USB发送函数

现在可以在main函数里添加发送代码了,我这里设置按一下按键就发送一次,同时led亮1s:

 while (1)
  {
    /* USER CODE BEGIN 3 */
        if(HAL_GPIO_ReadPin(GPIOE,k1_Pin)==0)
        {    
            //按键消抖
            while(HAL_GPIO_ReadPin(GPIOE,k1_Pin)==0);
            //点亮指示灯
            HAL_GPIO_WritePin(GPIOE,led1_Pin,GPIO_PIN_RESET);
            //USB发送数据
            USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, send_buf, sizeof(send_buf));
       //实际发送到上位机的数据有65个,一个报文ID:0 + 64个send_buf 数据,一共65个数据到上位机
            HAL_Delay(1000);
            //关闭指示灯
            HAL_GPIO_WritePin(GPIOE,led1_Pin,GPIO_PIN_SET);           
        }
  }

发送函数就是这么简单,接下来说接收函数了,接收函数是中断接收的,建立工程时已经默认开启了。下面就说一下USB接收:
  先在main.c定义个接收BUFF:

unsigned char USB_Recive_Buffer[64]; //USB接收缓存
unsigned char USB_Received_Count = 0;//USB接收数据计数

打开usbd_custom_hid_if.c文件,添加外部声明:

extern unsigned char USB_Recive_Buffer[64];
extern unsigned char USB_Received_Count;

接着在usbd_custom_hid_if.c文件中找到 static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state) 函数,当USB接收完数据后,就会进入到这个函数,我们可以在这里添加接收函数,把函数修改如下:

/**
  * @brief  Manage the CUSTOM HID class events
  * @param  event_idx: Event index
  * @param  state: Event state
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
//当芯片完成一组数据接收的时候,中断会调用CUSTOM_HID_OutEvent_FS这个回调函数
static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
{
  /* USER CODE BEGIN 6 */
     char i;
     HAL_GPIO_TogglePin(GPIOE,led1_Pin);
    
    /*查看接收数据长度
    USB_Received_Count = USBD_GetRxCount( &hUsbDeviceFS,CUSTOM_HID_EPOUT_ADDR );
    printf("USB_Received_Count = %d \r\n",USB_Received_Count);
    
    USB_Received_Count = USBD_GetRxCount( &hUsbDeviceFS,CUSTOM_HID_EPIN_ADDR  );
    printf("USB_Received_Count_in = %d \r\n",USB_Received_Count);
    */
    
  USBD_CUSTOM_HID_HandleTypeDef   *hhid; //定义一个指向USBD_CUSTOM_HID_HandleTypeDef结构体的指针
  hhid = (USBD_CUSTOM_HID_HandleTypeDef*)hUsbDeviceFS.pClassData;//得到USB接收数据的储存地址
    
    for(i=0;i<64;i++) 
    {
        USB_Recive_Buffer[i]=hhid->Report_buf[i];  //把接收到的数据送到自定义的缓存区保存(Report_buf[i]为USB的接收缓存区)
        //printf("USB_Recive_Buffer[%d] = 0x%x \r\n",i,USB_Recive_Buffer[i]); //打印接收到的信息,确认是否正确,调试用
    } 
  return USBD_OK;
  /* USER CODE END 6 */
}

这样就 USB_Recive_Buffer[i] 里面就保存到接收到的数据了,用Bus Hound可以看到已经成功啦。
 这里我使用的不是Bus Hound,而是这个软件,个人感觉用起来更顺手(需要的可以加我企鹅:1205775165)
 在这里插入图片描述

以上实现了数据传输,接下来只需要再添加一个键盘的interface就行,后续步骤参考了如下
参考1
参考2

在usbd_customhid.c文件中找到如下定义

/* USB CUSTOM_HID device FS Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_CfgFSDesc[USB_CUSTOM_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{
  0x09, /* bLength: Configuration Descriptor size */
  USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
  USB_CUSTOM_HID_CONFIG_DESC_SIZ,
  /* wTotalLength: Bytes returned */
  0x00,
  0x01,         /*bNumInterfaces: 1 interface*/
  0x01,         /*bConfigurationValue: Configuration value*/
  0x00,         /*iConfiguration: Index of string descriptor describing
  the configuration*/
  0xC0,         /*bmAttributes: bus powered */
  0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*/
........................
........................ 省略
........................
  0x03, /* bmAttributes: Interrupt endpoint */
  CUSTOM_HID_EPOUT_SIZE,  /* wMaxPacketSize: 2 Bytes max  */
  0x00,
  CUSTOM_HID_FS_BINTERVAL,  /* bInterval: Polling Interval */
  /* 41 */
};

这部分就是配置描述符, 我们把这部分其中的

  0x01,         /*bNumInterfaces: 1 interface*/

修改为

  0x02,         /*bNumInterfaces: 1 interface*/

表示有两个接口

并在最后添加如下代码:

/************** Descriptor of Joystick Keyboard interface ****************/
  0x09,         /*bLength: Interface Descriptor size*/
  USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
  0x01,         /*bInterfaceNumber: Number of Interface*/
  0x00,         /*bAlternateSetting: Alternate setting*/
  0x01,         /*bNumEndpoints*/
  0x03,         /*bInterfaceClass: HID*/
  0x01,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
  0x01,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
  0,            /*iInterface: Index of string descriptor*/
/******************** Descriptor of Joystick Keyboard HID ********************/
  /* 50 */
  0x09,         /*bLength: HID Descriptor size*/
  CUSTOM_HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
  0x11,         /*bcdHID: HID Class Spec release number*/
  0x01,
  0x00,         /*bCountryCode: Hardware target country*/
  0x01,         /*bNumDescriptors: Number of HID class descriptors to follow*/
  0x22,         /*bDescriptorType*/
  HID_KEYBOARD_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
  0x00,
  /******************** Descriptor of Keyboard endpoint ********************/
  /* 59 */
  0x07,          /*bLength: Endpoint Descriptor size*/
  USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/  
  HID_EPIN_ADDR,     /*bEndpointAddress: Endpoint Address (IN)*/
  0x03,          /*bmAttributes: Interrupt endpoint*/
  HID_EPIN_SIZE, /*wMaxPacketSize: 8 Byte max */
  0x00,
  CUSTOM_HID_FS_BINTERVAL,          /*bInterval: Polling Interval (10 ms)*/
  /* 66 */

这里的/* 数字 */ 是用来记录当前数组有多大的。可以看到原来这个数组大小为USB_CUSTOM_HID_CONFIG_DESC_SIZ,
我们右键go to definition过去可以看到是

#define USB_CUSTOM_HID_CONFIG_DESC_SIZ       41U

现在在结尾添加了一个接口的信息,总大小已经是66了,所以我们修改为66

#define USB_CUSTOM_HID_CONFIG_DESC_SIZ       66U

添加后可以看到,有些宏定义是没有的,我们到usbd_conf.h文件夹中添加如下:

#define HID_KEYBOARD_REPORT_DESC_SIZE    63

在usbd_custom.h中添加如下:

#define HID_EPIN_ADDR                 0x82U
#define HID_EPIN_SIZE                 0x08U

我们增加了一个0X82这个端点,所以我们需要在初始化函数中添加对其的初始化。打开usbd_customhid.c文件,可以找到一个
static uint8_t USBD_CUSTOM_HID_Init(USBD_HandleTypeDef *pdev,uint8_t cfgidx)的函数, 我们在其中添加如下代码:

 USBD_LL_OpenEP(pdev, HID_EPIN_ADDR, USBD_EP_TYPE_INTR,  //KEYBOARD
                 HID_EPIN_SIZE); 

我们在usbd_customhid.c文件中(尽量定义在文件的上方一点,最好在所有函数之前),添加一个键盘的报表

__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, 0xFF,// LOGICAL_MAXIMUM (255)
 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
}

还是在usbd_customhid.c文件中我们可以找到
static uint8_t USBD_CUSTOM_HID_Setup(USBD_HandleTypeDef *pdev,USBD_SetupReqTypedef *req)函数
case USB_REQ_TYPE_STANDARD:下的case USB_REQ_GET_DESCRIPTOR:下 有如下代码

case USB_REQ_GET_DESCRIPTOR:
          if (req->wValue >> 8 == CUSTOM_HID_REPORT_DESC)
          {
            len = MIN(USBD_CUSTOM_HID_REPORT_DESC_SIZE, req->wLength);
            pbuf = ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->pReport;
          }
          else
          {
            if (req->wValue >> 8 == CUSTOM_HID_DESCRIPTOR_TYPE)
            {
              pbuf = USBD_CUSTOM_HID_Desc;
              len = MIN(USB_CUSTOM_HID_DESC_SIZ, req->wLength);
            }
          }

把其中第一个if里面的东西修改为:

	if(req->wIndex == 0){                            //  如果是接口0 还是用以前的报表
        len = MIN(USBD_CUSTOM_HID_REPORT_DESC_SIZE, req->wLength);
        pbuf = ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->pReport; 
       }
        if(req->wIndex == 1){                            // 如果是接口1  则使用 键盘报表
        len = MIN(HID_KEYBOARD_REPORT_DESC_SIZE, req->wLength);
          pbuf=HID_KEYBOARD_ReportDesc;
       }

我们仿照USBD_CUSTOM_HID_SendReport() 函数 写一个键盘的发送函数。我们在usbd_customhid.c中可以找到这个函数,并仿照写出如下

uint8_t USBD_KEYBOADR_HID_SendReport(USBD_HandleTypeDef  *pdev,
                                   uint8_t *report,
                                   uint16_t len)
{
  USBD_CUSTOM_HID_HandleTypeDef     *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData;
  
  if (pdev->dev_state == USBD_STATE_CONFIGURED)
  {
    if (hhid->state == CUSTOM_HID_IDLE)
    {
      hhid->state = CUSTOM_HID_BUSY;
      USBD_LL_Transmit(pdev, HID_EPIN_ADDR, report, len);
    }
    else
    {
      return USBD_BUSY;
    }
  }
  return USBD_OK;
}

在main.c 中添加头文件,如果有则不用添加

#include "usbd_customhid.h"  

在usbd_customhid.h中添加声明

uint8_t USBD_KEYBOADR_HID_SendReport(USBD_HandleTypeDef  *pdev,
                                   uint8_t *report,
                                   uint16_t len);

最后调用 USBD_KEYBOADR_HID_SendReport函数即可。我们在主函数中定义数组:

uint8_t KEYBOARD_Buffer[8]={0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00};
uint8_t KEYBOARD_Zero[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

调用函数

USBD_KEYBOADR_HID_SendReport(&hUsbDeviceFS, KEYBOARD_Buffer,8)
HAL_Delay(300);
USBD_KEYBOADR_HID_SendReport(&hUsbDeviceFS, KEYBOARD_Zero,8)

代表了STM32这个键盘向电脑发送a。
自此,一个STM32上的USB连接电脑后电脑识别为两个接口,
在这里插入图片描述
一个是键盘,一个是自定义通信的设备。可以同时模拟键盘的同时与PC进行数据通信。

键盘的按键定义参考了链接

键盘发送给PC的数据每次8个字节:BYTE1 BYTE2 BYTE3 BYTE4 BYTE5 BYTE6 BYTE7 BYTE8。定义分别是:
BYTE1 –
|–bit0: Left Control 是否按下,按下为1
|–bit1: Left Shift 是否按下,按下为1
|–bit2: Left Alt 是否按下,按下为1
|–bit3: Left GUI 是否按下,按下为1
|–bit4: Right Control 是否按下,按下为1
|–bit5: Right Shift 是否按下,按下为1
|–bit6: Right Alt 是否按下,按下为1
|–bit7: Right GUI 是否按下,按下为1
BYTE2 – 暂不清楚,有的地方说是保留位
BYTE3–BYTE8 – 这六个为普通按键
第一列10进制键值,第二列16进制键值,第四列是按键
0 00 Reserved (no event indicated)9 N/A √ √ √ 4/101/104
1 01 Keyboard ErrorRollOver9 N/A √ √ √ 4/101/104
2 02 Keyboard POSTFail9 N/A √ √ √ 4/101/104
3 03 Keyboard ErrorUndefined9 N/A √ √ √ 4/101/104
4 04 Keyboard a and A4 31 √ √ √ 4/101/104
5 05 Keyboard b and B 50 √ √ √ 4/101/104
6 06 Keyboard c and C4 48 √ √ √ 4/101/104
7 07 Keyboard d and D 33 √ √ √ 4/101/104
8 08 Keyboard e and E 19 √ √ √ 4/101/104
9 09 Keyboard f and F 34 √ √ √ 4/101/104
10 0A Keyboard g and G 35 √ √ √ 4/101/104
11 0B Keyboard h and H 36 √ √ √ 4/101/104
12 0C Keyboard i and I 24 √ √ √ 4/101/104
13 0D Keyboard j and J 37 √ √ √ 4/101/104
14 0E Keyboard k and K 38 √ √ √ 4/101/104
15 0F Keyboard l and L 39 √ √ √ 4/101/104
16 10 Keyboard m and M4 52 √ √ √ 4/101/104
17 11 Keyboard n and N 51 √ √ √ 4/101/104
18 12 Keyboard o and O4 25 √ √ √ 4/101/104
19 13 Keyboard p and P4 26 √ √ √ 4/101/104
20 14 Keyboard q and Q4 17 √ √ √ 4/101/104
21 15 Keyboard r and R 20 √ √ √ 4/101/104
22 16 Keyboard s and S4 32 √ √ √ 4/101/104
23 17 Keyboard t and T 21 √ √ √ 4/101/104
24 18 Keyboard u and U 23 √ √ √ 4/101/104
25 19 Keyboard v and V 49 √ √ √ 4/101/104
26 1A Keyboard w and W4 18 √ √ √ 4/101/104
27 1B Keyboard x and X4 47 √ √ √ 4/101/104
28 1C Keyboard y and Y4 22 √ √ √ 4/101/104
29 1D Keyboard z and Z4 46 √ √ √ 4/101/104
30 1E Keyboard 1 and !4 2 √ √ √ 4/101/104
31 1F Keyboard 2 and @4 3 √ √ √ 4/101/104
32 20 Keyboard 3 and #4 4 √ √ √ 4/101/104
33 21 Keyboard 4 and $4 5 √ √ √ 4/101/104
34 22 Keyboard 5 and %4 6 √ √ √ 4/101/104
35 23 Keyboard 6 and ^4 7 √ √ √ 4/101/104
36 24 Keyboard 7 and &4 8 √ √ √ 4/101/104
37 25 Keyboard 8 and *4 9 √ √ √ 4/101/104
38 26 Keyboard 9 and (4 10 √ √ √ 4/101/104
39 27 Keyboard 0 and )4 11 √ √ √ 4/101/104
40 28 Keyboard Return (ENTER)5 43 √ √ √ 4/101/104
41 29 Keyboard ESCAPE 110 √ √ √ 4/101/104
42 2A Keyboard DELETE (Backspace)13 15 √ √ √ 4/101/104
43 2B Keyboard Tab 16 √ √ √ 4/101/104
44 2C Keyboard Spacebar 61 √ √ √ 4/101/104
45 2D Keyboard - and (underscore)4 12 √ √ √ 4/101/104
46 2E Keyboard = and +4 13 √ √ √ 4/101/104
47 2F Keyboard [ and {4 27 √ √ √ 4/101/104
48 30 Keyboard ] and }4 28 √ √ √ 4/101/104
49 31 Keyboard \ and | 29 √ √ √ 4/101/104
50 32 Keyboard Non-US # and ~2 42 √ √ √ 4/101/104
51 33 Keyboard ; and :4 40 √ √ √ 4/101/104
52 34 Keyboard ‘ and “4 41 √ √ √ 4/101/104
53 35 Keyboard Grave Accent and Tilde4 1 √ √ √ 4/101/104
54 36 Keyboard, and <4 53 √ √ √ 4/101/104
55 37 Keyboard . and >4 54 √ √ √ 4/101/104
56 38 Keyboard / and ?4 55 √ √ √ 4/101/104
57 39 Keyboard Caps Lock11 30 √ √ √ 4/101/104
58 3A Keyboard F1 112 √ √ √ 4/101/104
59 3B Keyboard F2 113 √ √ √ 4/101/104
60 3C Keyboard F3 114 √ √ √ 4/101/104
61 3D Keyboard F4 115 √ √ √ 4/101/104
62 3E Keyboard F5 116 √ √ √ 4/101/104
63 3F Keyboard F6 117 √ √ √ 4/101/104
64 40 Keyboard F7 118 √ √ √ 4/101/104
65 41 Keyboard F8 119 √ √ √ 4/101/104
66 42 Keyboard F9 120 √ √ √ 4/101/104
67 43 Keyboard F10 121 √ √ √ 4/101/104
68 44 Keyboard F11 122 √ √ √ 101/104
69 45 Keyboard F12 123 √ √ √ 101/104
70 46 Keyboard PrintScreen1 124 √ √ √ 101/104
71 47 Keyboard Scroll Lock11 125 √ √ √ 4/101/104
72 48 Keyboard Pause1 126 √ √ √ 101/104
73 49 Keyboard Insert1 75 √ √ √ 101/104
74 4A Keyboard Home1 80 √ √ √ 101/104
75 4B Keyboard PageUp1 85 √ √ √ 101/104
76 4C Keyboard Delete Forward1;14 76 √ √ √ 101/104
77 4D Keyboard End1 81 √ √ √ 101/104
78 4E Keyboard PageDown1 86 √ √ √ 101/104
79 4F Keyboard RightArrow1 89 √ √ √ 101/104
80 50 Keyboard LeftArrow1 79 √ √ √ 101/104
81 51 Keyboard DownArrow1 84 √ √ √ 101/104
82 52 Keyboard UpArrow1 83 √ √ √ 101/104
83 53 Keypad Num Lock and Clear11 90 √ √ √ 101/104
84 54 Keypad /1 95 √ √ √ 101/104
85 55 Keypad * 100 √ √ √ 4/101/104
86 56 Keypad - 105 √ √ √ 4/101/104
87 57 Keypad + 106 √ √ √ 4/101/104
88 58 Keypad ENTER5 108 √ √ √ 101/104
89 59 Keypad 1 and End 93 √ √ √ 4/101/104
90 5A Keypad 2 and Down Arrow 98 √ √ √ 4/101/104
91 5B Keypad 3 and PageDn 103 √ √ √ 4/101/104
92 5C Keypad 4 and Left Arrow 92 √ √ √ 4/101/104
93 5D Keypad 5 97 √ √ √ 4/101/104
94 5E Keypad 6 and Right Arrow 102 √ √ √ 4/101/104
95 5F Keypad 7 and Home 91 √ √ √ 4/101/104
96 60 Keypad 8 and Up Arrow 96 √ √ √ 4/101/104
97 61 Keypad 9 and PageUp 101 √ √ √ 4/101/104
98 62 Keypad 0 and Insert 99 √ √ √ 4/101/104
99 63 Keypad . and Delete 104 √ √ √ 4/101/104
100 64 Keyboard Non-US \ and |3;6 45 √ √ √ 4/101/104
101 65 Keyboard Application10 129 √ √ 104
102 66 Keyboard Power9 √ √
103 67 Keypad = √
104 68 Keyboard F13 √
105 69 Keyboard F14 √
106 6A Keyboard F15 √
107 6B Keyboard F16
108 6C Keyboard F17
109 6D Keyboard F18
110 6E Keyboard F19
111 6F Keyboard F20
112 70 Keyboard F21
113 71 Keyboard F22
114 72 Keyboard F23
115 73 Keyboard F24
116 74 Keyboard Execute √
117 75 Keyboard Help √
118 76 Keyboard Menu √
119 77 Keyboard Select √
120 78 Keyboard Stop √
121 79 Keyboard Again √
122 7A Keyboard Undo √
123 7B Keyboard Cut √
124 7C Keyboard Copy √
125 7D Keyboard Paste √
126 7E Keyboard Find √
127 7F Keyboard Mute √
128 80 Keyboard Volume Up √
129 81 Keyboard Volume Down √
130 82 Keyboard Locking Caps Lock12 √
131 83 Keyboard Locking Num Lock12 √
132 84 Keyboard Locking Scroll Lock12 √
133 85 Keypad Comma27 107
134 86 Keypad Equal Sign29
135 87 Keyboard International115,28 56
136 88 Keyboard International216
137 89 Keyboard International317
138 8A Keyboard International418
139 8B Keyboard International519
140 8C Keyboard International620
141 8D Keyboard International721
142 8E Keyboard International822
143 8F Keyboard International922
144 90 Keyboard LANG125
145 91 Keyboard LANG226
146 92 Keyboard LANG330
147 93 Keyboard LANG431
148 94 Keyboard LANG532
149 95 Keyboard LANG68
150 96 Keyboard LANG78
151 97 Keyboard LANG88
152 98 Keyboard LANG98
153 99 Keyboard Alternate Erase7
154 9A Keyboard SysReq/Attention1
155 9B Keyboard Cancel
156 9C Keyboard Clear
157 9D Keyboard Prior
158 9E Keyboard Return
159 9F Keyboard Separator
160 A0 Keyboard Out
161 A1 Keyboard Oper
162 A2 Keyboard Clear/Again
163 A3 Keyboard CrSel/Props
164 A4 Keyboard ExSel
165-175 A5-CF Reserved
176 B0 Keypad 00
177 B1 Keypad 000
178 B2 Thousands Separator 33
179 B3 Decimal Separator 33
180 B4 Currency Unit 34
181 B5 Currency Sub-unit 34
182 B6 Keypad (
183 B7 Keypad )
184 B8 Keypad {
185 B9 Keypad }
186 BA Keypad Tab
187 BB Keypad Backspace
188 BC Keypad A
189 BD Keypad B
190 BE Keypad C
191 BF Keypad D
192 C0 Keypad E
193 C1 Keypad F
194 C2 Keypad XOR
195 C3 Keypad ^
196 C4 Keypad %
197 C5 Keypad <
198 C6 Keypad >
199 C7 Keypad &
200 C8 Keypad &&
201 C9 Keypad |
202 CA Keypad ||
203 CB Keypad :
204 CC Keypad #
205 CD Keypad Space
206 CE Keypad @
207 CF Keypad !
208 D0 Keypad Memory Store
209 D1 Keypad Memory Recall
210 D2 Keypad Memory Clear
211 D3 Keypad Memory Add
212 D4 Keypad Memory Subtract
213 D5 Keypad Memory Multiply
214 D6 Keypad Memory Divide
215 D7 Keypad +/-
216 D8 Keypad Clear
217 D9 Keypad Clear Entry
218 DA Keypad Binary
219 DB Keypad Octal
220 DC Keypad Decimal
221 DD Keypad Hexadecimal
222-223 DE-DF Reserved
224 E0 Keyboard LeftControl 58 √ √ √ 4/101/104
225 E1 Keyboard LeftShift 44 √ √ √ 4/101/104
226 E2 Keyboard LeftAlt 60 √ √ √ 4/101/104
227 E3 Keyboard Left GUI10;23 127 √ √ √ 104
228 E4 Keyboard RightControl 64 √ √ √ 101/104
229 E5 Keyboard RightShift 57 √ √ √ 4/101/104
230 E6 Keyboard RightAlt 62 √ √ √ 101/104
231 E7 Keyboard Right GUI10;24 128 √ √ √ 104
232-65535 E8-FFFF Reserved

发布了1 篇原创文章 · 获赞 2 · 访问量 1093

猜你喜欢

转载自blog.csdn.net/weixin_42362902/article/details/104171585