基于CUBEMX的HID双向通讯

在STM32中如何自定义HID设备,用cubemx怎么生成代码并配置?

生成USB HID工程

可以看到,勾选usb device的功能后,右侧的芯片引脚已经设置好了,DP和DM两根线就是usb通信的差分线。

再配置USB的软件中间件,选择usb device,Custom Interface Device Class,这个选项生成的就是自定义的HID设备。

然后需要修改三个参数:

CUSTOM_HID_FS_BINTERVAL,这个设置的是HID设备的通信时间间隔,单位为ms,最快可以为1ms间隔;

USBD_CUSTOM_HID_REPORT_DESC_SIZE,设置的是报告描述符的长度,设为34(后面会提到为什么是这个值);

USBD_CUSTOMHID_OUTREPORT_BUF_SIZE,比较好理解,设置的是发送缓冲区的大小,HID一次最多可以发送64个字节,我们设置为最大值。

在另一个选项卡中,我们可以看到下面几个参数:VID、PID,以及设备标识,这里我们都不修改。

其他的配置都不用改,就可以生成工程代码了。

2)代码编写

打开生成的keil工程,可以看到已经生成了usb相关的源文件。

我们一步步添加需要的代码。

首先添加报告描述符,如下图,在usbd_custom_hid_if.c文件中,CUSTOM_HID_ReportDesc_FS定义数组内部添加:

/** 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 */
//  0x00,
	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, 0x08,                    //   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, 0x08,                    // REPORT_COUNT (64)
    0x75, 0x08,                    // REPORT_SIZE (8)
    0x91, 0x02,                    // OUTPUT (Data,Var,Abs)
  /* USER CODE END 0 */
  0xC0    /*     END_COLLECTION	             */
};

描述符定义了usb传输数据的格式。

这里的数组长度USBD_CUSTOM_HID_REPORT_DESC_SIZE就是在cubemx中定义的34,与描述符数组的长度必须一样。

然后,在usbd_customhid.c文件中,找到USBD_CUSTOM_HID_CfgHSDesc数组,修改里面的参数:

标记的四个参数,分别是:接收的长度、延时,发送的长度、延时;这里我们可以跳转到它们的宏定义处修改;长度都修改为0x40;延时可以默认,也可以修改到1,也就是1ms周期,可以加快通信的最快速率。

接着,修改接收函数,如下图,在usbd_custom_hid_if.c文件中,添加语句如下:

这个函数在usb接收到数据时会自动调用,这里我们在函数中,把接收到的数据用strncpy这个函数拷贝到usb_rx_data数组中,然后设置usb_rx_flag标志位。

到主函数中循环查询标志位,查询到则可以处理usb_rx_data中接收到的数据。

需要发送数据时,直接调用HAL库生成的发送函数即可,函数原型如下:

uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef  *pdev,
                                   uint8_t *report,
                                   uint16_t len)
{
  USBD_CUSTOM_HID_HandleTypeDef     *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData;

  if (pdev->dev_state == USBD_STATE_CONFIGURED)
  {
    if (hhid->state == CUSTOM_HID_IDLE)
    {
      hhid->state = CUSTOM_HID_BUSY;
      USBD_LL_Transmit(pdev, CUSTOM_HID_EPIN_ADDR, report, len);
    }
    else
    {
      return USBD_BUSY;
    }
  }
  return USBD_OK;
}

主函数中主要添加的是:初始时将USB端口复位,以及主循环中的接收和发送数据。

USB_IO_rest();这个函数主要是用在初始时把usb接口引脚拉低一下,让计算机知道有新设备插入(以前的文章讲过,也可以参考源代码,很容易理解);

主循环中检测接收标志位,如果收到数据,则把数据更新到usb_tx_data中,每隔1s检测一下;每隔1s把usb_tx_data中的数据发送出去。

看看具体的额效果,端点2接受和发送

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 2
收藏 3
关注 192
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧