单片机USB 鼠标键盘实验

单片机 :STM32F407

开发板:DMF407电机开发板

平台:keil V5.31

HSE 为8MHZ

HSI为16MHZ

一、初始化

复制代码
USBH_Init(&g_hUSBHost, USBH_UserProcess, 1);

USBH_HandleTypeDef g_hUSBHost;    /* USB Host处理结构体 */

/* USB Host handle structure */
typedef struct _USBH_HandleTypeDef
{
  __IO HOST_StateTypeDef     gState;       /*  Host State Machine Value */
  ENUM_StateTypeDef     EnumState;    /* Enumeration state Machine */
  CMD_StateTypeDef      RequestState;
  USBH_CtrlTypeDef      Control;
  USBH_DeviceTypeDef    device;
  USBH_ClassTypeDef    *pClass[USBH_MAX_NUM_SUPPORTED_CLASS];
  USBH_ClassTypeDef    *pActiveClass;
  uint32_t              ClassNumber;
  uint32_t              Pipes[16];
  __IO uint32_t         Timer;
  uint32_t              Timeout;
  uint8_t               id;
  void                 *pData;
  void (* pUser)(struct _USBH_HandleTypeDef *pHandle, uint8_t id);

#if (USBH_USE_OS == 1U)
#if osCMSIS < 0x20000
  osMessageQId          os_event;
  osThreadId            thread;
#else
  osMessageQueueId_t    os_event;
  osThreadId_t          thread;
#endif
  uint32_t              os_msg;
#endif

} USBH_HandleTypeDef;

void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id)
{
    uint8_t dev_type = 0XFF;    /* 设备类型,1,键盘;2,鼠标;其他,不支持的设备 */

    switch (id)
    {
        case HOST_USER_SELECT_CONFIGURATION:
            break;

        case HOST_USER_DISCONNECTION:
            usbh_msg_show(0);   /* 显示已经断开连接,准备重新连接 */
            App_State = APPLICATION_DISCONNECT;
            break;

        case HOST_USER_CLASS_ACTIVE:
            App_State = APPLICATION_READY;
            dev_type = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol;

            if (dev_type == HID_KEYBRD_BOOT_CODE)       /* 键盘设备 */
            {
                g_usb_first_plugin_flag = 1;    /* 标记第一次插入 */
                usbh_msg_show(1);   /* 显示键盘界面 */
            }
            else if (dev_type == HID_MOUSE_BOOT_CODE)   /* 鼠标设备 */
            {
                g_usb_first_plugin_flag = 1;    /* 标记第一次插入 */
                usbh_msg_show(2);   /* 显示鼠标界面 */
            }
            else
            {
                usbh_msg_show(3);   /* 显示不支持 */
            }
            
            break;

        case HOST_USER_CONNECTION:
            App_State = APPLICATION_START;
            break;

        default:
            break;
    }
}

USBH_StatusTypeDef  USBH_Init(USBH_HandleTypeDef *phost,
                              void (*pUsrFunc)(USBH_HandleTypeDef *phost,
                              uint8_t id), uint8_t id)
{
  /* Check whether the USB Host handle is valid */
  if (phost == NULL)
  {
    USBH_ErrLog("Invalid Host handle");
    return USBH_FAIL;
  }

  /* Set DRiver ID */
  phost->id = id;

  /* Unlink class*/
  phost->pActiveClass = NULL;
  phost->ClassNumber = 0U;

  /* Restore default states and prepare EP0 */
  DeInitStateMachine(phost);

  /* Restore default Device connection states */
  phost->device.PortEnabled = 0U;
  phost->device.is_connected = 0U;
  phost->device.is_disconnected = 0U;
  phost->device.is_ReEnumerated = 0U;

  /* Assign User process */
  if (pUsrFunc != NULL)
  {
    phost->pUser = pUsrFunc;
  }

#if (USBH_USE_OS == 1U)
#if (osCMSIS < 0x20000U)

  /* Create USB Host Queue */
  osMessageQDef(USBH_Queue, MSGQUEUE_OBJECTS, uint16_t);
  phost->os_event = osMessageCreate(osMessageQ(USBH_Queue), NULL);

  /* Create USB Host Task */
#if defined (USBH_PROCESS_STACK_SIZE)
  osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0U, USBH_PROCESS_STACK_SIZE);
#else
  osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0U, 8U * configMINIMAL_STACK_SIZE);
#endif /* defined (USBH_PROCESS_STACK_SIZE) */

  phost->thread = osThreadCreate(osThread(USBH_Thread), phost);

#else

  /* Create USB Host Queue */
  phost->os_event = osMessageQueueNew(MSGQUEUE_OBJECTS, sizeof(uint32_t), NULL);

  /* Create USB Host Task */
  USBH_Thread_Atrr.name = "USBH_Queue";

#if defined (USBH_PROCESS_STACK_SIZE)
  USBH_Thread_Atrr.stack_size = USBH_PROCESS_STACK_SIZE;
#else
  USBH_Thread_Atrr.stack_size = (8U * configMINIMAL_STACK_SIZE);
#endif /* defined (USBH_PROCESS_STACK_SIZE) */

  USBH_Thread_Atrr.priority = USBH_PROCESS_PRIO;
  phost->thread = osThreadNew(USBH_Process_OS, phost, &USBH_Thread_Atrr);

#endif /* (osCMSIS < 0x20000U) */
#endif /* (USBH_USE_OS == 1U) */

  /* Initialize low level driver */
  USBH_LL_Init(phost);

  return USBH_OK;
}

USBH_StatusTypeDef USBH_LL_Init(USBH_HandleTypeDef *phost)
{
    /* Init USB_IP */
    if (phost->id == HOST_FS)
    {

        /* Link the driver to the stack. */
        g_hhcd_USB_OTG_FS.Instance = USB_OTG_FS;                /* 使用USB_OTG */
        g_hhcd_USB_OTG_FS.Init.Host_channels = 11;              /* 主机通道数为11个 */
        g_hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL;          /* USB全速 12M */
        g_hhcd_USB_OTG_FS.Init.dma_enable = DISABLE;            /* 不使用DMA */
        g_hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED;   /* 使能内部PHY */
        g_hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE;            /* 禁止SOF中断 */
        g_hhcd_USB_OTG_FS.Init.vbus_sensing_enable = 0;         /* 不使能VBUS检测 */
        g_hhcd_USB_OTG_FS.Init.lpm_enable = 0;                  /* 使能连接电源管理 */
        g_hhcd_USB_OTG_FS.Init.low_power_enable = 0;            /* 不使能低功耗模式 */

        g_hhcd_USB_OTG_FS.pData = phost;
        phost->pData = &g_hhcd_USB_OTG_FS;
        
        if (HAL_HCD_Init(&g_hhcd_USB_OTG_FS) != HAL_OK)
        {
            printf("USB Init ERROR \r\n");
        }
        else {
            printf("USB Init OK \r\n");
        }
        USBH_LL_SetTimer(phost, HAL_HCD_GetCurrentFrame(&g_hhcd_USB_OTG_FS));
    }

    return USBH_OK;
}

HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
{
  USB_OTG_GlobalTypeDef *USBx;

  /* Check the HCD handle allocation */
  if (hhcd == NULL)
  {
    return HAL_ERROR;
  }

  /* Check the parameters */
  assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));

  USBx = hhcd->Instance;

  if (hhcd->State == HAL_HCD_STATE_RESET)
  {
    /* Allocate lock resource and initialize it */
    hhcd->Lock = HAL_UNLOCKED;

#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
    hhcd->SOFCallback = HAL_HCD_SOF_Callback;
    hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
    hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
    hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
    hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
    hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;

    if (hhcd->MspInitCallback == NULL)
    {
      hhcd->MspInitCallback = HAL_HCD_MspInit;
    }

    /* Init the low level hardware */
    hhcd->MspInitCallback(hhcd);
#else
    /* Init the low level hardware : GPIO, CLOCK, NVIC... */
    HAL_HCD_MspInit(hhcd);
#endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
  }

  hhcd->State = HAL_HCD_STATE_BUSY;

  /* Disable DMA mode for FS instance */
  if ((USBx->CID & (0x1U << 8)) == 0U)
  {
    hhcd->Init.dma_enable = 0U;
  }

  /* Disable the Interrupts */
  __HAL_HCD_DISABLE(hhcd);

  /* Init the Core (common init.) */
  (void)USB_CoreInit(hhcd->Instance, hhcd->Init);

  /* Force Host Mode*/
  (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE);

  /* Init Host */
  (void)USB_HostInit(hhcd->Instance, hhcd->Init);

  hhcd->State = HAL_HCD_STATE_READY;

  return HAL_OK;
}

void HAL_HCD_MspInit(HCD_HandleTypeDef *hcdHandle)
{
    GPIO_InitTypeDef gpio_init_struct= { 0 };

    if (hcdHandle->Instance == USB_OTG_FS)
    {
        __HAL_RCC_GPIOA_CLK_ENABLE();                           /* 使能GPIOA时钟 */

        gpio_init_struct.Pin = GPIO_PIN_11 | GPIO_PIN_12;
        gpio_init_struct.Mode = GPIO_MODE_AF_PP;                /* 复用 */
        gpio_init_struct.Pull = GPIO_NOPULL;                    /* 浮空 */
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;     /* 高速 */
        gpio_init_struct.Alternate = GPIO_AF10_OTG_FS;          /* 复用为OTG_FS */
        HAL_GPIO_Init(GPIOA, &gpio_init_struct);                /* 初始化PA11和PA12引脚 */

        __HAL_RCC_USB_OTG_FS_CLK_ENABLE();                      /* 使能OTG FS时钟 */

        HAL_NVIC_SetPriority(OTG_FS_IRQn, 1, 0);
        HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
    }
}

二、注册

复制代码
USBH_RegisterClass(&g_hUSBHost, USBH_HID_CLASS);

#define USBH_HID_CLASS    &HID_Class

typedef struct
{
  const char          *Name;
  uint8_t              ClassCode;
  USBH_StatusTypeDef(*Init)(struct _USBH_HandleTypeDef *phost);
  USBH_StatusTypeDef(*DeInit)(struct _USBH_HandleTypeDef *phost);
  USBH_StatusTypeDef(*Requests)(struct _USBH_HandleTypeDef *phost);
  USBH_StatusTypeDef(*BgndProcess)(struct _USBH_HandleTypeDef *phost);
  USBH_StatusTypeDef(*SOFProcess)(struct _USBH_HandleTypeDef *phost);
  void                *pData;
} USBH_ClassTypeDef;

USBH_StatusTypeDef USBH_RegisterClass(USBH_HandleTypeDef *phost, USBH_ClassTypeDef *pclass)
{
  USBH_StatusTypeDef status = USBH_OK;

  if (pclass != NULL)
  {
    if (phost->ClassNumber < USBH_MAX_NUM_SUPPORTED_CLASS)
    {
      /* link the class to the USB Host handle */
      phost->pClass[phost->ClassNumber++] = pclass;
      status = USBH_OK;
    }
    else
    {
      USBH_ErrLog("Max Class Number reached");
      status = USBH_FAIL;
    }
  }
  else
  {
    USBH_ErrLog("Invalid Class handle");
    status = USBH_FAIL;
  }

  return status;
}

三、启动

复制代码
USBH_Start(&g_hUSBHost);

USBH_StatusTypeDef  USBH_Start(USBH_HandleTypeDef *phost)
{
  /* Start the low level driver  */
  USBH_LL_Start(phost);

  /* Activate VBUS on the port */
  USBH_LL_DriverVBUS(phost, TRUE);

  return USBH_OK;
}

USBH_StatusTypeDef USBH_LL_Start(USBH_HandleTypeDef *phost)
{
    HAL_StatusTypeDef hal_status = HAL_OK;
    USBH_StatusTypeDef usb_status = USBH_OK;

    hal_status = HAL_HCD_Start(phost->pData);

    usb_status = USBH_Get_USB_Status(hal_status);

    return usb_status;
}

USBH_StatusTypeDef USBH_LL_DriverVBUS(USBH_HandleTypeDef *phost, uint8_t state)
{
    if (phost->id == HOST_FS)
    {
        if (state == 0)
        {
            
        }
        else
        {
            
        }
    }

    USBH_Delay(200);
    return USBH_OK;
}

HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
{
  __HAL_LOCK(hhcd);
  __HAL_HCD_ENABLE(hhcd);
  (void)USB_DriveVbus(hhcd->Instance, 1U);
  __HAL_UNLOCK(hhcd);

  return HAL_OK;
}

USBH_StatusTypeDef USBH_Get_USB_Status(HAL_StatusTypeDef hal_status)
{
    USBH_StatusTypeDef usb_status = USBH_OK;

    switch (hal_status)
    {
        case HAL_OK :
            usb_status = USBH_OK;
            break;

        case HAL_ERROR :
            usb_status = USBH_FAIL;
            break;

        case HAL_BUSY :
            usb_status = USBH_BUSY;
            break;

        case HAL_TIMEOUT :
            usb_status = USBH_FAIL;
            break;

        default :
            usb_status = USBH_FAIL;
            break;
    }

    return usb_status;
}

四、处理

复制代码
    while (1)
    {
        USBH_Process(&g_hUSBHost);
        usb_demo(&g_hUSBHost);
        if(usbh_check_enume_dead(&g_hUSBHost))    /* 检测USB HOST 枚举是否死机了?死机了,则重新初始化 */
        {
            printf("Error! USB HID reconnect!\r\n");
            usbh_hid_reconnect();       /* 重连 */
        }
    }

USBH_StatusTypeDef  USBH_Process(USBH_HandleTypeDef *phost)
{
  __IO USBH_StatusTypeDef status = USBH_FAIL;
  uint8_t idx = 0U;

  /* check for Host pending port disconnect event */
  if (phost->device.is_disconnected == 1U)
  {
    phost->gState = HOST_DEV_DISCONNECTED;
  }

  switch (phost->gState)
  {
    case HOST_IDLE :

      if (phost->device.is_connected)
      {
        USBH_UsrLog("USB Device Connected");

        /* Wait for 200 ms after connection */
        phost->gState = HOST_DEV_WAIT_FOR_ATTACHMENT;
        USBH_Delay(200U);
        USBH_LL_ResetPort(phost);

        /* Make sure to start with Default address */
        phost->device.address = USBH_ADDRESS_DEFAULT;
        phost->Timeout = 0U;

#if (USBH_USE_OS == 1U)
        phost->os_msg = (uint32_t)USBH_PORT_EVENT;
#if (osCMSIS < 0x20000U)
        (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
#else
        (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
#endif
#endif
      }
      break;

    case HOST_DEV_WAIT_FOR_ATTACHMENT: /* Wait for Port Enabled */

      if (phost->device.PortEnabled == 1U)
      {
        USBH_UsrLog("USB Device Reset Completed");
        phost->device.RstCnt = 0U;
        phost->gState = HOST_DEV_ATTACHED;
      }
      else
      {
        if (phost->Timeout > USBH_DEV_RESET_TIMEOUT)
        {
          phost->device.RstCnt++;
          if (phost->device.RstCnt > 3U)
          {
            /* Buggy Device can't complete reset */
            USBH_UsrLog("USB Reset Failed, Please unplug the Device.");
            phost->gState = HOST_ABORT_STATE;
          }
          else
          {
            phost->gState = HOST_IDLE;
          }
        }
        else
        {
          phost->Timeout += 10U;
          USBH_Delay(10U);
        }
      }
#if (USBH_USE_OS == 1U)
      phost->os_msg = (uint32_t)USBH_PORT_EVENT;
#if (osCMSIS < 0x20000U)
      (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
#else
      (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
#endif
#endif
      break;

    case HOST_DEV_ATTACHED :

      if (phost->pUser != NULL)
      {
        phost->pUser(phost, HOST_USER_CONNECTION);
      }

      /* Wait for 100 ms after Reset */
      USBH_Delay(100U);

      phost->device.speed = USBH_LL_GetSpeed(phost);

      phost->gState = HOST_ENUMERATION;

      phost->Control.pipe_out = USBH_AllocPipe(phost, 0x00U);
      phost->Control.pipe_in  = USBH_AllocPipe(phost, 0x80U);

      /* Open Control pipes */
      USBH_OpenPipe(phost, phost->Control.pipe_in, 0x80U,
                    phost->device.address, phost->device.speed,
                    USBH_EP_CONTROL, (uint16_t)phost->Control.pipe_size);

      /* Open Control pipes */
      USBH_OpenPipe(phost, phost->Control.pipe_out, 0x00U,
                    phost->device.address, phost->device.speed,
                    USBH_EP_CONTROL, (uint16_t)phost->Control.pipe_size);

#if (USBH_USE_OS == 1U)
      phost->os_msg = (uint32_t)USBH_PORT_EVENT;
#if (osCMSIS < 0x20000U)
      (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
#else
      (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
#endif
#endif
      break;

    case HOST_ENUMERATION:
      /* Check for enumeration status */
      status = USBH_HandleEnum(phost);
      if (status == USBH_OK)
      {
        /* The function shall return USBH_OK when full enumeration is complete */
        USBH_UsrLog("Enumeration done.");

        phost->device.current_interface = 0U;

        if (phost->device.DevDesc.bNumConfigurations == 1U)
        {
          USBH_UsrLog("This device has only 1 configuration.");
          phost->gState = HOST_SET_CONFIGURATION;
        }
        else
        {
          phost->gState = HOST_INPUT;
        }
#if (USBH_USE_OS == 1U)
        phost->os_msg = (uint32_t)USBH_STATE_CHANGED_EVENT;
#if (osCMSIS < 0x20000U)
        (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
#else
        (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
#endif
#endif
      }
      break;

    case HOST_INPUT:
    {
      /* user callback for end of device basic enumeration */
      if (phost->pUser != NULL)
      {
        phost->pUser(phost, HOST_USER_SELECT_CONFIGURATION);
        phost->gState = HOST_SET_CONFIGURATION;

#if (USBH_USE_OS == 1U)
        phost->os_msg = (uint32_t)USBH_STATE_CHANGED_EVENT;
#if (osCMSIS < 0x20000U)
        (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
#else
        (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
#endif
#endif
      }
    }
    break;

    case HOST_SET_CONFIGURATION:
      /* set configuration */
      if (USBH_SetCfg(phost, (uint16_t)phost->device.CfgDesc.bConfigurationValue) == USBH_OK)
      {
        phost->gState = HOST_SET_WAKEUP_FEATURE;
        USBH_UsrLog("Default configuration set.");
      }

#if (USBH_USE_OS == 1U)
      phost->os_msg = (uint32_t)USBH_PORT_EVENT;
#if (osCMSIS < 0x20000U)
      (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
#else
      (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
#endif
#endif
      break;

    case  HOST_SET_WAKEUP_FEATURE:

      if ((phost->device.CfgDesc.bmAttributes) & (1U << 5))
      {
        if (USBH_SetFeature(phost, FEATURE_SELECTOR_REMOTEWAKEUP) == USBH_OK)
        {
          USBH_UsrLog("Device remote wakeup enabled");
          phost->gState = HOST_CHECK_CLASS;
        }
      }
      else
      {
        phost->gState = HOST_CHECK_CLASS;
      }

#if (USBH_USE_OS == 1U)
      phost->os_msg = (uint32_t)USBH_PORT_EVENT;
#if (osCMSIS < 0x20000U)
      (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
#else
      (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
#endif
#endif
      break;

    case HOST_CHECK_CLASS:

      if (phost->ClassNumber == 0U)
      {
        USBH_UsrLog("No Class has been registered.");
      }
      else
      {
        phost->pActiveClass = NULL;

        for (idx = 0U; idx < USBH_MAX_NUM_SUPPORTED_CLASS; idx++)
        {
          if (phost->pClass[idx]->ClassCode == phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass)
          {
            phost->pActiveClass = phost->pClass[idx];
            break;
          }
        }

        if (phost->pActiveClass != NULL)
        {
          if (phost->pActiveClass->Init(phost) == USBH_OK)
          {
            phost->gState = HOST_CLASS_REQUEST;
            USBH_UsrLog("%s class started.", phost->pActiveClass->Name);

            /* Inform user that a class has been activated */
            phost->pUser(phost, HOST_USER_CLASS_SELECTED);
          }
          else
          {
            phost->gState = HOST_ABORT_STATE;
            USBH_UsrLog("Device not supporting %s class.", phost->pActiveClass->Name);
          }
        }
        else
        {
          phost->gState = HOST_ABORT_STATE;
          USBH_UsrLog("No registered class for this device.");
        }
      }

#if (USBH_USE_OS == 1U)
      phost->os_msg = (uint32_t)USBH_STATE_CHANGED_EVENT;
#if (osCMSIS < 0x20000U)
      (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
#else
      (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
#endif
#endif
      break;

    case HOST_CLASS_REQUEST:
      /* process class standard control requests state machine */
      if (phost->pActiveClass != NULL)
      {
        status = phost->pActiveClass->Requests(phost);

        if (status == USBH_OK)
        {
          phost->gState = HOST_CLASS;
        }
        else if (status == USBH_FAIL)
        {
          phost->gState = HOST_ABORT_STATE;
          USBH_ErrLog("Device not responding Please Unplug.");
        }
        else
        {
          /* .. */
        }
      }
      else
      {
        phost->gState = HOST_ABORT_STATE;
        USBH_ErrLog("Invalid Class Driver.");
      }
#if (USBH_USE_OS == 1U)
      phost->os_msg = (uint32_t)USBH_STATE_CHANGED_EVENT;
#if (osCMSIS < 0x20000U)
      (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
#else
      (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
#endif
#endif
      break;

    case HOST_CLASS:
      /* process class state machine */
      if (phost->pActiveClass != NULL)
      {
        phost->pActiveClass->BgndProcess(phost);
      }
      break;

    case HOST_DEV_DISCONNECTED :
      phost->device.is_disconnected = 0U;

      DeInitStateMachine(phost);

      /* Re-Initilaize Host for new Enumeration */
      if (phost->pActiveClass != NULL)
      {
        phost->pActiveClass->DeInit(phost);
        phost->pActiveClass = NULL;
      }

      if (phost->pUser != NULL)
      {
        phost->pUser(phost, HOST_USER_DISCONNECTION);
      }
      USBH_UsrLog("USB Device disconnected");

      if (phost->device.is_ReEnumerated == 1U)
      {
        phost->device.is_ReEnumerated = 0U;

        /* Start the host and re-enable Vbus */
        USBH_Start(phost);
      }
      else
      {
        /* Device Disconnection Completed, start USB Driver */
        USBH_LL_Start(phost);
      }

#if (USBH_USE_OS == 1U)
      phost->os_msg = (uint32_t)USBH_PORT_EVENT;
#if (osCMSIS < 0x20000U)
      (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
#else
      (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
#endif
#endif
      break;

    case HOST_ABORT_STATE:
    default :
      break;
  }
  return USBH_OK;
}

void usb_demo(USBH_HandleTypeDef *phost)
{
    char c;
    HID_KEYBD_Info_TypeDef *k_pinfo;
    HID_MOUSE_Info_TypeDef *m_pinfo;

    if (App_State == APPLICATION_READY)
    {
        if (USBH_HID_GetDeviceType(phost) == HID_KEYBOARD)  /* 键盘设备 */
        {
            k_pinfo = USBH_HID_GetKeybdInfo(phost);         /* 获取键盘信息 */

            if (k_pinfo != NULL)
            {
                c = USBH_HID_GetASCIICode(k_pinfo);         /* 转换成ASCII码 */
                keybrd_data_process(c);                     /* 在LCD上显示出键盘字符 */
            }
        }
        else if (USBH_HID_GetDeviceType(phost) == HID_MOUSE)/* 鼠标设备 */
        {
            m_pinfo = USBH_HID_GetMouseInfo(phost);         /* 获取鼠标信息 */

            if (m_pinfo != NULL)
            {
                mouse_data_process(&mouse_info);            /* LCD上显示鼠标信息 */
            }
        }
    }
}

uint8_t usbh_check_enume_dead(USBH_HandleTypeDef *phost)
{
    static uint16_t errcnt = 0;

    /* 这个状态,如果持续存在,则说明USB死机了 */
    if (phost->gState == HOST_ENUMERATION && (phost->EnumState == ENUM_IDLE || phost->EnumState == ENUM_GET_FULL_DEV_DESC))
    {
        errcnt++;

        if (errcnt > 2000)              /* 死机了 */
        {
            errcnt = 0;
            return 1;
        }
    }
    else 
    {
        errcnt = 0;
    }

    return 0;
}

void usbh_hid_reconnect(void)
{
    /* 关闭之前的连接 */
    HID_Class.DeInit(&g_hUSBHost);    /* 复位HID */
    USBH_DeInit(&g_hUSBHost);         /* 复位USB HOST */
    
    /* 重新复位USB */
    RCC->AHB2RSTR |= 1 << 7;        /* USB OTG FS 复位 */
    delay_ms(5);
    RCC->AHB2RSTR &= ~(1 << 7);     /* 复位结束 */

    memset(&g_hUSBHost, 0, sizeof(g_hUSBHost)); /* 清零数据 */
    
    /* 重新连接USB HID设备 */
    USBH_Init(&g_hUSBHost, USBH_UserProcess, 0);
    USBH_RegisterClass(&g_hUSBHost, USBH_HID_CLASS);
    USBH_Start(&g_hUSBHost);
}

测试结果:

1、接键盘

2、接鼠标

相关推荐
大卡片1 小时前
单片机第二次答辩
单片机·嵌入式硬件
广州灵眸科技有限公司10 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) 开发(编译)方式说明
linux·服务器·单片机·嵌入式硬件·电脑
IT_阿水11 小时前
STM32 HAL库输入捕获配置
stm32·单片机·嵌入式硬件
nuoxin11411 小时前
WILX1200HC-5TG144I替代 LCMXO2-1200HC-5TG144I(富利威)
人工智能·嵌入式硬件·fpga开发·电脑·硬件工程·dsp开发
zlinear数据采集卡12 小时前
555触摸延时开关深度解析:从电路原理到智能楼道灯应用
单片机·嵌入式硬件
国科安芯15 小时前
国科安芯推出商业航天级抗辐照全双工 RS485/422 收发器 ASC491S2Y
网络·分布式·单片机·架构·安全性测试
czhaii15 小时前
LCD320240间接接口 RA8835控制器 温度MAX6675显示
单片机·嵌入式硬件·硬件工程
破晓单片机15 小时前
030、STM32项目分享:计时充电桩系统
stm32·单片机·嵌入式硬件
森利威尔电子-16 小时前
森利威尔SL3150H |PIN TO PIN 替换 MRDC88-1 10~150V 输入 0.6A 降压电源芯片
单片机·嵌入式硬件·物联网·集成电路·芯片