STM32

STM32CubeMX学习笔记(44)——USB接口使用(HID

2022-10-26  本文已影响0人  Leung_ManWah

一、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 进行具体参数配置。

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) 人机接口设备。


参数配置保持默认。

设备描述符保持默认。


四、添加按键

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配置全速描述符数组定义处。

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

  /******************** 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) 描述
0 bLength 1 数字 此描述符的长度,以字节为单位
1 bDescriptorType 1 常量 描述符种类(此处 0x21为HID类)
2 bcdHID 2 数字 HID规范版本号(BCD码),采用4个16进制的BCD格式编码
4 bCountryCode 1 数字 硬件目的国家的识别码
5 bNumDescriptors 1 数字 支持的附属描述符数目
6 bDescriptorType 1 常量 0x21-HID描述符,0x22-报告描述符,0x23-实体描述符
7 wDescriptorLength 2 数字 报告描述符的总长度
9 bDescriptorType 1 常量 用于识别描述符类型的常量,使用有一个以上描述符的设备
10 wDescriptorLength 2 数字 描述符总长度,使用在有一个以上描述符的设备
  /******************** 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 NUSER CODE END N 之间,否则下次使用 STM32CubeMX 重新生成代码后,会被删除。

如果USB端口出现感叹号设备无法启动的问题,可适当将堆改大,如0x400



• 由 Leung 写于 2022 年 10 月 26 日

• 参考:STM32F042F6P6-USB设备开发最小系统之键盘示例
    USB 协议分析之 HID 设备
    关于STM32的USB设备库DIY机械键盘
    STM32-USB学习系列(六):USB-HID键盘的实现以及键盘报文描述符的简介
    DIY一个usb数字键盘(一) 基于stm32cubemx HAL库 usb hid协议
    DIY一个usb数字键盘(二)逻辑部分 基于stm32cubemx HAL库 usb hid协议
    STM32 基础系列教程 24 - USB_HID_key

上一篇下一篇

猜你喜欢

热点阅读