STM32F103芯片集成了USB2.0 Full-Speed接口,可以用作与外部设备进行通信,如电脑。基本连接如下:其中,V3P3是USB接口VBUS通过LDO转换为3.3V。

  

STM32CubeMX 复合 usb hid_数据

  因为STM32F103内部没有集成USB2.0 Full-Speed的上拉电阻,因此外接上拉电阻(详细见上篇文章“USB2.0系列—HID设备”),然后将MCU_DM和MCU_DP分别接MCU的DM和DP,即可实现USB2.0Full-speed硬件配置。

  关于STM32F103的Firmware,本文采用了STM32CubeIDE自动产生相应的参考代码,配置信息如下:

  

STM32CubeMX 复合 usb hid_嵌入式硬件_02

  

STM32CubeMX 复合 usb hid_stm32_03

  通过配置上述参数,然后即可生成相应的参考代码。注意:这个生产的参考代码是不完整的,不能直接用的。还需要填写Report Descriptor数据(详细见上篇文章“USB2.0系列—HID设备”)。打开USB_Device-->App-->usbd_custom_hid_if.c文件,找到下面的定义,将其大学内容书写完整。如下图所示:(数一下下面这个数组的Byte数为38,将上面配置中的Report Descriptor数目改为38,OUT Report Bytes设置为64)

__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
  {
  /* USER CODE BEGIN 0 */
  0x05, 0x8c, //0x05:USAGE PAGE
  0x09, 0x00, //0x09:USAGE
  0xA1, 0x00, //0xA1:COLLECTION
  //下面开始数据配置
  0x09, 0x00, //0x09:USAGE
  0xA1, 0x00, //0xA1:COLLECTION
  0x09, 0x00, //0x09:USAGE
  0x15, 0x00, //0x15:LOGICAL MIN 最小数为0x00
  0x26, 0xFF, 0x00, //0x26:LOGICAL MAX 最大数为0XFF
  0x75, 0x08, //0x75:REPORT SIZE;0x08:8位bit
  0x95, 0x40, //0x95:REPORT COUNT;0x40:最大64 bytes传输
  0x91, 0x02, //0x91:OUTPUT;0x02:Var(可变量)
  //上面OUT格式
  0x09, 0x00, //0x09:USAGE
  0x15, 0x00, //0x15:LOGICAL MIN
  0x26, 0xFF, 0x00, //0x26:LOGICAL MAX
  0x75, 0x08, //0x75:REPORT SIZE
  0x95, 0x40, //0x95:REPORT COUNT
  0x81, 0x02, //0x81:INPUT; 0x02:Var(可变量)
  //上面IN格式
  //有两个 COLLECTION,就需要两个END COLLECTION
  0xC0, //END COLLECTION
  /* USER CODE END 0 */
  0xC0 /* END_COLLECTION */
  };

  然后设置USB接收的中断优先级,我这里设置为6,根据不同的需求进行调整。

  

STM32CubeMX 复合 usb hid_stm32_04

  另外,USB的时钟只能设置为48M,因此在设置Clock的时候要尤其注意,见下图所示:

  

STM32CubeMX 复合 usb hid_DM_05

  这样,我们的STM32下位机插入电脑之后,电脑就会认为是HID设备,在电脑上打开USBTreeView.exe。可以看到我们设置的是否正确,如果是以上面的配置设置,那么电脑端应该显示如下:

  

STM32CubeMX 复合 usb hid_单片机_06

  那么,设备可以识别了,那么Firmware中通信要怎么弄呢?调用两个函数即可:

uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef *pdev,uint8_t *report,uint16_t len);
  //上面为STM32向主机发送数据
  static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state);
  //上面为STM32接收到HOST的数据会执行的函数,这个函数需要自己完善,我自己完善的数据如下:
  static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state)
  {
  /* USER CODE BEGIN 6 */
  USBD_CUSTOM_HID_HandleTypeDef *hhid_temp=(USBD_CUSTOM_HID_HandleTypeDef*)hUsbDeviceFS.pClassData; //STM32会将数据存储的位置
  usb_status_t *usb_status_temp=get_usb_status();//自己定义的数组存储位置
  uint8_t temp=0;
  for(;temp<64;temp++)
  {
  usb_status_temp->usb_receive_data.usb_buffer[index]=hhid_temp->Report_buf[index];
  }
  //usb_status_temp->usb_receive_data.usb_buffer[index]将存储接受的数据,用来做你想要做的。
  return (USBD_OK);
  /* USER CODE END 6 */
  }

  另外提醒一下:

  在USB上电初始化之后,最好检查一下USB是否配置完成(即与HOST的初始通信是否建立),然后进行相关的USB操作。hUsbDeviceFS.dev_config!=0并且hUsbDeviceFS.dev_address!=0。只要这两个参数不为0,那么表示USB的设备通信已经建立完成,否则则是有问题的。

  USB HID接口建立完成,那么我们的HOST端(即电脑要怎么弄呢?),下一篇会介绍一下用C#实现简单的上位机软件与STM32进行通信。