STM32CubeMX学习笔记-USB接口使用(HID按键)


原创链接 1

一、USB简介

USB(Universal Serial BUS)通用串行总线,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯。是应用在 PC 领域的接口技术。USB 接口支持设备的即插即用和热插拔功能。USB 是在 1994 年底由英特尔、康柏、IBM、Microsoft 等多家公司联合提出的。

USB 发展到现在已经有 USB1.0/1.1/2.0/3.0 等多个版本。目前用的最多的就是 USB1.1 和 USB2.0,USB3.0 目前已经开始普及。STM32F103 自带的 USB 符合 USB2.0 规范,不过 STM32F103 的 USB 都只能用来做设备,而不能用作主机。

标准 USB 共四根线组成,除 VCC/GND 外,另外为 D+,D-; 这两根数据线采用的是差分电压的方式进行数据传输的。在 USB 主机上,D-和 D+都是接了 15K 的电阻到低的,所以在没有设备接入的时候,D+、D-均是低电平。而在 USB 设备中,如果是高速设备,则会在 D+上接一个 1.5K 的电阻到 VCC,而如果是低速设备,则会在 D-上接一个 1.5K 的电阻到 VCC。这样当设备接入主机的时候,主机就可以判断是否有设备接入,并能判断设备是高速设备还是低速设备。

STM32F103 的 MCU 自带 USB 从控制器,符合 USB 规范的通信连接;PC 主机和微控制器之间的数据传输是通过共享一专用的数据缓冲区来完成的,该数据缓冲区能被 USB 外设直接访问。这块专用数据缓冲区的大小由所使用的端点数目和每个端点最大的数据分组大小所决定,每个端点最大可使用 512 字节缓冲区(专用的 512 字节,和 CAN 共用),最多可用于 16 个单向或 8 个双向端点。USB 模块同 PC 主机通信,根据 USB 规范实现令牌分组的检测,数据发送/接收的处理,和握手分组的处理。整个传输的格式由硬件完成,其中包括 CRC 的生成和校验。

1.1 USB HID简介

USB HID类是USB设备的一个标准设备类,包括的设备非常多。HID类设备定义它属于人机交互操作的设备,用于控制计算机操作的一些方面,如USB鼠标、USB键盘、USB游戏操纵杆等。但HID设备类不一定要有人机接口,只要符合HID类别规范的设备都是HID设备。

USB HID设备的一个好处就是操作系统自带了HID类的驱动程序,而用户无需去开发驱动程序,只要使用API系统调用即可完成通信。

官方资料:http://www.usb.org/developers/hidpage
其中包含最主要的两个说明:

《Device Class Definition for human interface device (HID)》【描述了 HID 的基本组成和格式】
《Universal Serial Bus HID Usage Tables》【对上面文档的补充,将各种不同的 HID 设备的基本组成列举出来】

二、新建工程

1. 打开 STM32CubeMX 软件,点击“新建工程”

在这里插入图片描述

2. 选择 MCU 和封装

在这里插入图片描述

3. 配置时钟

RCC 设置,选择 HSE(外部高速时钟) 为 Crystal/Ceramic Resonator(晶振/陶瓷谐振器)
在这里插入图片描述

选择 Clock Configuration,配置系统时钟 SYSCLK 为 72MHz
修改 HCLK 的值为 72 后,输入回车,软件会自动修改所有配置
在这里插入图片描述

4. 配置调试模式

非常重要的一步,否则会造成第一次烧录程序后续无法识别调试器
SYS 设置,选择 Debug 为 Serial Wire
在这里插入图片描述

三、USB

3.1 参数配置

Connectivity 中选择 USB 设置,并勾选 Device(FS) 激活 USB 设备。
在这里插入图片描述

Parameter Settings 进行具体参数配置。
在这里插入图片描述

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

3.2 引脚配置

USB 的 DP 引脚必须上拉 1.5K 欧的电阻,电脑才能检测到 USB,否则检测不到。

查看野火指南者开发板原理图可知,需要将 PD6 配置为低电平使能 USB。
在这里插入图片描述

在右边图中找到 PD6 引脚,选择 GPIO_Output。
在这里插入图片描述

在GPIO output level 中选择 Low 输出低电平。
在这里插入图片描述

3.3 配置时钟

选择 Clock Configuration,USB 时钟配置为 48MHz,且来源最好是外部晶振分频得到。
在这里插入图片描述

3.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) 人机接口设备。
在这里插入图片描述

参数配置保持默认。
在这里插入图片描述

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

四、添加按键

4.1 GPIO配置

System Core 中选择 GPIO 设置。
在这里插入图片描述

在右边图中找到按键对应引脚,选择 GPIO_Input
在这里插入图片描述

五、生成代码

输入项目名和项目路径
在这里插入图片描述

选择应用的 IDE 开发环境 MDK-ARM V5
在这里插入图片描述

每个外设生成独立的 ’.c/.h’ 文件
不勾:所有初始化代码都生成在 main.c
勾选:初始化代码生成在对应的外设文件。 如 GPIO 初始化代码生成在 gpio.c 中。
在这里插入图片描述

点击 GENERATE CODE 生成代码
在这里插入图片描述

六、修改usbd_hid.c

打开工程文件夹Middlewares/USB_Device_Libraryusbd_hid.c文件
在这里插入图片描述

6.1 修改接口描述符(可跳过)

HID设备的描述符除了5个USB的标准描述符(设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符)外,还包括三个HID设备类特定的描述符:HID描述符、报告描述符(Report)、实体描述符(Physical)
他们之间的层次关系如图:
在这里插入图片描述

打开usbd_hid.c文件,找到USBD_HID_CfgFSDesc配置全速描述符数组定义处。

●配置描述符
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设备是操作系统启动厚才能识别使用的设备。

  /************** 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*/

这里我们将bInterfaceProtocol的值改为1:(0 — NONE,1 — Keyboard(键盘),2 — Mouse (鼠标),3~255 Reserved)
在这里插入图片描述

●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,

下表为HID描述符的结构。

偏移量大小(Byte)描述
0bLength1数字此描述符的长度,以字节为单位
1bDescriptorType1常量描述符种类(此处 0x21为HID类)
2bcdHID2数字HID规范版本号(BCD码),采用4个16进制的BCD格式编码
4bCountryCode1数字硬件目的国家的识别码
5bNumDescriptors1数字支持的附属描述符数目
6bDescriptorType1常量0x21-HID描述符,0x22-报告描述符,0x23-实体描述符
7wDescriptorLength2数字报告描述符的总长度
9bDescriptorType1常量用于识别描述符类型的常量,使用有一个以上描述符的设备
10wDescriptorLength2数字描述符总长度,使用在有一个以上描述符的设备

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

  /******************** Descriptor of Mouse endpoint ********************/
  /* 27 */
  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: 4 Byte max */
  0x00,
  HID_FS_BINTERVAL,          /*bInterval: Polling Interval */
  /* 34 */
};

6.2 修改报告描述符

下载 HID Descriptor Tool (DT) HID描述符工具:
官网下载:https://usb.org/sites/default/files/documents/dt2_4.zip
百度网盘:https://pan.baidu.com/s/1ayjdQtc7e9NWwYJqdp0pXA?pwd=4ghb 提取码:4ghb

打开 File——》Open...——》keybrd.hid
在这里插入图片描述

我们可以看到HID键盘的描述符情况:
在这里插入图片描述

打开usbd_hid.c文件,找到HID_MOUSE_ReportDesc数组定义处(默认生产HID设备为Mouse,这里数组名不影响,只要里面的描述符是键盘的就行)。

 0x05, 0x01, // USAGE_PAGE (Generic Desktop) //63
 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

在这里插入图片描述

6.3 修改报告描述符大小

打开usbd_hid.h文件,修改HID_MOUSE_REPORT_DESC_SIZE的值为63

七、修改main.c

添加头文件和USB设备句柄。

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usbd_hid.h"
/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
extern USBD_HandleTypeDef hUsbDeviceFS;

添加一个数组变量,用于传输键盘参数的,Byte0是传控制键,Byte1是保留键,不用改;Byte3~byte7都可以存放传输的按键值。

/* USER CODE BEGIN PV */
/*
 * buffer[0] - bit0: Left CTRL
 *           -bit1: Left SHIFT
 *           -bit2: Left ALT
 *           -bit3: Left GUI
 *           -bit4: Right CTRL
 *           -bit5: Right SHIFT
 *           -bit6: Right ALT
 *           -bit7: Right GUI 
 * buffer[1] - Padding = Always 0x00
 * buffer[2] - Key 1
 * buffer[3] - Key 2
 * buffer[4] - Key 3
 * buffer[5] - Key 4
 * buffer[6] - Key 5
 * buffer[7] - Key 6
 */
uint8_t buffer[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/* USER CODE END PV */

添加按键检测及传输键值到电脑。

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
//    usb_printf("\r\n****** USB-HID Keyboard Example ******\r\n\r\n");
    if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 0)
    {  
      buffer[0] = 0x02; //shift
      buffer[2] = 0x04; //a
      USBD_HID_SendReport(&hUsbDeviceFS, buffer, 8); //send
      HAL_Delay(15); //delay
     
      buffer[0] = 0x00;
      buffer[2] = 0x00;
      USBD_HID_SendReport(&hUsbDeviceFS, buffer, 8);
      HAL_Delay(15);
     
      while(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 0)
      HAL_Delay(15);
    }
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

在这里插入图片描述

对应键值可和此文件中的HID Usage ID对应,是16进制(如字符‘a’对应键值为0x04)
USB_HIDtoKBScanCodeTranslationTable.pdf
在这里插入图片描述

八、查看效果

编译工程,下载到板子上,插上USB线连接到电脑上,识别出为键盘设备
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

注意: 如果设备带有感叹号,则参考下面十、注意事项

按下按键时在电脑上输入一个大写的‘A’。

九、工程代码

链接:https://pan.baidu.com/s/1E7wwefhBNgCRKX1tgG0kxA?pwd=agm4 提取码:agm4

十、注意事项

用户代码要加在 USER CODE BEGIN N 和 USER CODE END N 之间,否则下次使用 STM32CubeMX 重新生成代码后,会被删除。
在这里插入图片描述

如果USB端口出现感叹号设备无法启动的问题,可适当将堆改大,如0x400
在这里插入图片描述
在这里插入图片描述


  1. 链接地址:https://www.jianshu.com/p/0bd36e2a7f07 作者:Leung_ManWah ↩︎

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
en.stm32cubemx-win-v6-9-1是一个针对STMicroelectronics的STM32微控制器系列的软件工具。这个软件工具可在Windows操作系统上使用,其版本号为6.9.1。 STM32微控制器系列是STMicroelectronics推出的一种低功耗、高性能的微控制器芯片系列。这些微控制器芯片广泛用于嵌入式系统、物联网设备、工业自动化以及各种电子产品中。STM32微控制器系列有多个不同的型号和系列,每个型号都有不同的功能和性能特点。 en.stm32cubemx-win-v6-9-1是用于STM32微控制器系列的软件工具。它具有通过图形化界面进行配置和生成代码的功能,使得开发人员可以更加方便地进行STM32微控制器的软件开发。通过这个软件工具,开发人员可以选择不同的模块、外设和功能,然后生成相应的初始化代码。这个软件工具还可以提供一些自动生成的模版,使得开发人员可以快速开始开发。 除了代码生成外,en.stm32cubemx-win-v6-9-1还提供了一些其他功能。例如,它可以通过图形化界面配置时钟树、引脚映射、中断优先级等。此外,该软件工具还可以集成其他开发环境,例如Keil或IAR,以便更直接地进行代码编辑和编译。 总而言之,en.stm32cubemx-win-v6-9-1是一个用于STM32微控制器系列的软件工具,它提供了图形化界面配置和生成代码的功能,帮助开发人员更方便地进行STM32微控制器的软件开发。它是一个很有用的工具,可以提高开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谢谢~谢先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值