故障表现:
使用st官方hal库函数写项目时发现始终无法读取键盘的按键值,使用调试器发现 USBH_HID_GetKeybdInfo(&hUsbHostFS)
函数始终返回NULL;删除后续iic显示函数后可以正常读取hid数据,初步猜测是轮训间隔过长导致无法读取键盘值。
解决方案:
修改usbh_hid.h中宏定义 HID_MIN_POLL
的值为200U即可
思路:
USBH_HID_KeybdDecode
中调用的函数USBH_HID_FifoRead
始终返回0,即usb fifo数据量一直为0,怀疑没有往usb fifo缓冲区写入过数据,于是查找USBH_HID_FifoWrite
函数调用位置,发现这个函数在USBH_HID_Process
函数中switch
语句的case USBH_HID_POLL
分支出现 (幸好只出现一次) 。继续调试发现,程序不会进入该分支,没有调用USBH_HID_FifoWrite
函数。
而前面一个分支case USBH_HID_GET_DATA
后面更新了状态为USBH_HID_POLL
,在第二次调用USBH_HID_Process
函数时应该会执行该分支内容,实际没有执行,说明在其他地方(即中断中)更改了hid的状态,于是搜索HID_Handle->state
查找修改状态的地方,发现在USBH_HID_SOFProcess
函数中有可能把USBH_HID_POLL
修改为USBH_HID_GET_DATA
。
USBH_HID_SOFProcess
函数定义:
static USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost)
{
HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;
if (HID_Handle->state == USBH_HID_POLL)
{
if ((phost->Timer - HID_Handle->timer) >= HID_Handle->poll)
{
HID_Handle->state = USBH_HID_GET_DATA;
#if (USBH_USE_OS == 1U)
USBH_OS_PutMessage(phost, USBH_URB_EVENT, 0U, 0U);
#endif /* (USBH_USE_OS == 1U) */
}
}
return USBH_OK;
}
结合AI搜索了解这个函数是usb sof进程(起始帧进程) (我也不知道是干啥用的23333333) 。函数中的if ((phost->Timer - HID_Handle->timer) >= HID_Handle->poll)
即为判断超时的语句,其中HID_Handle->poll
在前面有赋值:
if (HID_Handle->poll < HID_MIN_POLL)
{
HID_Handle->poll = HID_MIN_POLL;
}
HID_MIN_POLL
为宏定义,定义在usbh_hid.h中,值为10U,应该是超时时长为10ms,将10U改大即可解决,我这里修改为了200U。