关于怎么用Cubemx生成的USBHID设备实现读取一体的鼠标键盘设备(改进版) ...

打印 上一主题 下一主题

主题 703|帖子 703|积分 2109

重要近来做了一个要用STM32实现读取鼠标键盘一体的那种USB设备,STM32的界面上要和电脑一样的能通过这个USB接口实现鼠标移动,键盘的按键。然后我就很自然的去参考了正点原子的例程,可是找了一圈,发现正点原子似乎用的库函数,照旧本身实现的,然后看了半天都看晕了,感觉本身实现不了,然后就主攻Cubemx实现的USB设备读取了。
在网上找了一圈,终于让我发现了一个可以用的博主的,而且实现了USB读取鼠标键盘一体的设备。
参考网址如下:
https://blog.csdn.net/weixin_50969532/article/details/134313495
基于STM32-USB中间库的多接口主机开发实战
感觉这个博主实现的非常好了,重要实现方法我都是参考这个博主的,只是基于Cubemx实现的照旧和博主的实现有一点点的收支,我这里重要跟随博主的实现方法,和博主的文章对比着修改下博主的实现方法,并融合一下,并且实现的更好一点。
使用的硬件

根据网上很多的HID实现方法,大多数都是用F103一类的STM32设备,将STM32设置成Device,模拟鼠标键盘和电脑举行通信,相当于就是用STM32做一个鼠标键盘。但是我们要实现的正好是反着来的,我们要用STM32当做是电脑,读取真正的鼠标键盘的数据,然后在STM32上显示鼠标的移动,按键,键盘的按键。下面是我用的重要硬件。
STM32:正点原子的阿波罗F767开发板
鼠标键盘(一体的):不知道是什么杂牌子,反正写着型号T1,2.4G无线充电鼠标,电压4.2V,载波频率:2402Mhz。
第一步相识USB主机和设备

首先第一步,看下博主的博客。根据博主的分析,我们可以知道,主机和设备之间的USB基础知识。
USB:通用串行总线,是由主机发起通信、从机被动接收的主从机通信机制。
管道:主从机通信的通道,可以理解为两个海岸之间船只来往的航线。要想船只走得通,必须开放这条航线;要想举行通信,必须打开对应的管道。(着实生成的代码里细致看也会有,生成的Cubemx代码里叫pipe,还分为进出pipe)
端点:主从机传输的终极对象,可以理解为船只来往的船埠,航线的两头即端点。要想船只来往,必须开放船埠;要想举行通信,必须开放对应的端点。(这个可以理解为Freertos里的队列的进出口,关键Cubemx里也真的是用的队列,队列实现的管道,写入队列和读取队列就是端点)
接口:几个端点的聚集,实现某一详细功能。比如这2个船埠用来运输食品,这就是一个食品接口;另外4个船埠用来运输石油,这是一个石油接口。键鼠一体有两个接口,一个接口是键盘,一个接口是鼠标。(这里就是最重要的,按照博主的分析,接口的数量决定是只有一个鼠标大概一个键盘,照旧两个都有。也就是说,如果一个USB的接口插在电脑上,可以接收很多个无线设备的数据,接口几个,就有几个设备)

这里参考的就是【半旅程序媛】https://blog.csdn.net/weixin_50969532/article/details/134313495这位博主的图片,感谢博主的分析。。。
第二步 用Cubemx生成STM32代码

Cubemx来生成的STM32的代码,重要要设置Cubemx的两个部分,第一个,就是USB_OTG_FS,第二个是USB_HOST。(留意,STM32F1都实现不了HOST,只能是Device,所以买错STM32的小同伴留意了)
然后就是打开Cubemx,选择本身的STM32,我这里用的硬件是F767IGT6,我就选择F767IGT6。
然后就是一般的CUbemx设置,选晶振,设置时钟,设置UART1作为调试接口输出到电脑,Freertos体系设置(是的,我用了体系,没试过不消体系的,但是有体系的话,为啥非要跑裸机呢~)。
好了,设置好了后,就可以开始用Cubemx设置USB设备了,首先是Connectivity里的USB_OTG_FS(我这里有USB_OTG_HS,但是我的设备重要用这个OTG_FS接口)

这里设置好了后,Middleware and Software里就会有一个USB_HOST(有的Cubemx版本可能不在这里,留意找一下,如果找不到,就是你的STM32不支持HOST),然后就是USB_HOST的设置。

User Constants不消,就用默认就可以了,然后就是Platform Settings这个设置要分析一下。
Platform Settings设置分析

这个设置的意思是STM32支持其中一个STM32的引脚来控制USB设备的供电,也就是在硬件上要有类似的设置。如果你的硬件电路板上,硬件工程师做了这么一个设置,可以用一个STM32的引脚来给外部USB供电,这个设置你就是必须要设置的,而且一定要问硬件工程师是设置的哪个引脚,引脚要一致。
但是如果你电路板本身就是USB有供电了,那这个的设置就对你毫无用处,随便设置一个不消的引脚吧,就是为了Cubemx能顺遂生成代码而已。。而且在生成后的代码里,也没啥用处。。
如果你用的板子和我的一样,都是正点原子的阿波罗,那你要细致看下硬件原理图了,正点原子的USB的供电引脚是用一个扩展芯片来实现的,叫pcf8574,这个芯片要用IIC驱动才能让USB供电上,不供电的话就算你怎么改代码都读不到USB的。。别被坑了。。。
回到正题,继承设置Cubemx

Cubemx设置好了这两个以后,USB这方面就完成了。然后就是生成代码。下面我们来看下keil5的代码吧。
Keil5上看下生成的代码,修改代码来实现

Keil5生成的代码我们先看下文件树,我这里重要生成的文件是如许的。


这三个文件夹是个USB设备有关的,后面我们重要也是要修改这几个文件来实现一体化设备的数据读取。
关于Cubemx生成的代码里,本身是可以直接用的,要实现键盘的话,就本身生成好的就可以直接用。
Cubemx的代码可以直接驱动一个USB设备?

是的,Cubemx的代码确实直接生成好的就是可以直接插上USB设备就能用。
先看main。。。。呃。。我用的freertos的体系,看main没啥用,就不看了,重要看下在那里初始化USB设备和怎么用吧。

我这里的这个函数是Cubemx上了freertos体系后,自动生成的一个使命,我直接把初始化放在使命里,然后初始化USB设备,下面的for(;;)里面只用写本身要处理的usb_demo(&hUsbHostFs)就可以了。下面是我的usb_demo。
下面展示一些 内联代码片。
  1. void USB_Demo(USBH_HandleTypeDef * phost)
  2. {
  3.     char c,i;
  4. for(i=0;i<USBH_MAX_NUM_INTERFACES;i++)
  5. {
  6. if(InterfaceIndex[i] != 0xff)
  7. {
  8.     if(USBH_HID_GetDeviceType(&hUSBHost)==HID_KEYBOARD)     //键盘设备
  9.     {
  10.          if(Appli_state==APPLICATION_READY)
  11.          {           //获取键盘信息
  12.             if(k_pinfo!=NULL)
  13.             {
  14.                 c=USBH_HID_GetASCIICode(k_pinfo);           //转换成ASCII码
  15.                 //这里是我自己加的一句,只用输出c就行了
  16.                 printf("%c",c);
  17.                 MYUSR_KEYBRD_ProcessData(c);                //在LCD上显示出键盘字符
  18.                 k_pinfo = NULL;
  19.                 memset(k_pinfo ,0,sizeof(HID_KEYBD_Info_TypeDef ));
  20.             }
  21.          }
  22.     }
  23.     else if (USBH_HID_GetDeviceType(&hUSBHost)==HID_MOUSE)  //鼠标设备
  24.     {
  25.         if(Appli_state==APPLICATION_READY)
  26.         {
  27.            // MOUSE_Demo(&hUSBHost);
  28.             if(m_pinfo!=NULL)
  29.             {
  30.                 MYUSR_MOUSE_ProcessData(&mouse_info);       //LCD上显示鼠标信息
  31.                 m_pinfo = NULL;
  32.                 memset(m_pinfo ,0,sizeof(HID_MOUSE_Info_TypeDef ));
  33.             }
  34.         }
  35.     }else                                                   //无法识别的设备
  36.     {
  37.         //printf("无法识别的设备\r\n");
  38.     }
  39. }
  40. }
  41. }
复制代码
这个代码着实就是楼上博主的demo代码,博主的文章中没有实现的两点是MYUSR_MOUSE_ProcessData(&mouse_info);和 MYUSR_KEYBRD_ProcessData©;
但是这两个函数我们这里可以先不要,因为本身的这个Cubemx生成的代码里,也只能实现键盘的读取,所以,代码运行到了c=USBH_HID_GetASCIICode(k_pinfo);的时候,就可以了,后面只要printf出来c,就是你按下的那个按键。
到这里Cubemx本身的使用就如许子了,实现一个键盘的按键读取,鼠标我还没试过,不过改改也是可以实现的,只是临时没那个时间啦。
下面就是要根据参考的博主的步伐,改下Cubemx生成的代码,实现一个USB,读取鼠标键盘两个设备。
一个USB,读取鼠标和键盘两个设备

第一步,改代码,重要在usbh_hid.c里

我这里的修改重要对标博主的第三步和第四步。
把原来Cubemx生成的static函数都改成__WEAK,然后本身重写一遍这几个函数,因为这几个函数两个接口都会要用到。

原来博主的文章里写的是直接改这几个红框后面的函数,我这里按照博主的方法,把这几个函数重写,原来的函数就直接把static改成__WEAK,如许就算再用Cubemx修改生成一遍,改动也会很小。
第二步,重新建立本身的.c和.h文件,把改动都放在本身的文件里

我这里建立的名字是My_USB_MouseKey.h和My_USB_MouseKey.c,第一步的图里的函数都要重写,所以我把重写后的函数都放下面吧,大家复制粘贴一下,然后本身跑一下,看那里没有包罗.h的本身包罗一下。
下面展示一些 内联代码片。
  1. My_USB_MouseKey.c
  2. /*------------------函数修改的区域------------------------------*/
  3. uint8_t USBH_HID_GetPollInterval(USBH_HandleTypeDef *phost)
  4. {
  5.         for(int i=0;i<USBH_MAX_NUM_INTERFACES;i++)
  6.         {
  7.                 HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData[i];
  8.                 if ((phost->gState == HOST_CLASS_REQUEST) ||
  9.                                 (phost->gState == HOST_INPUT) ||
  10.                                 (phost->gState == HOST_SET_CONFIGURATION) ||
  11.                                 (phost->gState == HOST_CHECK_CLASS) ||
  12.                                 ((phost->gState == HOST_CLASS)))
  13.                 {
  14.                         return (uint8_t)(HID_Handle->poll);
  15.                 }
  16.                 else
  17.                 {
  18.                         return 0U;
  19.                 }
  20.         }
  21.         return 0U;
  22. }
  23. USBH_StatusTypeDef USBH_HID_SOFProcess(USBH_HandleTypeDef *phost)
  24. {
  25.         for(int i=0;i<USBH_MAX_NUM_INTERFACES;i++)
  26.         {
  27.                 HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData[i];
  28.                 if (HID_Handle->state == USBH_HID_POLL)
  29.                 {
  30.                         if ((phost->Timer - HID_Handle->timer) >= HID_Handle->poll)
  31.                         {
  32.                                 HID_Handle->state = USBH_HID_GET_DATA;
  33.                         #if (USBH_USE_OS == 1U)
  34.                                                 phost->os_msg = (uint32_t)USBH_URB_EVENT;
  35.                         #if (osCMSIS < 0x20000U)
  36.                                                 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
  37.                         #else
  38.                                                 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, 0U);
  39.                         #endif
  40.                         #endif
  41.                         }
  42.                 }
  43.         }
  44.   return USBH_OK;
  45. }
  46. USBH_StatusTypeDef USBH_HID_InterfaceInit(USBH_HandleTypeDef *phost)
  47. {
  48.   USBH_StatusTypeDef status;
  49.   HID_HandleTypeDef *HID_Handle;
  50.   uint8_t max_ep;
  51.   uint8_t num = 0U;
  52.   uint8_t interface;
  53.         for(int i=0;i<USBH_MAX_NUM_INTERFACES;i++)
  54.         {
  55.                 interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, i+1);
  56.                 #include "My_USB_MouseKey.h"
  57.                 InterfaceIndex[i] = interface;
  58.                 if ((interface == 0xFFU) || (interface >= USBH_MAX_NUM_INTERFACES)) /* No Valid Interface */
  59.                 {
  60.                         USBH_DbgLog("Cannot Find the interface for %s class.", phost->pActiveClass->Name);
  61.                         return USBH_FAIL;
  62.                 }
  63.                 status = USBH_SelectInterface(phost, interface);
  64.                 if (status != USBH_OK)
  65.                 {
  66.                         return USBH_FAIL;
  67.                 }
  68.                 phost->pActiveClass->pData[i] = (HID_HandleTypeDef *)USBH_malloc(sizeof(HID_HandleTypeDef));
  69.                 HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData[i];
  70.                 if (HID_Handle == NULL)
  71.                 {
  72.                         USBH_DbgLog("Cannot allocate memory for HID Handle");
  73.                         return USBH_FAIL;
  74.                 }
  75.                 /* Initialize hid handler */
  76.                 (void)USBH_memset(HID_Handle, 0, sizeof(HID_HandleTypeDef));
  77.                 HID_Handle->state = USBH_HID_ERROR;
  78.                 /*Decode Bootclass Protocol: Mouse or Keyboard*/
  79.                 if (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE)
  80.                 {
  81.                         USBH_UsrLog("KeyBoard device found!");
  82.                         HID_Handle->Init = USBH_HID_KeybdInit;
  83.                 }
  84.                 else if (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bInterfaceProtocol  == HID_MOUSE_BOOT_CODE)
  85.                 {
  86.                         USBH_UsrLog("Mouse device found!");
  87.                         HID_Handle->Init = USBH_HID_MouseInit;
  88.                 }
  89.                 else
  90.                 {
  91.                         USBH_UsrLog("Protocol not supported.");
  92.                         return USBH_FAIL;
  93.                 }
  94.                 HID_Handle->state     = USBH_HID_INIT;
  95.                 HID_Handle->ctl_state = USBH_HID_REQ_INIT;
  96.                 HID_Handle->ep_addr   = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bEndpointAddress;
  97.                 HID_Handle->length    = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].wMaxPacketSize;
  98.                 HID_Handle->poll      = phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[0].bInterval;
  99.                 if (HID_Handle->poll  < HID_MIN_POLL)
  100.                 {
  101.                         HID_Handle->poll = HID_MIN_POLL;
  102.                 }
  103.                 /* Check of available number of endpoints */
  104.                 /* Find the number of EPs in the Interface Descriptor */
  105.                 /* Choose the lower number in order not to overrun the buffer allocated */
  106.                 max_ep = ((phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS) ?
  107.                                                         phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].bNumEndpoints : USBH_MAX_NUM_ENDPOINTS);
  108.                 /* Decode endpoint IN and OUT address from interface descriptor */
  109.                 for (num = 0U; num < max_ep; num++)
  110.                 {
  111.                         if ((phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[num].bEndpointAddress & 0x80U) != 0U)
  112.                         {
  113.                                 HID_Handle->InEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[num].bEndpointAddress);
  114.                                 HID_Handle->InPipe = USBH_AllocPipe(phost, HID_Handle->InEp);
  115.                                 /* Open pipe for IN endpoint */
  116.                                 (void)USBH_OpenPipe(phost, HID_Handle->InPipe, HID_Handle->InEp, phost->device.address,
  117.                                                                                                                 phost->device.speed, USB_EP_TYPE_INTR, HID_Handle->length);
  118.                                 (void)USBH_LL_SetToggle(phost, HID_Handle->InPipe, 0U);
  119.                         }
  120.                         else
  121.                         {
  122.                                 HID_Handle->OutEp = (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface].Ep_Desc[num].bEndpointAddress);
  123.                                 HID_Handle->OutPipe  = USBH_AllocPipe(phost, HID_Handle->OutEp);
  124.                                 /* Open pipe for OUT endpoint */
  125.                                 (void)USBH_OpenPipe(phost, HID_Handle->OutPipe, HID_Handle->OutEp, phost->device.address,
  126.                                                                                                                 phost->device.speed, USB_EP_TYPE_INTR, HID_Handle->length);
  127.                                 (void)USBH_LL_SetToggle(phost, HID_Handle->OutPipe, 0U);
  128.                         }
  129.                 }
  130.         }
  131.   return USBH_OK;
  132. }
  133. USBH_StatusTypeDef USBH_HID_InterfaceDeInit(USBH_HandleTypeDef *phost)
  134. {
  135.         for(int i=0;i<USBH_MAX_NUM_INTERFACES;i++)
  136.         {
  137.                 HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData[i];
  138.                 if (HID_Handle->InPipe != 0x00U)
  139.                 {
  140.                         (void)USBH_ClosePipe(phost, HID_Handle->InPipe);
  141.                         (void)USBH_FreePipe(phost, HID_Handle->InPipe);
  142.                         HID_Handle->InPipe = 0U;     /* Reset the pipe as Free */
  143.                 }
  144.                 if (HID_Handle->OutPipe != 0x00U)
  145.                 {
  146.                         (void)USBH_ClosePipe(phost, HID_Handle->OutPipe);
  147.                         (void)USBH_FreePipe(phost, HID_Handle->OutPipe);
  148.                         HID_Handle->OutPipe = 0U;     /* Reset the pipe as Free */
  149.                 }
  150.                 if ((phost->pActiveClass->pData[i]) != NULL)
  151.                 {
  152.                         USBH_free(phost->pActiveClass->pData[i]);
  153.                         phost->pActiveClass->pData[i] = 0U;
  154.                 }
  155.         }
  156.   return USBH_OK;
  157. }
  158. USBH_StatusTypeDef USBH_HID_ClassRequest(USBH_HandleTypeDef *phost)
  159. {
  160.   USBH_StatusTypeDef status         = USBH_BUSY;
  161.   USBH_StatusTypeDef classReqStatus = USBH_BUSY;
  162.         for(int i=0;i<USBH_MAX_NUM_INTERFACES;i++)
  163.         {
  164.                 HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData[i];
  165.                 /* Switch HID state machine */
  166.                 switch (HID_Handle->ctl_state)
  167.                 {
  168.                         case USBH_HID_REQ_INIT:
  169.                         case USBH_HID_REQ_GET_HID_DESC:
  170.                                 USBH_HID_ParseHIDDesc(&HID_Handle->HID_Desc, phost->device.CfgDesc_Raw);
  171.                                 HID_Handle->ctl_state = USBH_HID_REQ_GET_REPORT_DESC;
  172.                                 break;
  173.                         case USBH_HID_REQ_GET_REPORT_DESC:
  174.                                 /* Get Report Desc */
  175.                                 classReqStatus = USBH_HID_GetHIDReportDescriptor(phost, HID_Handle->HID_Desc.wItemLength);
  176.                                 if (classReqStatus == USBH_OK)
  177.                                 {
  178.                                         /* The descriptor is available in phost->device.Data */
  179.                                         HID_Handle->ctl_state = USBH_HID_REQ_SET_IDLE;
  180.                                 }
  181.                                 else if (classReqStatus == USBH_NOT_SUPPORTED)
  182.                                 {
  183.                                         USBH_ErrLog("Control error: HID: Device Get Report Descriptor request failed");
  184.                                         status = USBH_FAIL;
  185.                                 }
  186.                                 else
  187.                                 {
  188.                                         /* .. */
  189.                                 }
  190.                                 break;
  191.                         case USBH_HID_REQ_SET_IDLE:
  192.                                 classReqStatus = USBH_HID_SetIdle(phost, 0U, 0U);
  193.                                 /* set Idle */
  194.                                 if (classReqStatus == USBH_OK)
  195.                                 {
  196.                                         HID_Handle->ctl_state = USBH_HID_REQ_SET_PROTOCOL;
  197.                                 }
  198.                                 else
  199.                                 {
  200.                                         if (classReqStatus == USBH_NOT_SUPPORTED)
  201.                                         {
  202.                                                 HID_Handle->ctl_state = USBH_HID_REQ_SET_PROTOCOL;
  203.                                         }
  204.                                 }
  205.                                 break;
  206.                         case USBH_HID_REQ_SET_PROTOCOL:
  207.                                 /* set protocol */
  208.                                 classReqStatus = USBH_HID_SetProtocol(phost, 0U);
  209.                                 if (classReqStatus == USBH_OK)
  210.                                 {
  211.                                         HID_Handle->ctl_state = USBH_HID_REQ_IDLE;
  212.                                         /* all requests performed*/
  213.                                         phost->pUser(phost, HOST_USER_CLASS_ACTIVE);
  214.                                         status = USBH_OK;
  215.                                 }
  216.                                 else if (classReqStatus == USBH_NOT_SUPPORTED)
  217.                                 {
  218.                                         USBH_ErrLog("Control error: HID: Device Set protocol request failed");
  219.                                         status = USBH_FAIL;
  220.                                 }
  221.                                 else
  222.                                 {
  223.                                         /* .. */
  224.                                 }
  225.                                 break;
  226.                         case USBH_HID_REQ_IDLE:
  227.                         default:
  228.                                 break;
  229.                 }
  230.         }
  231.   return status;
  232. }
  233. USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost)
  234. {
  235.   USBH_StatusTypeDef status = USBH_OK;
  236.         for(int i=0;i<USBH_MAX_NUM_INTERFACES;i++)
  237.         {
  238.                 HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData[i];
  239.                 uint32_t XferSize;
  240.                 switch (HID_Handle->state)
  241.                 {
  242.                         case USBH_HID_INIT:
  243.                                 HID_Handle->Init(phost);
  244.                                 HID_Handle->state = USBH_HID_IDLE;
  245.                                 #if (USBH_USE_OS == 1U)
  246.                                                         phost->os_msg = (uint32_t)USBH_URB_EVENT;
  247.                                 #if (osCMSIS < 0x20000U)
  248.                                                         (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
  249.                                 #else
  250.                                                         (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, 0U);
  251.                                 #endif
  252.                                 #endif
  253.                                                         break;
  254.                         case USBH_HID_IDLE:
  255.                                 status = USBH_HID_GetReport(phost, 0x01U, 0U, HID_Handle->pData, (uint8_t)HID_Handle->length);
  256.                                 if (status == USBH_OK)
  257.                                 {
  258.                                         HID_Handle->state = USBH_HID_SYNC;
  259.                                 }
  260.                                 else if (status == USBH_BUSY)
  261.                                 {
  262.                                         HID_Handle->state = USBH_HID_IDLE;
  263.                                         status = USBH_OK;
  264.                                 }
  265.                                 else if (status == USBH_NOT_SUPPORTED)
  266.                                 {
  267.                                         HID_Handle->state = USBH_HID_SYNC;
  268.                                         status = USBH_OK;
  269.                                 }
  270.                                 else
  271.                                 {
  272.                                         HID_Handle->state = USBH_HID_ERROR;
  273.                                         status = USBH_FAIL;
  274.                                 }
  275.         #if (USBH_USE_OS == 1U)
  276.                                 phost->os_msg = (uint32_t)USBH_URB_EVENT;
  277.         #if (osCMSIS < 0x20000U)
  278.                                 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
  279.         #else
  280.                                 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, 0U);
  281.         #endif
  282.         #endif
  283.                                 break;
  284.                         case USBH_HID_SYNC:
  285.                                 /* Sync with start of Even Frame */
  286.                                 if ((phost->Timer & 1U) != 0U)
  287.                                 {
  288.                                         HID_Handle->state = USBH_HID_GET_DATA;
  289.                                 }
  290.         #if (USBH_USE_OS == 1U)
  291.                                 phost->os_msg = (uint32_t)USBH_URB_EVENT;
  292.         #if (osCMSIS < 0x20000U)
  293.                                 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
  294.         #else
  295.                                 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, 0U);
  296.         #endif
  297.         #endif
  298.                                 break;
  299.                         case USBH_HID_GET_DATA:
  300.                                 (void)USBH_InterruptReceiveData(phost, HID_Handle->pData,
  301.                                                                                                                                                                 (uint8_t)HID_Handle->length,
  302.                                                                                                                                                                 HID_Handle->InPipe);
  303.                                 HID_Handle->state = USBH_HID_POLL;
  304.                                 HID_Handle->timer = phost->Timer;
  305.                                 HID_Handle->DataReady = 0U;
  306.                                 break;
  307.                         case USBH_HID_POLL:
  308.                                 if (USBH_LL_GetURBState(phost, HID_Handle->InPipe) == USBH_URB_DONE)
  309.                                 {
  310.                                         XferSize = USBH_LL_GetLastXferSize(phost, HID_Handle->InPipe);
  311.                                         if ((HID_Handle->DataReady == 0U) && (XferSize != 0U))
  312.                                         {
  313.                                                 (void)USBH_HID_FifoWrite(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length);
  314.                                                 HID_Handle->DataReady = 1U;
  315.                                                
  316.                                                 USBH_HID_EventCallback(phost,i);
  317.         #if (USBH_USE_OS == 1U)
  318.                                                 phost->os_msg = (uint32_t)USBH_URB_EVENT;
  319.         #if (osCMSIS < 0x20000U)
  320.                                                 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
  321.         #else
  322.                                                 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, 0U);
  323.         #endif
  324.         #endif
  325.                                         }
  326.                                 }
  327.                                 else
  328.                                 {
  329.                                         /* IN Endpoint Stalled */
  330.                                         if (USBH_LL_GetURBState(phost, HID_Handle->InPipe) == USBH_URB_STALL)
  331.                                         {
  332.                                                 /* Issue Clear Feature on interrupt IN endpoint */
  333.                                                 if (USBH_ClrFeature(phost, HID_Handle->ep_addr) == USBH_OK)
  334.                                                 {
  335.                                                         /* Change state to issue next IN token */
  336.                                                         HID_Handle->state = USBH_HID_GET_DATA;
  337.                                                 }
  338.                                         }
  339.                                 }
  340.                                 break;
  341.                         default:
  342.                                 break;
  343.                 }
  344.         }
  345.   return status;
  346. }
复制代码
My_USB_MouseKey.h
下面展示一些 内联代码片。
  1. #ifndef __MY_USB_MOUSEKEY_H__
  2. #define __MY_USB_MOUSEKEY_H__               
  3. #include "main.h"         
  4. #include "usbh_def.h"
  5. #include "usart.h"
  6. #include "usbh_hid_mouse.h"
  7. #include "usb_host.h"
  8. #include "usbh_hid.h"
  9. #include "usbh_hid_parser.h"
  10. #ifdef __cplusplus
  11. extern "C" {
  12. #endif
  13. typedef enum{
  14.         EXTRA_NULL=0,
  15.         LEFT_PRESSED,
  16.         RIGHT_PRESSED,
  17.         EXTRA_NULL2,
  18.         MIDDLE_PRESSED,
  19.         EXTRA_NULL3,
  20.         EXTRA_NULL4,
  21.         EXTRA_NULL5,
  22.         SIDE_PRESSED,
  23.         EXTRA_NULL6,
  24.         EXTRA_NULL7,
  25.         EXTRA_NULL8,
  26.         EXTRA_NULL9,
  27.         EXTRA_NULL10,
  28.         EXTRA_NULL11,
  29.         EXTRA_NULL12,
  30.         EXTRA_PRESSED,
  31. }mouse_status;       
  32. typedef enum{
  33.                 MOVEMENT_NULL = 0,
  34.                 UP,
  35.                 DOWN,
  36.                 LEFT,
  37.                 RIGHT,
  38.                 UP_LEFT,
  39.                 UP_RIGHT,
  40.                 DOWN_LEFT,
  41.                 DOWN_RIGHT,
  42. }mouse_movement_status;
  43. extern void USBH_HID_ParseHIDDesc(HID_DescTypeDef *desc, uint8_t *buf);
  44. extern ApplicationTypeDef Appli_state;         
  45. extern  HID_MOUSE_Info_TypeDef    mouse_info;
  46. #ifdef __cplusplus
  47. }
  48. #endif
  49. #endif
复制代码
这就是我的两个.c和.h文件,其中有一些要分析一下。先说.h文件。
我的.h文件里的#include不消说,都要包罗进来,然后是mouse_status,这个枚举是用来最后对标鼠标按键用的枚举;mouse_movement_status是用来对标鼠标移动的枚举。其他的extern重要都是我本身写的函数要用到,所以要extern出来。
然后是.c文件的分析,上面的.c文件里,都是原来的Cubemx里生成的文件,但是要按照博主的方法修改的函数。
第三步,修改struct

我这里对标的是博主的第二步。
修改类结构体,原界说中只有一个数据接口,将这个改成数组形式,就可实现多个接口/类。
下面展示一些 内联代码片。
  1. /* USB Host Class structure */
  2. typedef struct
  3. {
  4.   const char          *Name;
  5.   uint8_t              ClassCode;  
  6.   USBH_StatusTypeDef  (*Init)        (struct _USBH_HandleTypeDef *phost);
  7.   USBH_StatusTypeDef  (*DeInit)      (struct _USBH_HandleTypeDef *phost);
  8.   USBH_StatusTypeDef  (*Requests)    (struct _USBH_HandleTypeDef *phost);  
  9.   USBH_StatusTypeDef  (*BgndProcess) (struct _USBH_HandleTypeDef *phost);
  10.   USBH_StatusTypeDef  (*SOFProcess) (struct _USBH_HandleTypeDef *phost);  
  11.   void*                pData[USBH_MAX_NUM_INTERFACES];//原为pData修改为数组形式
  12. } USBH_ClassTypeDef;
复制代码
第四步,补充USBH_HID_EventCallbcak函数

这里对标博主的第五步。
补充USBH_HID_EventCallbcak函数。此函数被调用于USBH_HID_Process->case HID_POLL,当接收到数据填入fifo后,立即调用USBH_HID_EventCallbcak函数将数据读取到对应的fifo中,防止被下一接口数据覆盖。KeyboardFlag和MouseFlag 用于标志是哪个接口接收了数据。
关于我本身的修改:我这里的修改着实和博主不太一样,因为每次按下键盘大概鼠标都会触发这个函数,所以我把这个函数放在了我本身写的My_USB_MouseKey.h和My_USB_MouseKey.c中。原生的Cubemx的代码我也是直接__WEAK掉了。
Cubemx的代码修改:

然后本身写了一遍,本身写的如下:
重要实现的函数是USBH_HID_MouseDecode(phost);和USBH_HID_GetASCIICode(k_pinfo);
但是这两个函数是Cubemx生成的,所以可以直接用。本身要写的数据处理函数是mouse_data_process(mouse_info);
keypad_data_process©;
这两个函数。
下面展示一些 内联代码片。
  1. void USBH_HID_EventCallback(USBH_HandleTypeDef *phost,uint8_t flag)
  2. {
  3.   #include "usb_host.h"
  4.         #include "usbh_hid_mouse.h"
  5.   char c;
  6.   HID_KEYBD_Info_TypeDef *k_pinfo;
  7.   HID_MOUSE_Info_TypeDef *m_pinfo;
  8.   if(1 == flag)
  9.         {
  10.                 m_pinfo = USBH_HID_GetMouseInfo(phost);
  11.                 if (m_pinfo != NULL)
  12.                 {
  13.                                 //LED_0_State = 0;
  14.                                 USBH_HID_MouseDecode(phost);
  15.                                 mouse_data_process(mouse_info);
  16.                                 memset(m_pinfo ,0,sizeof(HID_MOUSE_Info_TypeDef ));
  17.                 }
  18.         }
  19.         else
  20.         {
  21.                 k_pinfo = USBH_HID_GetKeybdInfo(phost); /* ?????? */
  22.                 if(k_pinfo == NULL)
  23.                 {
  24.                          uint8_t err = 0xff;
  25.                 }
  26.                 if (k_pinfo != NULL)
  27.                 {
  28.                                 c = USBH_HID_GetASCIICode(k_pinfo); /* ???ASCII? */
  29.                                 keypad_data_process(c);
  30.                                
  31.                                 memset(k_pinfo ,0,sizeof(HID_KEYBD_Info_TypeDef ));
  32.                 }
  33.    
  34.         }
  35. }
复制代码
  1. // An highlighted block
复制代码
第五步 修改鼠标和键盘初始化里的pdata

体系自动生成的代码里有两个和键盘鼠标有关的.C文件,一个是usbh_hid_keybd.c,另一个就是usbh_hid_mouse.c。这两个文件夹里各有两个函数要修改。
5.1 键盘文件修改

第一个是关于键盘的,里面的USBH_HID_KeybdInit函数的第一行的phost->pActiveClass->pData要改成phost->pActiveClass->pData[0]。
第二个是USBH_HID_KeybdDecode函数的第一行的phost->pActiveClass->pData要改成phost->pActiveClass->pData[0]。
5.2 鼠标文件修改

第一个是关于鼠标的,里面的USBH_HID_MouseInit函数的第一行的phost->pActiveClass->pData要改成phost->pActiveClass->pData[1]。
第二个是USBH_HID_MouseDecode函数的第一行的phost->pActiveClass->pData要改成phost->pActiveClass->pData[1]。
修改理由:
重要是因为0存储的是键盘的协议,1存储的是鼠标的协议。
第六步 留意Cubemx生成的时候的内存

在Cuebmx的界面里我们设置过一个USB_HOST —>arameter Settings -----> CMSIS_RTOS ----> USBH_PROCESS_STACK_SIZE
这个参数的设置非常重要,必须大于1500,一般在我们的鼠标键盘没有写什么的时候,大于512就可以跑的起来,但是当像我如许写了一些函数来判断后,内存如果小于1500就跑不完,有的时候就连USB的设置符参数都没有读取完成,大概就直接出现体系卡死现象。这个函数就是用来控制整个USB线程能不能正常跑完,不卡死体系的参数。
另有一个参数就是USB_HOST —>arameter Settings -----> Host_Configuration ----->USBH_MAX_DATA_BUFFER
这个参数也很重要,一般没有写什么在Callback的返回函数里的时候,这个数值要大于1024,小于这个数值就会根本进不了Callback函数,会出现按了键盘鼠标什么都不出现。当写了一些判断函数后,也就是我这里的所有的函数的量后,这个数值要大于1500,越大自然越好。小了后,不管按什么都不会有反应。一般最好要大于2000左右,小了自然就很难找到错误了。
关于参考的博主的第六步和第七步

关于博主的第六步和第七步我都没有去做,第一是我发现做了以后,整个USB就跑不动了,不知道那里出了标题,第二就是我觉得博主的第七步说的很对,根本不需要跑demo了,直接所有的都在USBH_HID_EventCallback里已经处理了。
关于运行后另有的一些错误

如果你按我的方法如许修改后,KEIL5一定照旧会报一些错误,因为原生的Cubemx代码里照旧有一些是static界说的,所以如果另有错误,你可以看下错误的地方,把host_hid.c里只要是本身__weak了的函数里的错误的全删除掉,因为只要__weak了,而且你重写了,就不会再跑__WEAK的函数。还可能有一些错误是辨认不到函数,就要#include 一下啊,大概有些变量比如pdata大概下面改进的部分会出现的标题,加了Z在鼠标解码的结构体里,就要本身改下加一下。
关于我本身做的一些改进

我根据本身的硬件设备,做了一些读取USB键盘和鼠标的改进,因为原生的Cubemx生成的鼠标另有一些标题,现在的设备的鼠标的数据和Cubemx生成代码的解码照旧有一些收支,这里分析一下这些有收支的地方和我本身的改进部分。
键盘的改进

我上面的代码里不是有实现keypad_data_process©;这个函数么,我这个函数就是输出一下按键到UART1这种调试接口,用电脑显示一下,我的函数如下:
下面展示一些 内联代码片。
  1. void keypad_data_process(uint8_t data)
  2. {
  3.         printf("%c",data);
  4. }       
  5.                
复制代码
鼠标的改进

因为原生的Cubmx生成的代码在鼠标上和现在的键盘鼠标一体的设备的收支比力大,所以在原生的Cubemx生成的代码上,还要做一些修改。
第一步

USBH_StatusTypeDef USBH_HID_MouseDecode(USBH_HandleTypeDef *phost)函数要修改。
修改后的函数如下,大家可以对比下Cubemx生成的代码,看下区别。

第二步

我这里的是比原生的代码多出来的部分,我这里着实是增加了下面的这个prop_z,这个你们也可以按照我的方法本身加一下,重要是打开usbh_hid_mouse.c文件,差不多150行左右,复制prop_y,粘贴在prop_y下面,并且把mouse_report_data + 2改成mouse_report_data + 3就行了,其他的稳固。

第三步

这个.h里要加一个z,只有z才包罗鼠标的上下移动的数据。

如许就好了,这里我要分析下为啥要加这个。
首先,我发现mouse_info这个变量,也就是用HID_MOUSE_Info_TypeDef界说的是如许的,原生的代码只有x,y,buttons[3],这三个变量,但是我测试下来发现,x里面只有鼠标按键的左键、右键、中建、边按键、第二个边键的信息。y里面只有鼠标的左右移动的信息,所以还缺失了鼠标上下移动的信息。所以在原生的代码里,还要加上这条,才能实现鼠标的上下移动的代码。关于buttons[3],这个就没啥用了,但是每次发送返来的数据里button[3]都是一样的数据,所以可以当做是一种验证码,如果哪次发送返来的buttons【3】数据不一样,就分析这次是错误数据。
关于鼠标的剖析

因为颠末不断的测试,我的鼠标的y和z两个函数和上下左右的关联都有,所以必须要一起处理,单独处理的话,就会很轻易剖析出错,明显是左移数据,就可能会剖析成左和下都有,所以花乐2个小时又不断测试修改,最后成了下面的这些函数。
我本身的鼠标的剖析函数如下:
下面展示一些 内联代码片。
  1. int InterfaceIndex[USBH_MAX_NUM_INTERFACES] ={0};uint8_t Pressed[5]={0};void CLear_MousePressed(){        for(int i =0;i<5;i++)        {                Pressed[i]=0;        }}void Show_MousePressed_Status(uint8_t status){        if((status & LEFT_PRESSED) != 0)        {                Pressed[0] = 1;                printf("左键");        }        if((status & RIGHT_PRESSED) != 0)        {                Pressed[1] = 1;                printf("右键");        }        if((status & MIDDLE_PRESSED) != 0)        {                Pressed[2] = 1;                printf("中建");        }        if((status & SIDE_PRESSED) != 0)        {                Pressed[3] = 1;                printf("边按键");        }        if((status & EXTRA_PRESSED) != 0)        {                Pressed[4] = 1;                printf("边2按键");        }}uint8_t Movement_Measure(uint8_t status1,uint8_t status2){                if(status1 == 0)        {                if(status2 != 0)                {                        if(status2>255/2)                        {                                return UP;                        }                        else                        {                                return DOWN;                        }                }                else                {                        return 0;                }        }        else        {                if(status2 != 0)                {                        if((status1>255/2) && (status2<16))                        {                                return LEFT;//0,253,15                        }                        else                        {                                if((status1>255/2) && (status2>255/2))                                {                                        return UP_LEFT;//0,255,239                                }                                else                                {                                        if((status1<255/2) && (status2>255/2))                                        {                                                return UP_RIGHT;//0,3,240                                        }                                        else                                        {                                                if((status1>255/2) && (status2<255/2))                                                {                                                        return DOWN_LEFT;//0,254,31                                                }                                                else                                                {                                                        return DOWN_RIGHT;//0,2,32                                                }                                        }                                }                        }                }                else                {                        if(status1<255/2 )                        {                                return RIGHT;                        }                                        }        }        return 0;}void Show_MouseMoved_Status(uint8_t status1,uint8_t status2){        switch(Movement_Measure(status1,status2))        {                case LEFT:{printf("左\r\n");break;}                case RIGHT:{printf("右\r\n");break;}                case UP:{printf("上\r\n");break;}                case DOWN:{printf("下\r\n");break;}                case UP_LEFT:{printf("左上\r\n");break;}                case UP_RIGHT:{printf("右上\r\n");break;}                case DOWN_LEFT:{printf("左下\r\n");break;}                case DOWN_RIGHT:{printf("右下\r\n");break;}                default:break;        }}        void keypad_data_process(uint8_t data)
  2. {
  3.         printf("%c",data);
  4. }       
  5.                
  6.          void mouse_data_process(HID_MOUSE_Info_TypeDef data){        if((data.buttons[0] == 0x00) &&(data.buttons[1] == 0x01)&&(data.buttons[2] == 0x00))        {                                if(data.x !=0)                {                //鼠标按键                        Show_MousePressed_Status(data.x);                }                if((data.y != 0x00)||(data.z != 0x00))                {                //鼠标移动                        Show_MouseMoved_Status(data.y,data.z);                }        }        CLear_MousePressed();}       
复制代码
关于鼠标的知识

参考这位博主的文章,这位博主的剖析是正确的。
链接: Linux之剖析鼠标input变乱数据
根据博主的表明,对应我们STM32的HID_MOUSE_Info_TypeDef的数据结构可知,x是鼠标按键,而且x是uint8_t的8位数据。
x的第一位是左键按下
x的第二位是右键按下
x的第三位是中键按下
x的第四位是边键按下
x的第5位是边2键按下
博主文章中的,data 数组的第1个字节:表示鼠标的水平位移;
也就是对应我们的y。
博主文章中的,data 数组的第2个字节:表示鼠标的垂直位移;
也就是对应我们本身新加的z。
关于后续

因为我这个项目只需要用到这几个按键,和移动,所以我也就测试到这里了,如果另有需要鼠标滚轮的变乱的,可以参考
链接: Linux之剖析鼠标input变乱数据
这位博主的继承修改代码,读取滚轮的数据。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

西河刘卡车医

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表