目录

一、项目目的

二、CubeIDE项目配置

1、RCC

2、SYS

3、USART6

4、USB_OTG_FS

5、USB_DEVICE

6、NVIC

三、软件设计

1、main.c

2、usbd_custom_hid_if.c

四、运行并测试

1、查找USBD_HID设备

2、测试USBD_HID设备发送

3、测试USBD_HID设备接收、发送


        本例,作者通过创建一个USBD_Custom_HID的键盘项目,并提供一套软件DEMO,向读者介绍此类项目的开发经验、编程入口。

        项目继续使用旺宝红龙开发板STM32F407ZGT7 KIT V1.0。本项目使用的原理图部分如下:

一、项目目的

  • 实现一个USBD_Custom_HID项目;
  • 编写USBD descriptors,如何编写USBD descriptor将由作者的其他文章介绍;
  • 开发板的USBD接口连接到电脑后,自动实现HID驱动;
  • 使用USB分析软件查找到该USBD HID,校验设备参数;
  • 验证USBD HID的收发;
  • 使用USART验证收发;

二、CubeIDE项目配置

        使用STM32CubeIDE,Version: 1.19.0。

1、RCC

        HSE选择外部晶振,USB时钟=48MHz。

2、SYS

        DEBUG选择serial wire.

3、USART6

        设置PG9、PG14为USART6,参数默认。

4、USB_OTG_FS

        Mode选择Device Only,默认MCU管脚PA11、PA12,参数默认。

5、USB_DEVICE

        Class For FS IP选择为:Custom HID。其它参数设置如下图:

6、NVIC

        Time Base的优先级修改为0,其它默认。

三、软件设计

        设置完毕后,通过STM32CubeIDE自动生成软件框架。

1、main.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"

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

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

/* USER CODE BEGIN PV */
uint8_t send_buf[64] = {0};
uint8_t i;
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* MCU Configuration--------------------------------------------------------*/

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

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

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  MX_USART6_UART_Init();
  /* USER CODE BEGIN 2 */
  /**
   * This is the DEMO sent by the HID device.
   * Write whatever you want to send.
   *
   **/
  for(i=0;i<64;i++)
  {
      send_buf[i] = i;
  }
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
//	  USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, send_buf, 64);
//	  send_buf[0]++;
//	  HAL_Delay(2000);
  }
  /* USER CODE END 3 */
}

// 省略以下默认生成的代码

/* USER CODE BEGIN 4 */
int __io_putchar(int ch)
{
	HAL_UART_Transmit(&huart6,(uint8_t*)&ch,1,0xFFFF);
	return ch;
}
/* USER CODE END 4 */

// 省略以下默认生成的代码

        USER CODE BEGIN 3沙箱里的代码的使用方法:

  • 当需要在电脑端的USB分析仪软件连续显示USBD_HID设备发送的数据时,启用此段代码。也就是测试USBD_HID发送,同时注释掉usbd_custom_hid_if.c(这个函数是APP应用接口函数)里的CUSTOM_HID_OutEvent_FS()里的私有代码;
  • 当需要在电脑端的USB分析仪软件发送数据,然后USBD_HID设备接收并转发送该数据时,注释此段代码。也就是测试USBD_HID接收和发送,同时启用usbd_custom_hid_if.c里的CUSTOM_HID_OutEvent_FS()里的私有代码;

2、usbd_custom_hid_if.c

/**
  ******************************************************************************
  * @file           : usbd_custom_hid_if.c
  * @version        : v1.0_Cube
  * @brief          : USB Device Custom HID interface file.
  ******************************************************************************

/* Includes ------------------------------------------------------------------*/
#include "usbd_custom_hid_if.h"

/* USER CODE BEGIN INCLUDE */
#include <stdio.h>
#include "usart.h"
/* USER CODE END INCLUDE */

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
void Test_Report_buf_Print(USBD_CUSTOM_HID_HandleTypeDef *hhid);
/* USER CODE END PV */

/** @defgroup USBD_CUSTOM_HID_Private_Variables USBD_CUSTOM_HID_Private_Variables
  * @brief Private variables.
  * @{
  */

/** Usb HID report descriptor. */
__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
  /* USER CODE BEGIN 0 */
		/**This Desc description must be modified manually
		 * and consistent with the parameters of the CubeMX settings page.
		 * */
	    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)
  /* USER CODE END 0 */
  0xC0    /*     END_COLLECTION	             */
};

/** @defgroup USBD_CUSTOM_HID_Exported_Variables USBD_CUSTOM_HID_Exported_Variables
  * @brief Public variables.
  * @{
  */
extern USBD_HandleTypeDef hUsbDeviceFS;

/** @defgroup USBD_CUSTOM_HID_Private_FunctionPrototypes USBD_CUSTOM_HID_Private_FunctionPrototypes
  * @brief Private functions declaration.
  * @{
  */

static int8_t CUSTOM_HID_Init_FS(void);
static int8_t CUSTOM_HID_DeInit_FS(void);
static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state);

/**
  * @}
  */

USBD_CUSTOM_HID_ItfTypeDef USBD_CustomHID_fops_FS =
{
  CUSTOM_HID_ReportDesc_FS,
  CUSTOM_HID_Init_FS,
  CUSTOM_HID_DeInit_FS,
  CUSTOM_HID_OutEvent_FS
};

//省略以下自动生成的默认代码

/**
  * @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
  */
static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
{
  /* USER CODE BEGIN 6 */

  /**
   * Start next USB packet transfer once data processing is completed.
   *
   * This function is called in the USB Custom HID device of STM32,
   * and is used to handle events after USB receives a packet of data.
   * */
	UNUSED(event_idx);
	UNUSED(state);

	USBD_CUSTOM_HID_HandleTypeDef *hhid = hUsbDeviceFS.pClassData;
	if (USBD_CUSTOM_HID_ReceivePacket(&hUsbDeviceFS) != (uint8_t)USBD_OK)
	{
		return -1;
	}
	else{
		printf("Received DATA is ");
		Test_Report_buf_Print(hhid);		//test
	}

	/**
	  * @brief  pClassData points to the data interface of USB Device Class.
	  *         Further,
	  *         hUsbDeviceFS.pClassData is the instantiation of hhid.
	  */

	USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, hhid->Report_buf,64);

	printf("Transmitted DATA is ");
	Test_Report_buf_Print(hhid);	//test
	return (USBD_OK);
  /* USER CODE END 6 */
}

/* USER CODE BEGIN 7 */
/**
  * @brief  Send the report to the Host
  * @param  report: The report to be sent
  * @param  len: The report length
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
/*
static int8_t USBD_CUSTOM_HID_SendReport_FS(uint8_t *report, uint16_t len)
{
  return USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, report, len);
}
*/
/* USER CODE END 7 */

/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
void Test_Report_buf_Print(USBD_CUSTOM_HID_HandleTypeDef *hhid)
{
	printf("Report_buf[63]:\r\n");
	for(int i=0;i<USBD_CUSTOMHID_OUTREPORT_BUF_SIZE;i++){
		printf("%d ",hhid->Report_buf[i]);
	}
	printf("\r\n");
	for(int i=0;i<USBD_CUSTOMHID_OUTREPORT_BUF_SIZE;i++){
		printf("%c",hhid->Report_buf[i]);
	}
	printf("\r\n");
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */

        该段代码中的Usb HID report descriptor是需要设计者设计的,具体的设计方法可以参考本文作者的其他文章。

四、运行并测试

        编译后下载到开发板上。注意,下载的时候关闭USB分析仪软件,否则USB分析仪软件因为固件更新而连接不上导致卡死。

        有很多USB分析仪软件,本文使用单片机多功能调试助手,PortHelper.exe.

1、查找USBD_HID设备

        查找到STM32 Custom HID设备,就是本项目生成的设备,电脑端正常自动驱动。截图中的PID、VID、PVN都是CubeMX设置的,其含义为:

2、测试USBD_HID设备发送

        按照上面文字里的规定,生成和下载代码。

        接收区,1帧,64字节数据,数据内容是程序赋值的,帧头、1、2、...、63,共64个字节。每相邻两帧间隔2ms。

        开启监视后的效果,该结果可以另存为CSV文件。

3、测试USBD_HID设备接收、发送

        按照上面文字里的规定,生成和下载代码。

        一共发了2次数据,发送的是字符,ASCII字符,64字节,1个字符占一个字节,空格也占一个字节。多余的字节被忽略。

        在串口助手上,共收到4组数据,每组里包括接收到的和发送出去的。无论接收到还是发送出去的,都有两种格式,一种ASCII字符,一种ASCII 16进制值。

        USB分析仪上,也接收到了2次数值,只能显示16进制数值,不能显示字符。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐