全文目录

  • 参考文章
    • 创建CubeMX工程
      • 一、新建工程
      • 二、USB
      • 三、生成代码
      • 四、了解usbd_hid.c
    • 更改代码实现鼠标改键盘
    • 键码值(keyCode)
    • 补充

参考文章

STM32CubeMX学习笔记(45)——USB接口使用(HID鼠标)
STM32-USB学习系列(六):USB-HID键盘的实现以及键盘报文描述符的简介
HID设备(USB键鼠/扫码枪)转串口(UART)键盘键值及字符处理示例——CH9350
本文对在以上三篇文章中引用的内容进行整合,并通过实践验证了各个步骤的可行性,增加了代码修改方面的相关细节

创建CubeMX工程

一、新建工程

  1. 打开 STM32CubeMX 软件,点击“新建工程”
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图
  2. 选择 MCU 和封装
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(1)
  3. 配置时钟
    RCC 设置,选择 HSE(外部高速时钟) 为 Crystal/Ceramic Resonator(晶振/陶瓷谐振器)
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(2)
    选择 Clock Configuration,配置系统时钟 SYSCLK 为 72MHz
    修改 HCLK 的值为 72 后,输入回车,软件会自动修改所有配置
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(3)
  4. 配置调试模式
    非常重要的一步,否则会造成第一次烧录程序后续无法识别调试器
    SYS 设置,选择 Debug 为 Serial Wire
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(4)

二、USB

  1. 参数配置
    Connectivity 中选择 USB 设置,并勾选 Device (FS) 激活 USB 设备。
    “FS” stands for “Full Speed”.
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(5)

    Parameter Settings 进行具体参数配置。
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(6)
    Speed: Full Speed 12MBit/s(固定为全速)
    Low Power: 默认 Disabled(在任何不需要使用usb模块的时候,通过写控制寄存器总可以使usb模块置于低功耗模式(low power mode ,suspend模式)。在这种模式下,不产生任何静态电流消耗,同时usb时钟也会减慢或停止。通过对usb线上数据传输的检测,可以在低功耗模式下唤醒usb模块。也可以将一特定的中断输入源直接连接到唤醒引脚上,以使系统能立即恢复正常的时钟系统,并支持直接启动或停止时钟系统。)

  2. 引脚配置
    USB 的 DP 引脚必须上拉 1.5K 欧的电阻,电脑才能检测到 USB,否则检测不到。
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(7)

    野火:需要将 PD6 配置为低电平使能 USB
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(8)
    在右边图中找到 PD6 引脚,选择 GPIO_Output
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(9)

    GPIO output level 中选择 Low 输出低电平。
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(10)

    正点原子:只需将排针4–6和3–5分别用跳线帽相连
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(11)
    由于本次需要实现USB HID keyboard,故需要使用开关KEY0~2。可参照以上的GPIO配置步骤将相应的引脚配置为GPIO_Input,Pull_up。

  3. 配置时钟
    选择 Clock Configuration,USB 时钟配置为 48MHz,且来源最好是外部晶振分频得到。
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(12)

  4. USB Device

    USB有主机(Host)和设备(Device)之分。一般电脑的USB接口为主机接口,而键盘、鼠标、U盘等则为设备。
    部分型号的STM32芯片有1~2个USB接口。像STM32F103系列的有一个USB
    Device接口,STM32F407系列的有2个USB接口,既可以作为HOST,又可以作为Device,还可以作为OTG接口。

    Middleware 中选择 USB_DEVICE 设置,在 Class For FS IP 设备类别选择 Human Interface Device Class (HID)人机接口设备。
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(13)

    参数配置保持默认。
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(14)
    HID_FS_BINTERVAL(主机读取设备数据时间间隔)0xA(STM32将数据发送到一个缓存区,而不是直接发送到上位机,而上位机每隔一端时间会来访问缓冲区读取数据。读取时间间隔过快会导致多次数据发送,过慢会导致数据丢失)
    USBD_MAX_NUM_INTERFACES (Maximum number of supported interfaces)(最大支持HID设备的接口数)1(应为现在只有鼠标,所以1就行,如果是需要同时键盘,鼠标,手柄之类的,根据数量选择即可)

    设备描述符保持默认。
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(15)

三、生成代码

  1. 输入项目名和项目路径
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(16)
  2. 选择应用的 IDE 开发环境 MDK-ARM V5
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(17)
  3. 每个外设生成独立的 ’.c/.h’ 文件
    不选:所有初始化代码都生成在 main.c
    勾选:初始化代码生成在对应的外设文件。 如 GPIO 初始化代码生成在 gpio.c 中。
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(18)
  4. 点击 GENERATE CODE 生成代码
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(19)

四、了解usbd_hid.c

打开工程文件夹Middlewares/USB_Device_Libraryusbd_hid.c文件
STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(20)

  1. USB HID描述符
    HID设备的描述符除了5个USB的标准描述符(设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符)外,还包括3个HID设备类特定的描述符:HID描述符、报告描述符(Report)、实体描述符(Physical)。
    他们之间的层次关系如图:
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(21)
    打开usbd_hid.c文件,找到USBD_HID_CfgFSDesc配置全速(Full Speed)描述符数组定义处(由于配置USB设备时将其置为了全速,所以不用管USBD_HID_CfgHSDesc(High Speed))

    • 配置描述符
    bNumInterfaces表示这个设备有多少个接口。
    MaxPower 100 mA表示这个设备需要从总线上获取100mA电流。

    /* USB HID device FS Configuration Descriptor */
    __ALIGN_BEGIN static uint8_t USBD_HID_CfgFSDesc[USB_HID_CONFIG_DESC_SIZ]  __ALIGN_END =
    {
      0x09, /* bLength: Configuration Descriptor size */
      USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
      USB_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*/
      0xE0,         /*bmAttributes: bus powered and Support Remote Wake-up */
      0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*/
    

    • 接口描述符
    bInterfaceClass的值必须是 0x03
    bInterfaceSubClass的值为 0 或 1, 为1表示HID设备是一个启动设备(BootDevice, 一般对PC机有意义,意思是BIOS启动时能识别所使用的HID设备,且只有标准鼠标或者键盘才能称为BootDevice),为0表示HID设备是操作系统启动厚才能识别使用的设备。
    bInterfaceProtocol的值为 2 表示鼠标接口:(0 — NONE,1 — Keyboard(键盘),2 — Mouse (鼠标),3~255 Reserved)

      /************** Descriptor of Joystick Mouse interface ****************/
      /* 09 */
      0x09,         /*bLength: Interface Descriptor size*/
      USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
      0x00,         /*bInterfaceNumber: Number of Interface*/
      0x00,         /*bAlternateSetting: Alternate setting*/
      0x01,         /*bNumEndpoints*/
      0x03,         /*bInterfaceClass: HID*/
      0x01,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
      0x02,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
      0,            /*iInterface: Index of string descriptor*/
    

    • HID描述符
    HID描述符关联于接口描述符,因而如果一个设备只有一个接口描述符,则无论它有几个端点描述符,HID设备只有一个HID描述符。HID设备描述符主要描述HID规范的版本号, HID通信所使用的额外描述符,报告描述符的长度等。

      /******************** Descriptor of Joystick Mouse HID ********************/
      /* 18 */
      0x09,         /*bLength: HID Descriptor size*/
      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_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
      0x00,
    

    • 端点描述符
    bEndpointAddress表示端点地址,表示当前这个接口所需要的端点资源,输入(相对于主机而言)端点最高位为1,输出(相对于主机而言)端点最高位为0。HID设备一般都是使用中断端点进行数据传输。
    wMaxPacketSize表示该端点上数据传输的数量。
    bInterval表示主机查询设备数据的时间间隔,如果设置的太长,则键盘输入延迟很高。

  2. 报告描述符
    下载 HID Descriptor Tool (DT) HID描述符工具:
    官网下载:http://usb.org/sites/default/files/documents/dt2_4.zip
    百度网盘:http://pan.baidu.com/s/1ayjdQtc7e9NWwYJqdp0pXA?pwd=4ghb 提取码:4ghb
    打开 FileOpen...mouse.hid (键盘应该使用keybrd.hid,但本文为在程序中保留鼠标相关内容,故在mouse.hid中直接进行修改)
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(22)

    我们可以看到HID鼠标的描述符情况:
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(23)

    打开usbd_hid.c文件,找到HID_MOUSE_ReportDesc数组定义处(默认生产HID设备为Mouse,所以需要增加键盘数组)。
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(24)

更改代码实现鼠标改键盘

  1. 修改HID的接口描述符与报文描述符
    注意:端点描述符不做修改!即 HID_EPIN_SIZE 还是0x04 (对应4字节大小,后面在发送键盘报文的时候,需要将键盘的报文大小修改为 4个字节的数组或者结构体)
    usbd_hid.h中引入宏定义USE_KEYBOARD_HIDHID_KEYBOARD_REPORT_DESC_SIZE

    #define USE_KEYBOARD_HID 1	//WY: 1=enable; 0=disable
    		
    #define HID_EPIN_ADDR                 0x81U
    #define HID_EPIN_SIZE                 0x04U
    	
    #define USB_HID_CONFIG_DESC_SIZ       34U
    #define USB_HID_DESC_SIZ              9U
    #define HID_MOUSE_REPORT_DESC_SIZE    74U
    #define HID_KEYBOARD_REPORT_DESC_SIZE	63U	//WY: for keyboard
    

    USBD_HID_CfgFSDesc中修改

      /************** Descriptor of Joystick Mouse interface ****************/
      /* 09 */
      0x09,         /*bLength: Interface Descriptor size*/
      USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
      0x00,         /*bInterfaceNumber: Number of Interface*/
      0x00,         /*bAlternateSetting: Alternate setting*/
      0x01,         /*bNumEndpoints*/
      0x03,         /*bInterfaceClass: HID*/
      0x01,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
    #if(USE_KEYBOARD_HID)
      0x01,         //WY: nInterfaceProtocol: keyboard
    #else
      0x02,		/*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
    #endif
      0,            /*iInterface: Index of string descriptor*/
    
      /******************** Descriptor of Joystick Mouse HID ********************/
      /* 18 */
      0x09,         /*bLength: HID Descriptor size*/
      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*/
    #if(USE_KEYBOARD_HID)
      HID_KEYBOARD_REPORT_DESC_SIZE,
    #else
      HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
    #endif
      0x00,
    
  2. 修改USBD_HID_Setup函数
    在HID Setup的过程中会获取对应键盘报文描述符

     case USB_REQ_GET_DESCRIPTOR:
              if (req->wValue >> 8 == HID_REPORT_DESC)
              {
    #if(USE_KEYBOARD_HID)
    			len = MIN(HID_KEYBOARD_REPORT_DESC_SIZE, req->wLength);
                pbuf = HID_KEYBOARD_ReportDesc;
    #else
                len = MIN(HID_MOUSE_REPORT_DESC_SIZE, req->wLength);
                pbuf = HID_MOUSE_ReportDesc;
    #endif
              }
    
  3. 添加以及修改键盘报文描述符
    注意:修改部分为最后面按键输入描述部分,将后面6个按键缩减为2个按键(即:从6个字节缩减到2个字节),配合上前面2个字节的输入报告,正好是4个字节,刚好符合原来HID端点描述符一次最多发送的大小
    将原有HID_MOUSE_ReportDesc的内容注释掉,并在其后增加以下定义

    __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) /* 表示应用结合,必须以END_COLLECTION来结束 */
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)  /* 用途页为按键 */
    0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)  /* 用途最小值 左Ctrl */
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)	  /* 用途最大值 右GUI */
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)	   /* 逻辑最小值 0 */
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)	   /* 逻辑最大值 1 */
    0x75, 0x01,                    //   REPORT_SIZE (1)      /* 报告位大小(这个字段的宽度为1bit) */
    0x95, 0x08,                    //   REPORT_COUNT (8) 	 /* 输入报告第一个字节(报告位大小 8bit) */
    0x81, 0x02,                    //   INPUT (Data,Var,Abs) /* 报告为输入用 , 从左ctrl到右GUI 8bit刚好构成1个字节*/
    0x95, 0x01,                    //   REPORT_COUNT (1)	 /* 报告位数量  1个 */
    0x75, 0x08,                    //   REPORT_SIZE (8)      /* 输入报告的第二给字节(报告位大小 8bit) */
    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs) /* 输入用的保留位,设备必须返回0 */
    0x95, 0x05,                    //   REPORT_COUNT (5)     /* 报告位数量 5个 */
    0x75, 0x01,                    //   REPORT_SIZE (1)		 /* 报告位大小,1bit */
    0x05, 0x08,                    //   USAGE_PAGE (LEDs)    /* 用途为LED */
    0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock) /* 用途最小值 NUM Lock LED灯 */
    0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)  /* 用途最大值 Kana 灯 */
    0x91, 0x02,                    //   OUTPUT (Data,Var,Abs) /* 输出用途,用于控制LED等 */
    0x95, 0x01,                    //   REPORT_COUNT (1)     /* 报告位数量 1个 */
    0x75, 0x03,                    //   REPORT_SIZE (3)      /* 报告位大小 3bit */
    0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)/* 用于字节补齐,跟前面5个bit进行补齐 */
    0x95, 0x02,                    //   REPORT_COUNT (6)  /* 报告位数量 6个*/
    0x75, 0x08,                  	//   REPORT_SIZE (8)		 /* 报告位大小 8bit */
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)		 /* 逻辑最小值0 */
    0x25, 0xFF,                    //   LOGICAL_MAXIMUM (255)    /* 逻辑最大值255 */
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)    /* 用途页为按键 */
    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated)) /* 使用值最小为0 */
    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)		  /* 使用值最大为65 */
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)	 /* 输入用,变量,数组,绝对值 */
    0xc0  						   								 /* END_COLLECTION */
    };
    

键码值(keyCode)

  1. 以键盘为例(扫码枪一般模拟键盘输入)报文示例如下:
    STM32CubeMX实现USB HID keyboard(鼠标改键盘)插图(25)
    报文前三个字节的固定内容可自动生成,故代码中只需通过后8个字节传递正确的键码值,例如在main.c中定义:

    uint8_t txbuffer[8]= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    uint8_t sendbuffer_Enter[8]={0x00,0x00,0x28,0x00,0x00,0x00,0x00,0x00};
    uint8_t sendbuffer_Aa[8]={0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00};
    uint8_t sendbuffer_Space[8]={0x00,0x00,0x2C,0x00,0x00,0x00,0x00,0x00};
    

    发送报文使用USBD_HID_SendReport函数,为使代码友好易读,故在usb_device.c中对此函数进行封装,以便在main函数中直接调用:

    uint8_t MX_USB_DEVICE_Send(uint8_t *sendbuffer)
    {	
    return USBD_HID_SendReport(&hUsbDeviceFS,sendbuffer,8);	//Full speed
    }
    
  2. 全键盘码值表如下提供参考:

    //Keybord keyvalue define
    #define KEY_NULL 0x00          // NULL
    #define KEY_A 0x04             // A
    #define KEY_B 0x05             // B
    #define KEY_C 0x06             // C
    #define KEY_D 0x07             // D
    #define KEY_E 0x08             // E
    #define KEY_F 0x09             // F
    #define KEY_G 0x0A             // G
    #define KEY_H 0x0B             // H
    #define KEY_I 0x0C             // I
    #define KEY_J 0x0D             // J
    #define KEY_K 0x0E             // K
    #define KEY_L 0x0F             // L
    #define KEY_M 0x10             // M
    #define KEY_N 0x11             // N
    #define KEY_O 0x12             // O
    #define KEY_P 0x13             // P
    #define KEY_Q 0x14             // Q
    #define KEY_R 0x15             // R
    #define KEY_S 0x16             // S
    #define KEY_T 0x17             // T
    #define KEY_U 0x18             // U
    #define KEY_V 0x19             // V
    #define KEY_W 0x1A             // W
    #define KEY_X 0x1B             // X
    #define KEY_Y 0x1C             // Y
    #define KEY_Z 0x1D             // Z
    #define KEY_1 0x1E             // 1 and !
    #define KEY_2 0x1F             // 2 and @
    #define KEY_3 0x20             // 3 and #
    #define KEY_4 0x21             // 4 and $
    #define KEY_5 0x22             // 5 and %
    #define KEY_6 0x23             // 6 and ^
    #define KEY_7 0x24             // 7 and &
    #define KEY_8 0x25             // 8 and *
    #define KEY_9 0x26             // 9 and (
    #define KEY_0 0x27             // 10 and )
    #define KEY_ENTER 0x28         // ENTER
    #define KEY_ESC 0x29           // ESC
    #define KEY_BACKSPACE 0x2A     // BACKSPACE
    #define KEY_TAB 0x2B           // TAB
    #define KEY_SPACE 0x2C         // SPACE
    #define KEY_SUB 0x2D           // - and _
    #define KEY_EQUAL 0x2E         // = and +
    #define KEY_LEFT_BRACKET 0x2F  // [ and {
    #define KEY_RIGHT_BRACKET 0x30 // ] and }
    #define KEY_VERTICAL_LINE 0x31 // "\" and |
    #define KEY_WAVE 0x32          // ` and ~
    #define KEY_SEMICOLON 0x33     // ; and :
    #define KEY_QUOTE 0x34         // ' and "
    #define KEY_THROW 0x35         // ~ and `
    #define KEY_COMMA 0x36         // , and <
    #define KEY_DOT 0x37           // . and >
    #define KEY_QUESTION 0x38      // / and ?
    #define KEY_CAPS_LOCK 0x39     // CAPS
    #define KEY_F1 0x3A
    #define KEY_F2 0x3B
    #define KEY_F3 0x3C
    #define KEY_F4 0x3D
    #define KEY_F5 0x3E
    #define KEY_F6 0x3F
    #define KEY_F7 0x40
    #define KEY_F8 0x41
    #define KEY_F9 0x42
    #define KEY_F10 0x43
    #define KEY_F11 0x44
    #define KEY_F12 0x45
    #define KEY_PRT_SCR 0x46
    #define KEY_SCOLL_LOCK 0x47
    #define KEY_PAUSE 0x48
    #define KEY_INS 0x49
    #define KEY_HOME 0x4A
    #define KEY_PAGEUP 0x4B
    #define KEY_DEL 0x4C
    #define KEY_END 0x4D
    #define KEY_PAGEDOWN 0x4E
    #define KEY_RIGHT_ARROW 0x4F
    #define KEY_LEFT_ARROW 0x50
    #define KEY_DOWN_ARROW 0x51
    #define KEY_UP_ARROW 0x52
    //Num Pad
    #define KEY_PAD_NUMLOCK 0x53
    #define KEY_PAD_DIV 0x54
    #define KEY_PAD_MUL 0x55
    #define KEY_PAD_SUB 0x56
    #define KEY_PAD_ADD 0x57
    #define KEY_PAD_ENTER 0x58
    #define KEY_PAD_1 0x59
    #define KEY_PAD_2 0x5A
    #define KEY_PAD_3 0x5B
    #define KEY_PAD_4 0x5C
    #define KEY_PAD_5 0x5D
    #define KEY_PAD_6 0x5E
    #define KEY_PAD_7 0x5F
    #define KEY_PAD_8 0x60
    #define KEY_PAD_9 0x61
    #define KEY_PAD_0 0x62
    #define KEY_PAD_DOT 0x63
    #define KEY_PRESSED 0x00
    #define KEY_RELEASED 0x01
    // Control
    #define KEY_LCTRL 0xE0  // left ctrl // #define KEY_LCTRL 0x01
    #define KEY_LALT 0xE2   // left Alt // #define KEY_LALT 0x04
    #define KEY_LSHFIT 0xE1 // left Shift // #define KEY_LSHFIT 0x02
    #define KEY_LWIN 0xE3   // left windows // #define KEY_LWIN 0x08
    #define KEY_RWIN 0xE7   // right windows // #define KEY_RWIN 0x80
    #define KEY_RSHIFT 0xE5 // right Shift // #define KEY_RSHIFT 0x20
    #define KEY_RALT 0xE6   // right Alt // #define KEY_RALT 0x40
    #define KEY_RCTRL 0xE4  // right Ctrl // #define KEY_RCTRL 0x10
    #define KEY_APP 0x65    // Application // #define KEY_APP 0x65
    #define KEY_K14 0x89    // international key
    #define KEY_KR_L 0x91
    #define KEY_K107 0x85
    #define KEY_K45 0x64
    #define KEY_K42 0x32
    #define KEY_K131 0x8b
    #define KEY_K132 0x8a
    #define KEY_K133 0x88
    #define KEY_K56 0x87
    #define KEY_KR_R 0x90
    

补充

电脑设备管理器显示“未知USB设备(设备描述符请求失败)”时:
个人经验:
最好在CubeMX程序第一次生成之后(无改动)确认是否能识别设备,若此时识别成功,则之后再遇“未知USB设备(设备描述符请求失败)”问题时,重新插拔USB接口即可恢复正常。

本站无任何商业行为
个人在线分享 » STM32CubeMX实现USB HID keyboard(鼠标改键盘)
E-->