简介
- 前面了解了 STM32 CUSTOM HID 设备,但是有几个细节没有处理好,如接收到主机的报告后,如何接收到指定的数组,并实现通信功能,如控制LED亮灭?
- 还有就是CUSTOM HID设备的【报告描述符】,是否可以多【描述】几个,我控制几个LED灯,可能几个字节就可以了,不需要上来就发送【64字节】
USB HID接收
- 使用
STM32CubeMX
生成的 USB custom hid 功能,我仔细看了下,能接收 USB主机(电脑端)报告的函数接口为usbd_custom_hid_if.c
中的函数CUSTOM_HID_OutEvent_FS
- 当然默认工程,
CUSTOM_HID_OutEvent_FS
貌似没有做什么操作,造成不清楚如何处理接收的报告(数据) - 这里需要手动更改这个函数,接收主机的报告数据,并进行LED控制
修改方法
- 添加led.c 与 led.h两个 led BSP文件,用于实现三个LED的引脚初始化、提供三个LED亮灭控制函数
- led.c
#include "led.h"
/ all LEDS gpio init /
void leds_gpio_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
LEDR_GPIO_RCC_ENABLE();
LEDG_GPIO_RCC_ENABLE();
LEDB_GPIO_RCC_ENABLE();
HAL_GPIO_WritePin(LEDR_GPIO_PORT, LEDR_GPIO_PINS, GPIO_PIN_SET);
HAL_GPIO_WritePin(LEDG_GPIO_PORT, LEDG_GPIO_PINS, GPIO_PIN_SET);
HAL_GPIO_WritePin(LEDB_GPIO_PORT, LEDB_GPIO_PINS, GPIO_PIN_SET);
GPIO_InitStruct.Pin = LEDR_GPIO_PINS;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LEDR_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LEDG_GPIO_PINS;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LEDG_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LEDB_GPIO_PINS;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LEDB_GPIO_PORT, &GPIO_InitStruct);
}
/ LEDR power control /
void LEDR_power_ctrl(unsigned int bon)
{
if (bon == 0x01) / LEDR ON /
{
HAL_GPIO_WritePin(LEDR_GPIO_PORT, LEDR_GPIO_PINS, GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(LEDR_GPIO_PORT, LEDR_GPIO_PINS, GPIO_PIN_SET);
}
}
/ LEDG power control /
void LEDG_power_ctrl(unsigned int bon)
{
if (bon == 0x01) / LEDG ON /
{
HAL_GPIO_WritePin(LEDG_GPIO_PORT, LEDG_GPIO_PINS, GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(LEDG_GPIO_PORT, LEDG_GPIO_PINS, GPIO_PIN_SET);
}
}
/ LEDB power control /
void LEDB_power_ctrl(unsigned int bon)
{
if (bon == 0x01)
{
HAL_GPIO_WritePin(LEDB_GPIO_PORT, LEDB_GPIO_PINS, GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(LEDB_GPIO_PORT, LEDB_GPIO_PINS, GPIO_PIN_SET);
}
}
- led.h
```c
#ifndef __LED_H__
#define __LED_H__
#include "stm32l4xx_hal.h"
#define LEDR_GPIO_RCC_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE()
#define LEDR_GPIO_PORT GPIOE
#define LEDR_GPIO_PINS GPIO_PIN_7
#define LEDG_GPIO_RCC_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE()
#define LEDG_GPIO_PORT GPIOE
#define LEDG_GPIO_PINS GPIO_PIN_8
#define LEDB_GPIO_RCC_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE()
#define LEDB_GPIO_PORT GPIOE
#define LEDB_GPIO_PINS GPIO_PIN_9
void leds_gpio_init(void);
void LEDG_power_ctrl(unsigned int bon);
void LEDR_power_ctrl(unsigned int bon);
void LEDB_power_ctrl(unsigned int bon);
#endif
-
修改:
usbd_custom_hid_if.c
中的: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) { UNUSED(event_idx); UNUSED(state); USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)hUsbDeviceFS.pClassData; uint32_t usb_recv_len = USBD_GetRxCount(&hUsbDeviceFS,CUSTOM_HID_EPIN_ADDR); if (hhid->Report_buf[0] == 0x61) { LEDR_power_ctrl(1); } else { LEDR_power_ctrl(0); } if (hhid->Report_buf[1] == 0x61) { LEDG_power_ctrl(1); } else { LEDG_power_ctrl(0); } if (hhid->Report_buf[2] == 0x61) { LEDB_power_ctrl(1); } else { LEDB_power_ctrl(0); } for (uint32_t i = 0; i < usb_recv_len; i++) { usb_recv_buf[i] = hhid->Report_buf[i]; } /* Start next USB packet transfer once data processing is completed */ USBD_CUSTOM_HID_ReceivePacket(&hUsbDeviceFS); return (USBD_OK); }
- 在
usbd_customhid.h
,找到USBD_CUSTOM_HID_HandleTypeDef
这个结构体,接收的报告,会存在这个结构体的Report_buf
中 - 也就是USB HID 接收数据后,执行USB 的中断函数:
OTG_FS_IRQHandler
,STM32的USB HAL库与USB协议栈,会处理并接收数据,最后会调用CUSTOM_HID_OutEvent_FS
这个函数,用户可以在CUSTOM_HID_OutEvent_FS
这个函数取出报告:Report_buf
typedef struct
{
uint8_t Report_buf[USBD_CUSTOMHID_OUTREPORT_BUF_SIZE];
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
uint32_t IsReportAvailable;
CUSTOM_HID_StateTypeDef state;
} USBD_CUSTOM_HID_HandleTypeDef;
测试验证
- 通过软件调试,发现USB主机发过来的报告数据,正确的接收到了。
- 开发板的三个LED,可以正确的控制亮灭了
小结
- 使用32个字节控制三个LED?不是,这里只是用于验证USB HID通信
- 如何把采样的数据,如ADC、按键等数据上报给【主机】?接下来继续