STM32 USB 开发(一)HID Slave 通信

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

学习STM32中的USB通信的时候,面对USB中数据帧结构、设备描述符/配置描述符/接口描述符/端点描述符等等的概念,入门即放弃。因此抛开所有,先让开发板的小灯闪起来,一点一点调试、一点一点熟悉、一点一点深入,一点一点理解。LET’S DO。先来玩HID


一、开发板USB硬件

翻到了一块吃灰的STM32F407ZGT6的板子和SCH原理图。
usb Low-Speed -->1.5Mbps(192kB/s)
usb Full-Speed -->12Mbps(1.5MB/s)
支持Full-Speed

二、STM32CubeMX 设置

1.设置小灯灯和串口

DMA 串口传输

2.开启USB

其余参数保持默认

3.时钟设置

导出工程,用KEIL 打开

三、KEIL中的代码

1.设置串口,测试

在main.c 中添加

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define debug(...) {\
	int len=0;\
	len=snprintf(debug_buf , 128, __VA_ARGS__);\
	if(len>0)\
	{\
		HAL_UART_Transmit_DMA(&huart1, (uint8_t *)debug_buf, len );\
	}\
}
/* USER CODE END PD */

/* USER CODE BEGIN PV */
char debug_buf[128];
/* USER CODE END PV */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      debug("Enter main while loop!\r\n");
      HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
      HAL_Delay(500);
      HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
      HAL_Delay(500);
  }
  /* USER CODE END 3 */

记得选中,不然可能发现串口无信息输出。

2.设置USB,测试

报文描述符 usbd_custom_hid_if.c

从别人那里照抄

/** 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 */    
    0x05, 0x8c, // USAGE_PAGE (ST Page) /
    0x09, 0x01, // USAGE (Demo Kit) /
    0xa1, 0x01, // COLLECTION (Application) /
    /* 6 */
    // The Input report
    0x09,0x03, // USAGE ID - Vendor defined
    0x15,0x00, // LOGICAL_MINIMUM (0)
    0x26,0x00, 0xFF, // LOGICAL_MAXIMUM (255)
    0x75,0x08, // REPORT_SIZE (8)
    0x95,CUSTOM_HID_EPIN_SIZE, //0x95,0x16, REPORT_COUNT (20)
    0x81,0x02, // INPUT (Data,Var,Abs)
    //19
    // The Output report
    0x09,0x04, // USAGE ID - Vendor defined
    0x15,0x00, // LOGICAL_MINIMUM (0)
    0x26,0x00,0xFF, // LOGICAL_MAXIMUM (255)
    0x75,0x08, // REPORT_SIZE (8)
    0x95,CUSTOM_HID_EPOUT_SIZE, //0x95,0x16, REPORT_COUNT (20)
    0x91,0x02, // OUTPUT (Data,Var,Abs)
    //32
  /* USER CODE END 0 */
  0xC0    /*     END_COLLECTION	             */
};

发送数据长度 报文长度 usbd_conf.h

/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines
  * @brief Defines for configuration of the Usb device.
  * @{
  */

/*---------- -----------*/
#define USBD_MAX_NUM_INTERFACES     1U
/*---------- -----------*/
#define USBD_MAX_NUM_CONFIGURATION     1U
/*---------- -----------*/
#define USBD_MAX_STR_DESC_SIZ     512U
/*---------- -----------*/
#define USBD_DEBUG_LEVEL     0U
/*---------- -----------*/
#define USBD_LPM_ENABLED     0U
/*---------- -----------*/
#define USBD_SELF_POWERED     1U
/*---------- -----------*/
#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE     64U
/*---------- -----------*/
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE     33U
/*---------- -----------*/
#define CUSTOM_HID_FS_BINTERVAL     0x1U

/****************************************/

收发数据长度 时间间隔 usbd_customhid.h

/** @defgroup USBD_CUSTOM_HID_Exported_Defines
  * @{
  */
#ifndef CUSTOM_HID_EPIN_ADDR
#define CUSTOM_HID_EPIN_ADDR                         0x81U
#endif /* CUSTOM_HID_EPIN_ADDR */

#ifndef CUSTOM_HID_EPIN_SIZE
#define CUSTOM_HID_EPIN_SIZE                         0x40U
#endif /* CUSTOM_HID_EPIN_SIZE */

#ifndef CUSTOM_HID_EPOUT_ADDR
#define CUSTOM_HID_EPOUT_ADDR                        0x01U
#endif /* CUSTOM_HID_EPOUT_ADDR */

#ifndef CUSTOM_HID_EPOUT_SIZE
#define CUSTOM_HID_EPOUT_SIZE                        0x40U
#endif /* CUSTOM_HID_EPOUT_SIZE*/

#define USB_CUSTOM_HID_CONFIG_DESC_SIZ               41U
#define USB_CUSTOM_HID_DESC_SIZ                      9U

#ifndef CUSTOM_HID_HS_BINTERVAL
#define CUSTOM_HID_HS_BINTERVAL                      0x05U
#endif /* CUSTOM_HID_HS_BINTERVAL */

#ifndef CUSTOM_HID_FS_BINTERVAL
#define CUSTOM_HID_FS_BINTERVAL                      0x05U
#endif /* CUSTOM_HID_FS_BINTERVAL */

#ifndef USBD_CUSTOMHID_OUTREPORT_BUF_SIZE
#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE            0x02U
#endif /* USBD_CUSTOMHID_OUTREPORT_BUF_SIZE */

#ifndef USBD_CUSTOM_HID_REPORT_DESC_SIZE
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE             163U
#endif /* USBD_CUSTOM_HID_REPORT_DESC_SIZE */

#define CUSTOM_HID_DESCRIPTOR_TYPE                   0x21U
#define CUSTOM_HID_REPORT_DESC                       0x22U

#define CUSTOM_HID_REQ_SET_PROTOCOL                  0x0BU
#define CUSTOM_HID_REQ_GET_PROTOCOL                  0x03U

#define CUSTOM_HID_REQ_SET_IDLE                      0x0AU
#define CUSTOM_HID_REQ_GET_IDLE                      0x02U

#define CUSTOM_HID_REQ_SET_REPORT                    0x09U
#define CUSTOM_HID_REQ_GET_REPORT                    0x01U

通信关键函数:

usb hid 数据发送函数:usbd_customhid.c 中
	uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len)
usb hid 数据接收回调函数:usbd_custom_hid_it.c中
	static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)

拷贝代码

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
extern unsigned char USB_Recive_Buffer[64];
extern unsigned char USB_Received_Count;
/* USER CODE END PV */

...

/**
  * @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 */
//  UNUSED(event_idx);
//  UNUSED(state);
    
    int i;
    /*查看接收数据长度*/
    USB_Received_Count = USBD_GetRxCount( &hUsbDeviceFS,CUSTOM_HID_EPOUT_ADDR );  //第一参数是USB句柄,第二个参数的是接收的末端地址;要获取发送的数据长度的话就把第二个参数改为发送末端地址即可
    
    USBD_CUSTOM_HID_HandleTypeDef   *hhid; //定义一个指向USBD_CUSTOM_HID_HandleTypeDef结构体的指针
    hhid = (USBD_CUSTOM_HID_HandleTypeDef*)hUsbDeviceFS.pClassData;//得到USB接收数据的储存地址
    
    for(i=0;i<USB_Received_Count;i++) 
    {
        USB_Recive_Buffer[i]=hhid->Report_buf[i];  //把接收到的数据送到自定义的缓存区保存(Report_buf[i]为USB的接收缓存区)
    } 
    
/* Start next USB packet transfer once data processing is completed */
  if (USBD_CUSTOM_HID_ReceivePacket(&hUsbDeviceFS) != (uint8_t)USBD_OK)
  {
    return -1;
  }
  return (USBD_OK);
  /* USER CODE END 6 */
}

main.c

添加如下代码

extern USBD_HandleTypeDef hUsbDeviceFS; //外部声明USB的句柄
/* USER CODE END Includes */
...
/* USER CODE BEGIN PV */
unsigned char USB_Recive_Buffer[64] = {0}; //USB接收缓存
unsigned char USB_Received_Count = 0;//USB接收数据计数
/* USER CODE END PV */
...
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    HAL_Delay(1000);
	debug("Enter main while loop!\r\n");
	USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, USB_Recive_Buffer, 64);
    HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
    HAL_Delay(500);
    HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
    HAL_Delay(500);
	HAL_UART_Transmit_DMA(&huart1, (uint8_t *)USB_Recive_Buffer, 64);
	debug("\r\n");
	HAL_Delay(1000);
	debug("USB_Received_Count=== %d\r\n",USB_Received_Count);
	}
  /* USER CODE END 3 */

四、测试

如果和图中的一样,恭喜你,和我的水平一样了。✊ ✊ ✊ ✊ ✊ ✊ ✊ ✊

总结

慢慢来,尖刺就是生梨。

  • 2
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值