单片机 :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、接鼠标



