STM32 USB Host 同时连接多个设备样例(如鼠标和键盘)

在网上搜了很多都是USB Host单独连接鼠标或键盘的样例, 而当前很多无线鼠标键盘都是并到一个USB口上的, 也就是同一个USB有两个interface. 而官方提供的USB Host库中只会对一个Interface进行处理, 要么键盘要么鼠标, 所以为了能够同时使用键盘和鼠标要对USB Host库进行修改才行.
具体修改如下:
首先使用CubeMX创建了一个带USB HID类功能的工程, 创建步骤很简单网上有很多文档不在这里讨论.
接着进入正题, 修改USB Host库文件.

  1. usbh_def.h
    修改USBH_ClassTypeDef, 使当前Class支持多接口:
/* USB Host Class structure */
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_MAX_NUM_INTERFACES]; /* HID interfaces Handle */uint8_t              InterfaceNum;                   /* interface 数量 */__IO uint8_t         CurrInterface;                   /* 当前interface */
/* ] */
} USBH_ClassTypeDef;

修改HID_HandleTypeDef, 记录interface的协议类型:

/* Structure for HID process */
typedef struct _HID_Process
{uint8_t              OutPipe;uint8_t              InPipe;HID_StateTypeDef     state;uint8_t              OutEp;uint8_t              InEp;HID_CtlStateTypeDef  ctl_state;FIFO_TypeDef         fifo;uint8_t              *pData;uint16_t             length;uint8_t              ep_addr;uint16_t             poll;uint32_t             timer;uint8_t              DataReady;HID_DescTypeDef      HID_Desc;USBH_StatusTypeDef(* Init)(USBH_HandleTypeDef *phost);
/* [ */uint8_t              Protocol;    /* 协议类型: HID_KEYBRD_BOOT_CODE / HID_MOUSE_BOOT_CODE */
/* ] */
} HID_HandleTypeDef;
  1. usbh_hid.c
    修改USBH_HID_InterfaceInit函数, 在初始化的时候判断当前枚举了几个HID接口, 如果有多个接口, 则创建多个HID_HandleTypeDef:
static USBH_StatusTypeDef USBH_HID_InterfaceInit(USBH_HandleTypeDef *phost)
{USBH_StatusTypeDef status = USBH_OK;HID_HandleTypeDef *HID_Handle;uint8_t max_ep;uint8_t num = 0U;/* [ */uint8_t boot = HID_KEYBRD_BOOT_CODE;uint8_t interface_num = 0;uint8_t interface;for (interface_num = 0; interface_num < phost->device.CfgDesc.bNumInterfaces; interface_num++){interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, boot);/* ] */if ((interface == 0xFFU) || (interface >= USBH_MAX_NUM_INTERFACES)) /* No Valid Interface */{USBH_DbgLog("Cannot Find the interface for %s class.", phost->pActiveClass->Name);status = USBH_FAIL;break;}status = USBH_SelectInterface(phost, interface);if (status != USBH_OK){return USBH_FAIL;}/* [ */phost->pActiveClass->pData[interface_num] = (HID_HandleTypeDef *)USBH_malloc(sizeof(HID_HandleTypeDef));phost->pActiveClass->InterfaceNumber++;phost->pActiveClass->CurrInterface = interface_num;HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData[interface_num];/* ] */if (HID_Handle == NULL){USBH_DbgLog("Cannot allocate memory for HID Handle");return USBH_FAIL;}/* Initialize hid handler */USBH_memset(HID_Handle, 0, sizeof(HID_HandleTypeDef));HID_Handle->state = HID_ERROR;/*Decode Bootclass Protocol: Mouse or Keyboard*/HID_Handle->Protocol = phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol;....../* 配置完成 [ */if (boot == HID_KEYBRD_BOOT_CODE)boot = HID_MOUSE_BOOT_CODE;elseboot = HID_KEYBRD_BOOT_CODE;/* ] */}return status;
}

修改USBH_HID_Process, 在POLL空闲时如果10次连续空闲未收到有效数据则切换接口, 使下次执行Process的时候切换到另一个接口:

static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
{USBH_StatusTypeDef status = USBH_OK;HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData[phost->pActiveClass->CurrInterface];uint32_t XferSize;/* [ */uint8_t interface;uint8_t protocol;static __IO uint16_t num = 0;/* ] */switch (HID_Handle->state){...case HID_POLL:if (USBH_LL_GetURBState(phost, HID_Handle->InPipe) == USBH_URB_DONE){XferSize = USBH_LL_GetLastXferSize(phost, HID_Handle->InPipe);if ((HID_Handle->DataReady == 0U) && (XferSize != 0U)){USBH_HID_FifoWrite(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length);HID_Handle->DataReady = 1U;USBH_HID_EventCallback(phost);#if (USBH_USE_OS == 1U)phost->os_msg = (uint32_t)USBH_URB_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/* 如果检测到有效数据, 则清除空闲计数 [ */num = 0;/* ] */}}else{/* 如果空闲计数达到10次, 则切换到其他interface [ */num++;if (num > 10){if (phost->pActiveClass->InterfaceNumber > 1){if (phost->pActiveClass->CurrInterface == 0)phost->pActiveClass->CurrInterface = 1;elsephost->pActiveClass->CurrInterface = 0;protocol = ((HID_HandleTypeDef *)phost->pActiveClass->pData[phost->pActiveClass->CurrInterface])->Protocol;interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, protocol);USBH_SelectInterface(phost, interface);}num = 0;}/* ] *//* IN Endpoint Stalled */if (USBH_LL_GetURBState(phost, HID_Handle->InPipe) == USBH_URB_STALL){/* Issue Clear Feature on interrupt IN endpoint */if (USBH_ClrFeature(phost, HID_Handle->ep_addr) == USBH_OK){/* Change state to issue next IN token */HID_Handle->state = HID_GET_DATA;}}}break;...}
}

另外其他涉及到"phost->pActiveClass->pData"的地方全部改为"phost->pActiveClass->pData[phost->pActiveClass->CurrInterface]", 因为pData已经不再是一个结构体指针而是一个结构体指针数组, 主要涉及的文件包括:
usbh_hid.c, usbh_hid_keybs.c, usbh_hid_mouse.c
3. 修改键盘和鼠标的驱动
最后就是按照键盘鼠标的协议定义相应的回调函数, 因为不同的无线鼠标键盘有不同的协议, 在此不做描述. 主要涉及的文件包括:
usb_host.c, usbh_hid_keybs.c, usbh_hid_mouse.c
做好驱动以后就可以同时使用键盘和鼠标了, 此方法也可适用于USB连接其他多设备场景, 只要USB初始化的时候能够检测到相应的设备.

测试视频:

STM32 USB Host同时连接鼠标和键盘演示视频

转载请注明出处.

STM32 USB Host 同时连接多个设备样例(如鼠标和键盘)--原创相关推荐

  1. 为什么USB最多只能连接127个设备?

    ** 为什么USB最多只能连接127个设备?** 一台USB主机可以同时支持多达128个地址. 作为默认地址,地址0仅在设备枚举期间临时 使用,不能分配给任何设备.因此,一个 USB主机可以同时支持多 ...

  2. Android + kernel USB host 如何判断插入的设备是高速还是低速的设备

    d+      d- 0        0         PC 0        1         错误设备 1        0         非标准充电器 1        1        ...

  3. linux读写usb host,LINUX下USB1.1设备学习小记(3)_host与device

    各位还记得"任何传输都是由host发起的"这句话么~ 在usb设备插入pc中到拔出usb设备,都是由host进行询问的 一个usb鼠标的工作流程可以表达如下: usb鼠标插入pc中 ...

  4. 实现连接池技术的样例

    1. 在tomcat的安装文件夹下conf文件夹下的context.xml文件加入例如以下代码: <Resource name="jdbc/course" auth=&quo ...

  5. STM32 USB高速USB端口加持4G联网

    本文由RT-Thread论坛用户@fhqmcu原创发布:https://club.rt-thread.org/ask/article/8fc0968257c2ca01.html 1.前言 关于STM3 ...

  6. 首创STM32 USB主机驱动4G rndis设备

    1.4G模块使用技术现状与难题 4G模块支持的对外通信接口有串口和USB接口,串口一般使用AT指令的方式,这个在MCU类产品上面使用的很多,USB接口主用于在连接APU应用处理器上面,由LINUX操作 ...

  7. STM32 USB无法连接电脑

    一.说明 在调试 STM32 USB device MSC 功能时,使用官方提供的库和示例项目,电脑可以正确识别设备,也可以正常操作.但是将 USB 部分的代码移植到自己的工程后,发现电脑无法正确识别 ...

  8. Android USB Host开发之manager.getDeviceList()获取不到设备列表

    同样遇到这样的问题,我的Android设备是原道N12C,官方的4.0.3系统,遇到这个问题,后来找了半天找到的,现在汇总一下吧: 1.创建 android.hardware.usb.host.xml ...

  9. STM32之独立版USB(Host)驱动+MSC+Fatfs移植

    源:STM32之独立版USB(Host)驱动+MSC+Fatfs移植 STM32之USB驱动库详解(架构+文件+函数+使用说明+示例程序)

最新文章

  1. LOJ6435 PKUSC2018 星际穿越
  2. php变量定义的位置,php变量一般放在哪个位置
  3. java流处理为什么快_“任何情况下,都不可以堕胎”是道德普遍主义的观点。
  4. JNI中参数的传递与操作
  5. XShell常用快捷键
  6. 当下的互联网时代,“急功近利”不是坏事
  7. JSON-B和Yasson详解
  8. 淡定的写代码,淡定的人生
  9. 12c emcc Algorithm negotiation fail
  10. Calendar中add()和roll()函数的用法
  11. 二分图最大权匹配【KM算法 BFS优化下的真正的O(N3)的KM算法】【KM算法模板】
  12. 开源配置管理中心apollo使用方法
  13. android截图方法,安卓手机的截图方法
  14. 周鸿祎的“花房上市”执念
  15. Ubuntu18.04 配置nvidia 460驱动、cuda10.1和cudnn7.6.5
  16. div的水平排列、垂直排列
  17. 微信自定义分享卡片链接的解决方案(可自定义标题 描述 缩列图)
  18. Going out on a limb:Joint Extraction of Entity Mentions and Relations without Dependency Trees【论文笔记】
  19. 【动手学深度学习PyTorch版】6 权重衰退
  20. lumia flash android,Lumia830吃上棉花糖!WP手机刷安卓7.1详细教程

热门文章

  1. 春招必看一位老学长的真实互联网校招求职心路历程~
  2. 二十、从句_限定性定语从句
  3. WAF检测率及误报测试工具Gotestwaf
  4. Android OkHttp 源码解析 - 拦截器
  5. 2021年前端岗位面试题 “二”(本人亲测)
  6. 用Python海龟画图画哆啦A梦
  7. 王道机组笔记IEEE754
  8. 浩辰3D软件新手入门攻略:草图绘制功能全解析!
  9. 国产浏览器 html5,老外评测国产浏览器 HTML5性能不俗
  10. 考研复试问答(计算机组成原理部分)