故障表现:

使用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。