搜索
bottom↓
回复: 254

入门级详细USB移植教程——致正在为USB烦恼的朋友

  [复制链接]

出0入10汤圆

发表于 2014-6-2 12:42:56 | 显示全部楼层 |阅读模式
本帖最后由 10xjzheng 于 2014-6-3 12:23 编辑

同上一篇MPU6050一样,我还是写一篇关于USB的帖子,在圈圈等玩USB的大神面前,我掌握的USB知识实在是九牛一毛,所以这篇帖子加上了入门级的修饰语。写这篇帖子主要是为了那些想快速开发USB的人,至于想深入了解USB协议,可以先学完我这个再去看看别的高级教程可能会好点,虽然我强调自己掌握的USB知识不多,但是对于一般的应用已经足够,我这里主要是学会怎么去用USB做自己的东西,而且我觉得刚学完一个东西就来教下别人实在是一个一举两得的做法,因为我更清楚学习时的心理和一些小问题,而且我也可以进一步总结。我有个观点不知道其他大神中不中听,好像圈圈大神就搞了USB几年达到了精通的水平,可能一些几个月达到了很懂的水平,但是这个过程实在是很漫长,对于很多人也没有必要对USB进行彻底的研究,只要会用就好,就像你可能不懂车的高级原理,但是你会开车就好了,^_^。其他大神不同意的话,写个高级的USB教程让我们学习下吧。这里其实也是个人学习笔记。
记得一个月前,我想做无线鼠标,开始在网上查找资料,从那个时候开始学习USB,找了圈圈的书将前面足足看了3、4遍,还只是瞎子摸象,不过瞎子摸象很正常啦,学什么东西一开始哪里可能能够弄清全局。看了3、4编,实在是很煎熬,一直没有什么进展,没有搞出点成果。就开始上网找资料,让瞎子摸象来得更彻底一点。

如果学过I2C的话,可能对USB理解会更透彻点,两者在某些方面还是有共通之处的,某种意义上来说,STM32的USB跟硬件I2C有点像,89C52的USB介于软件I2C和硬件I2C之间,89C52有了USB芯片的协助后,很多时序不用自己模拟,但是编程使用芯片搞USB这过程就跟软件I2C一样的蛋疼。首先STM32是有USB的两个数据端口的,首先看上面的这张图,是野火ISO板子USB原理图部分,一个VCC,一个GND连接到USB设备,充电的时候就是这两个起作用,供电的作用。D+和D-就是差分数据线,ID我们一般没有用到,是用来设备和主机之间的识别用到,有时候两台机器可以做设备和主机就靠这根线来区别。主要是三极管这部分,由电路图可以知道PD3口要给低电平上拉电阻才能接到D+,应该这里在D-还要有一个三极管和上拉电路,不然这里默认了所接的设备一定是全速设备和高速设备,不是低速设备,不知道接低速设备有没有事。USB运行的前提是要上拉电阻接通才行喔,这里不直接接上拉的原因就是可以自己控制,你可以再程序中控制这里来断开USB连接然后再接上去,选择较多,当然也有直接接上去的。除了STM32,89c52和STC12等单片机也可以搞USB,圈圈就是用89C52来搞的,但是89C52是没有像STM32那样子内置USB外设的,那么就需要加多1块USB芯片,还有相应的外围电路,但是STM32就不用,好方便的说。”主机在检测到设备接入后,会执行设备识别,这个过程比较麻烦,它的枚举过程包含了设备的一些相关信息与通信方式。 “这个过程我觉得如果不是要真正研究USB的话,也没有必要看,看了搞不好神经错乱。加上ST官方库的USB例程后,STM32搞USB难度降低了几个等级。ST官方有个JoyStickMouse的例程,就是通过摇杆来控制鼠标。我们接下来是用按键来控制鼠标。
官方的源文件地址:http://pan.baidu.com/s/1eQuyL8I
原子的触控USB鼠标实验就是其中一个很好的教程,很通俗,很符合初学者心理,可惜讲解得太简短了,不懂触摸屏的可以直接忽略它的触摸屏部分,
教程地址:http://pan.baidu.com/s/1jGuW9EI   
工程地址:http://pan.baidu.com/s/1bnD1IZd
USB2.0协议中文版: http://pan.baidu.com/s/1bnndwYV
关于 STM32F102/103 的USB模块和USB库函数:http://pan.baidu.com/s/1kT7LLhd这是官方对库的说明:http://pan.baidu.com/s/1ntmdbsP
USB英文文档:http://pan.baidu.com/s/1nt6vLs1
USB描述符: http://pan.baidu.com/s/1kTkLlf5
圈圈教你玩USB----PDF: http://pan.baidu.com/s/1ntoKSwL
基于STM32 的USB程序开发笔记(看不懂,不过好像很牛逼):http://pan.baidu.com/s/1kTkLlKb
USB源代码分析(很详细的)http://pan.baidu.com/s/1o6mbbyq
USB鼠标工程(网上找的)圈圈USB资料合集:
首先说明的是你在过程里面看到很多的类似usmart,如果这些都是个人调试程序用的,如果你想进一步了解就看下我这个贴子,不想就直接忽略好了。http://www.amobbs.com/thread-5582408-1-1.html
记住,在网上找到一些USB例程无法直接使用在你的板子上面的原因之一就是硬件的原因,所以才需要稍微了解下原理才能根据自己的板子改装。本帖子会包括:STM32鼠标移植,STM32键盘移植,89C52鼠标移植,89C52键盘移植,可能后续还会有其他的USB作品的移植。

STM32-USB鼠标移植
1.首先你需要按照原子教程下面说的添加文件

这里顺便说下几个文件,大致了解下就好啦
上传一个USB的讲解文档,写得不错。这里面首先是讲解了USB的一些基本知识,如果全部懂了的话,那么USB已经算是学得很好了。鼠标改键盘也有,还有关于具体库函数的详解,看完觉得很赞!!!下面有些内容引用自这个文件!!
文件地址:http://pan.baidu.com/s/1dDw2Hep
usb_desc.c: 提供了设备、端点、接口、字符串、群组、制造商描述符(本来想在这里讲解下描述符的,但是描述符在这里的作用不大明显,到USB键盘那块的时候再讲解吧)

问题八:在标准的 USB 请求命令中,经常会看到 Descriptor,这是什么来的呢?
回答八:Descriptor 即描述符,是一个完整的数据结构,可以通过 C 语言等编程实现,并存
储在 USB 设备中,用于描述一个 USB 设备的所有属性,USB 主机是通过一系列命令来要
求设备发送这些信息的。它的作用就是通过如问答节中的命令***作来给主机传递信息,从
而让主机知道设备具有什么功能、属于哪一类设备、要占用多少带宽、使用哪类传输方式及
数据量的大小,只有主机确定了这些信息之后,设备才能真正开始工作,所以描述符也是十
分重要的部分,要好好掌握。标准的描述符有 5 种,USB 为这些描述符定义了编号:
1——设备描述符
2——配置描述符
3——字符描述符
4——接口描述符
5——端点描述符
上面的描述符之间有一定的关系,一个设备只有一个设备描述符,而一个设备描述符可以包
含多个配置描述符,而一个配置描述符可以包含多个接口描述符,一个接口使用了几个端点,
就有几个端点描述符。这间描述符是用一定的字段构成的,详细说明见上面文档的10页。

简单理解里面就是USB设备的一些描述,像档案。
usb_prop.c: 提供了 Device_Property(性能),Device_Table &USER_STANDARD_REQUEST(请求)结构描述,这 3 个东西定义于 usb_core.c,摇杆鼠标的一些处理过程
hw_config.c: 提供了实际硬件需要的操作函数,Joystick_Send()通过函数UserToPMABufferCopy 和  SetEPTxValid 将坐标值发给了 USB 端口。
STM32f10x_it.c:里面有中断处理函数,千万别忽略里面的内容。
usb_core.c:USB 总线数据处理的核心文件,标准协议。
usb_init.c,usb_int.c:用于端点数据输入输入中断处理
usb_mem.c:用于缓冲区操作
usb_regs.c:用于寄存器操作

2.接下来要在main里面配置USB

详细步骤如下:
1.官方例函数Set_System(); 用途:配置好系统时钟等,按键IO口,以及上面我们提到的接通上拉电阻的那个管脚,USB管脚等等,
这个函数根据作用分为以下几个部分:
系统时钟配置部分(可以省略)
开启上拉时钟管脚的时钟,然后配置该管脚,这个管脚(USB_DISCONNECT_PIN)应该找到它定义的地方,将它改为你板子上面对应的管脚,可以用Ctrl+F找,我们找到它所在的地方如下图,因为这里涉及条件编译,所以你需要找到你对应编译部分的全部改掉。我需要将它改成PD3.

如果你的板子上面没有对应的管脚,只有类似下面的一个跳帽,就需要接上跳帽,接上去之后不要管这部分了,跟你都已经没有关系了。


  1.   /* Enable the USB disconnect GPIO clock */
  2.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO_DISCONNECT, ENABLE);

  3.   /* USB_DISCONNECT used as USB pull-up */
  4.   GPIO_InitStructure.GPIO_Pin = USB_DISCONNECT_PIN;
  5.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  6.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
  7.   GPIO_Init(USB_DISCONNECT, &GPIO_InitStructure);
复制代码
配置USB管脚,不知道为什么没有设置USB还是可以工作。
  1. /*Set PA11,12 as IN - USB_DM,DP*/
  2.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
  3.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
  4.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  5.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  6.   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  7.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  8.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  9.    
  10.   /*SET PA11,12 for USB: USB_DM,DP*/
  11.   GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_14);
  12.   GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_14);
复制代码
配置按键等端口,官方的库是配置摇杆的4个管脚。
  1.   /*Enable Joystick GPIOs clock*/
  2.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE);
  3.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
  4.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);
  5.   /*Configure the JoyStick IOs as input floating*/
  6.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_4 |
  7.                                 GPIO_Pin_9 | GPIO_Pin_10;
  8.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  9.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; /*PullDown is mandatory for Joystick pins*/
  10.   GPIO_Init(GPIOF, &GPIO_InitStructure);

  11.   /*Configure the JoyStick IOs as input floating*/
  12.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_5;                  
  13.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  14.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; /*PullDown is mandatory for Joystick pins*/
  15.   GPIO_Init(GPIOB, &GPIO_InitStructure);
  16.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;  
  17.   GPIO_Init(GPIOF, &GPIO_InitStructure);
  18.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;  
  19.   GPIO_Init(GPIOE, &GPIO_InitStructure);
复制代码
配置USB中断向量,USB传输数据过程需要中断,这个是重中之重,你可以不设置上面其他的东西,但是这个必须设置,别人就会出现,后面自己设置这个,可能多次出现这个,很大原因是中断设置的问题。
  1.   EXTI_ClearITPendingBit(EXTI_Line18);
  2.   EXTI_InitStructure.EXTI_Line = EXTI_Line18;
  3.   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  4.   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  5.   EXTI_Init(&EXTI_InitStructure);
复制代码

上面几个步骤直接简化USB中断向量的设置,所以我在我的程序屏蔽了这个官方函数,直接自己写个,然后放在配置的最前面。
  1. EXTI_InitTypeDef EXTI_InitStructure;
  2. void USB_IT_Config(void)
  3. {
  4.         EXTI_ClearITPendingBit(EXTI_Line18);
  5.   EXTI_InitStructure.EXTI_Line = EXTI_Line18;
  6.   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  7.   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  8.   EXTI_Init(&EXTI_InitStructure);
  9. }
复制代码
2.官方例函数USB_Interrupts_Config();  作用:初始化USB中断,更准确的解释是:开启USB唤醒中断和USB低优先级数据处理中断
3.官方例函数Set_USBClock()       作用:开启USB时钟,更准确的解释是:配置USB 时钟,也就是从72M 的主频得到48M的USB 时钟(1.5 分频)
4.官方例函数USB_Init();         作用:USB硬件初始化,更准确的解释是:用于初始化USB,最主要的就是调用了Joystick_init函数,开启了USB部分的电源等
这里面有个很重要的东西要说下
  1. void USB_Init(void)
  2. {
  3.   pInformation = &Device_Info;
  4.   pInformation->ControlState = 2;
  5.   pProperty = &Device_Property;
  6.   pUser_Standard_Requests = &User_Standard_Requests;
  7.   /* Initialize devices one by one */
  8.   pProperty->Init();
  9. }
复制代码
&Device_Property是跟pProperty 一样的类型的结构体指针,结构体类型定义如下,不看也可以
  1. typedef struct _DEVICE_PROP
  2. {
  3.   void (*Init)(void);        /* Initialize the device */
  4.   void (*Reset)(void);       /* Reset routine of this device */

  5.   /* Device dependent process after the status stage */
  6.   void (*Process_Status_IN)(void);
  7.   void (*Process_Status_OUT)(void);

  8.   /* Procedure of process on setup stage of a class specified request with data stage */
  9.   /* All class specified requests with data stage are processed in Class_Data_Setup
  10.    Class_Data_Setup()
  11.     responses to check all special requests and fills ENDPOINT_INFO
  12.     according to the request
  13.     If IN tokens are expected, then wLength & wOffset will be filled
  14.     with the total transferring bytes and the starting position
  15.     If OUT tokens are expected, then rLength & rOffset will be filled
  16.     with the total expected bytes and the starting position in the buffer

  17.     If the request is valid, Class_Data_Setup returns SUCCESS, else UNSUPPORT

  18.    CAUTION:
  19.     Since GET_CONFIGURATION & GET_INTERFACE are highly related to
  20.     the individual classes, they will be checked and processed here.
  21.   */
  22.   RESULT (*Class_Data_Setup)(uint8_t RequestNo);

  23.   /* Procedure of process on setup stage of a class specified request without data stage */
  24.   /* All class specified requests without data stage are processed in Class_NoData_Setup
  25.    Class_NoData_Setup
  26.     responses to check all special requests and perform the request

  27.    CAUTION:
  28.     Since SET_CONFIGURATION & SET_INTERFACE are highly related to
  29.     the individual classes, they will be checked and processed here.
  30.   */
  31.   RESULT (*Class_NoData_Setup)(uint8_t RequestNo);

  32.   /*Class_Get_Interface_Setting
  33.    This function is used by the file usb_core.c to test if the selected Interface
  34.    and Alternate Setting (uint8_t Interface, uint8_t AlternateSetting) are supported by
  35.    the application.
  36.    This function is writing by user. It should return "SUCCESS" if the Interface
  37.    and Alternate Setting are supported by the application or "UNSUPPORT" if they
  38.    are not supported. */

  39.   RESULT  (*Class_Get_Interface_Setting)(uint8_t Interface, uint8_t AlternateSetting);

  40.   uint8_t* (*GetDeviceDescriptor)(uint16_t Length);
  41.   uint8_t* (*GetConfigDescriptor)(uint16_t Length);
  42.   uint8_t* (*GetStringDescriptor)(uint16_t Length);

  43.   /* This field is not used in current library version. It is kept only for
  44.    compatibility with previous versions */
  45.   void* RxEP_buffer;
  46.    
  47.   uint8_t MaxPacketSize;

  48. }DEVICE_PROP;
复制代码
Device_Property这个结构体里面有多个我们已经定义好的函数,如下:
  1. DEVICE_PROP Device_Property =
  2.   {
  3.     Joystick_init,
  4.     Joystick_Reset,
  5.     Joystick_Status_In,
  6.     Joystick_Status_Out,
  7.     Joystick_Data_Setup,
  8.     Joystick_NoData_Setup,
  9.     Joystick_Get_Interface_Setting,
  10.     Joystick_GetDeviceDescriptor,
  11.     Joystick_GetConfigDescriptor,
  12.     Joystick_GetStringDescriptor,
  13.     0,
  14.     0x40 /*MAX PACKET SIZE*/
  15.   };
复制代码
在语句pProperty = &Device_Property; 和 pProperty->Init();之后,就运行了这个函数Joystick_init,里面有再看PowerOn,里面又有USB_Cable_Config(ENABLE);好不容易找到我们想要的函数。这个就是断开和连接上拉电阻的函数,前面我们只是打开时钟和配置这个管脚而已,同样的他对应的管脚是USB_DISCONNECT和USB_DISCONNECT_PIN,前面如果将这两个改了,就不要改了。
  1. /*******************************************************************************
  2. * Function Name  : USB_Cable_Config.
  3. * Description    : Software Connection/Disconnection of USB Cable.
  4. * Input          : NewState: new state.
  5. * Output         : None.
  6. * Return         : None
  7. *******************************************************************************/
  8. void USB_Cable_Config (FunctionalState NewState)
  9. {
  10. #if defined(STM32L1XX_MD) || defined(STM32L1XX_HD)|| defined(STM32L1XX_MD_PLUS)
  11.   if (NewState != DISABLE)
  12.   {
  13.     STM32L15_USB_CONNECT;
  14.   }
  15.   else
  16.   {
  17.     STM32L15_USB_DISCONNECT;
  18.   }  
  19.    
  20. #else
  21.   if (NewState != DISABLE)
  22.   {
  23.     GPIO_ResetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
  24.   }
  25.   else
  26.   {
  27.     GPIO_SetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);
  28.   }
  29. #endif /* STM32L1XX_MD */
  30. }
复制代码
这样子很麻烦,我就自己写了个函数USB_Power_On();//给上拉电阻的三极管导通,我觉得这个是最重要的,如果你上拉电阻都没有连接上去,那还谈什么其他的。
要让你的电脑识别这是个鼠标的话,还需要配置中端函数,官方函数写在stm32_it.c这个文件里面,这个也是重点,我找了很久才知道在中断函数里面还有这样子的东西,相关代码如下:
  1. /******************************************************************************/
  2. /*            STM32 Peripherals Interrupt Handlers                            */
  3. /*******************************************************************************
  4. * Function Name  : USB_IRQHandler
  5. * Description    : This function handles USB Low Priority interrupts
  6. *                  requests.
  7. * Input          : None
  8. * Output         : None
  9. * Return         : None
  10. *******************************************************************************/
  11. #if defined(STM32L1XX_MD) || defined(STM32L1XX_HD)|| defined(STM32L1XX_MD_PLUS) || defined(STM32F37X)
  12. void USB_LP_IRQHandler(void)
  13. #else
  14. void USB_LP_CAN1_RX0_IRQHandler(void)
  15. #endif
  16. {
  17.   USB_Istr();
  18. }

  19. #if defined(STM32L1XX_MD) || defined(STM32L1XX_HD)|| defined(STM32L1XX_MD_PLUS)

  20. /*******************************************************************************
  21. * Function Name  : USB_FS_WKUP_IRQHandler
  22. * Description    : This function handles USB WakeUp interrupt request.
  23. * Input          : None
  24. * Output         : None
  25. * Return         : None
  26. *******************************************************************************/
  27. void USB_FS_WKUP_IRQHandler(void)
  28. {
  29.   EXTI_ClearITPendingBit(EXTI_Line18);
  30. }
  31. #endif
  32. /*******************************************************************************
  33. * Function Name  : EXTI_IRQHandler
  34. * Description    : This function handles External lines  interrupt request.
  35. * Input          : None
  36. * Output         : None
  37. * Return         : None
  38. *******************************************************************************/
  39. #if defined(STM32L1XX_MD) || defined(STM32L1XX_HD)|| defined(STM32L1XX_MD_PLUS)
  40. void EXTI0_IRQHandler(void)
  41. #elif defined (STM32F37X)
  42. void EXTI2_TS_IRQHandler(void)
  43. #else
  44. void EXTI9_5_IRQHandler(void)
  45. #endif
  46. {
  47.   if (EXTI_GetITStatus(KEY_BUTTON_EXTI_LINE) != RESET)
  48.   {
  49.     /* Check if the remote wakeup feature is enabled (it could be disabled
  50.         by the host through ClearFeature request) */
  51.     if (pInformation->Current_Feature & 0x20)
  52.     {      
  53.       pInformation->Current_Feature &= ~0x20;  
  54.       /* Exit low power mode and re-configure clocks */
  55.       Resume(RESUME_INTERNAL);
  56.     }
  57.   
  58.     /* Clear the EXTI line pending bit */
  59.     EXTI_ClearITPendingBit(KEY_BUTTON_EXTI_LINE);
  60.   }
  61. }

  62. /*******************************************************************************
  63. * Function Name  : USBWakeUp_IRQHandler
  64. * Description    : This function handles USB WakeUp interrupt request.
  65. * Input          : None
  66. * Output         : None
  67. * Return         : None
  68. *******************************************************************************/
  69. void USBWakeUp_IRQHandler(void)
  70. {
  71.   EXTI_ClearITPendingBit(EXTI_Line18);
  72. }
复制代码
我将他们移植到我的stm32f10x_it.c文件里面,实际代码如下:
  1. /*******************************************************************************
  2. * Function Name  : USBWakeUp_IRQHandler
  3. * Description    : This function handles USB WakeUp interrupt request.
  4. * Input          : None
  5. * Output         : None
  6. * Return         : None
  7. *******************************************************************************/
  8. void USBWakeUp_IRQHandler(void)
  9. {
  10.   EXTI_ClearITPendingBit(EXTI_Line18);
  11. }
  12. /*******************************************************************************
  13. * Function Name  : USB_IRQHandler
  14. * Description    : This function handles USB Low Priority interrupts
  15. *                  requests.
  16. * Input          : None
  17. * Output         : None
  18. * Return         : None
  19. *******************************************************************************/
  20. void USB_LP_CAN1_RX0_IRQHandler(void)
  21. {
  22.   USB_Istr();
  23. }
复制代码
上面的东西移植好了的话,成功的话你会发现在你的电脑上多了一个鼠标设备。其实这个过程远远没有我上面描述的那么简单,上面只是几个小问题而已,你会遇到很多文件编译的问题,慢慢解决吧。怎么说呢?编译的问题很多,我不想写出来,留给大家慢慢去学习下怎么移植程序吧,部分问题可以看下这个帖子:
http://www.openedv.com/posts/list/33515.htm?privmsg=21890&&sysid=20#192355
3.真正控制鼠标
实际要控制鼠标还要看死循环里面的这些函数

  1.     if (bDeviceState == CONFIGURED)
  2.     {
  3.       if ((JoyState() != 0) && (PrevXferComplete))
  4.       {
  5.         Joystick_Send(JoyState());
  6.       }
  7.     }
复制代码
主要是Joystick_Send(JoyState());这个函数,JoyState获取摇杆的动作之后发给Joystick_Send进行处理,CURSOR_STEP是鼠标移动的距离,这个过程简单地说就是需要单片机要发送一些东西给电脑,什么东西呢?Mouse_Buffer[4] 里面的东西,这四个元素分别作用是:Mouse_Buffer[0]的D0就是左键,D1就是右键,D2是中键,Mouse_Buffer[1]为x轴,你发送个负数鼠标就左移相应的距离,正数右移,Mouse_Buffer[2]为y轴,Mouse_Buffer[3为滚轮。由这些解释我们可以知道Joystick_Send这个函数就是先判断遥感的方向,然后发送相应的键值过去罢了。左右按键可以看下我之前遇到的一个问题,你会对这部分有更深的理解,后面有我的解释。
请教在设计USB键盘的时候怎么才能达到一直按下的效果:http://www.amobbs.com/thread-5581955-1-1.html
  1. void Joystick_Send(uint8_t Keys)
  2. {
  3.   uint8_t Mouse_Buffer[4] = {0, 0, 0, 0};
  4.   int8_t X = 0, Y = 0;
  5.   
  6.   switch (Keys)
  7.   {
  8.     case JOY_LEFT:
  9.       X -= CURSOR_STEP;
  10.       break;
  11.     case JOY_RIGHT:

  12.       X += CURSOR_STEP;
  13.       break;
  14.     case JOY_UP:
  15.       Y -= CURSOR_STEP;
  16.       break;
  17.     case JOY_DOWN:
  18.       Y += CURSOR_STEP;
  19.       break;
  20.     default:
  21.       return;
  22.   }
  23.   /* prepare buffer to send */
  24.   Mouse_Buffer[1] = X;
  25.   Mouse_Buffer[2] = Y;
  26.   
  27.   /* Reset the control token to inform upper layer that a transfer is ongoing */
  28.   PrevXferComplete = 0;
  29.   
  30.   /* Copy mouse position info in ENDP1 Tx Packet Memory Area*/
  31.   USB_SIL_Write(EP1_IN, Mouse_Buffer, 4);
  32.   
  33.   /* Enable endpoint for transmission */
  34.   SetEPTxValid(ENDP1);

  35. }
复制代码
鼠标的移植到这里就结束了。如果你是野火ISO的板子,那么下载我的工程下去后,按下KEY1鼠标左移,KEY2鼠标右移。
工程地址:http://pan.baidu.com/s/1jGMaXU2

STM32-USB键盘移植
放上一个山寨的电脑遥感飞车的视频,使用的就是USB键盘的原理。
http://v.youku.com/v_show/id_XNzE5MTM3NDUy.html
被山寨的作品的帖子:http://www.amobbs.com/thread-5531209-1-1.html成本:
目前成本:100块
元件清单:STM32最小系统+MPU6050+几根杜邦线+USB线
成本最低可降至:40块。
最低成本元件清单:2元STC12单片机+25元USB模块(可能可以降至更低,自己做的话)+MPU6050(最低10块),可能企业生产的话会便宜很多。
涉及的软硬件知识:
1.USB通讯协议,用来模拟键盘用,这个最坑
2.I2C通讯协议,用来获取MPU6050数据用
3.MPU6050的使用
4.STM32单片机的使用
5.串口方面的东西,用来调试MPU6050输出数据
项目细节介绍:
1.下面这两句是精华,可以看一个文档,就知道这里面的奥秘,从获取的各轴加速度大概算出MPU6050的姿态。高中物理知识啊!!http://pan.baidu.com/s/1jGzajLs
  1.         Roll =  (((atan2(temp1[2],temp1[0])*180)/3.1416)-90); //x轴角度
  2.         Pitch = (((atan2(temp1[2],temp1[1])*180)/3.1416)-90); //y轴角度
复制代码

2.MPU6050可以看这个我发的帖子:http://www.amobbs.com/thread-5581033-1-1.html
放上工程文件:http://pan.baidu.com/s/1bn3Yg3t板子是野火ISO。

怎么将上面的鼠标改成键盘呢?鼠标和键盘在程序上的区别是什么?总体上来说,两者都是HID设备,很大部分都是一样,所以程序很大部分一样。不一样就是鼠标是鼠标,键盘是键盘,细节的东西不一样。可以参见两篇帖子,一篇是上面的飞车
一篇是圈圈的:
http://www.amobbs.com/thread-1387906-1-1.html
有人将其内容整理成文档,地址如下:
http://pan.baidu.com/s/1i3j3uEL
不过一开始读他们的帖子感觉还是很难懂。设备描述符可以结合上面的那个USB基础知识去看,多少页?都说是10页那里了。^__^这些比较繁琐,而且都有这么多资料了,大就慢慢看吧
按下某个键就相当于在按照相应的格式发送相应键的值过去,这些键的值就在这个文档里面,HID键盘代码:http://pan.baidu.com/s/1kThxxNh









本帖子中包含更多资源

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

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入10汤圆

 楼主| 发表于 2014-6-19 09:54:54 | 显示全部楼层
lyk07351 发表于 2014-6-19 09:47
"USB源代码分析(很详细的)http://pan.baidu.com/s/1o6mbbyq"
这个链接已经挂掉了,楼主看到处理下? ...

在这里,云盘真烦!!

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2014-6-2 12:49:12 | 显示全部楼层
正需要,端午有要用到

出0入10汤圆

 楼主| 发表于 2014-6-2 12:52:49 | 显示全部楼层
Vmao 发表于 2014-6-2 12:49
正需要,端午有要用到

希望能对你们有帮助

出0入0汤圆

发表于 2014-6-2 13:06:32 | 显示全部楼层

出0入0汤圆

发表于 2014-6-2 13:52:44 | 显示全部楼层
前来支持

出0入10汤圆

 楼主| 发表于 2014-6-2 14:48:38 | 显示全部楼层

大神来支持啦

出0入0汤圆

发表于 2014-6-2 15:01:49 | 显示全部楼层

我不是大神。。。。。。。。。。见笑了

出0入0汤圆

发表于 2014-6-2 15:11:16 | 显示全部楼层
感谢分享精神,这种精神带动每一个人乐于分享,造成论坛良好氛围,人人为我,我为人人。。。。

出0入0汤圆

发表于 2014-6-2 15:22:24 | 显示全部楼层
顶顶顶顶,学习了啊

出0入10汤圆

 楼主| 发表于 2014-6-2 15:26:31 | 显示全部楼层
caizhiwei 发表于 2014-6-2 15:11
感谢分享精神,这种精神带动每一个人乐于分享,造成论坛良好氛围,人人为我,我为人人。。。。 ...

那楼主是不是有空也发几个技术贴啊?

出0入0汤圆

发表于 2014-6-2 15:36:53 | 显示全部楼层
10xjzheng 发表于 2014-6-2 15:26
那楼主是不是有空也发几个技术贴啊?

我经常发的,你这帖子还没来得及细看呢

出0入0汤圆

发表于 2014-6-2 15:59:38 | 显示全部楼层
mark,ding

出0入0汤圆

发表于 2014-6-2 16:07:40 | 显示全部楼层
前排留名.....
不小心点了发表233

出0入0汤圆

发表于 2014-6-2 23:45:06 | 显示全部楼层
感谢分享

出0入0汤圆

发表于 2014-6-3 09:11:34 | 显示全部楼层
楼主造福大众啊

出0入0汤圆

发表于 2014-6-3 09:30:55 | 显示全部楼层
感谢分享

出100入101汤圆

发表于 2014-6-3 09:53:11 | 显示全部楼层
总结的挺好!

出0入0汤圆

发表于 2014-6-3 10:50:06 | 显示全部楼层
感谢分享              

出0入0汤圆

发表于 2014-6-3 13:33:34 | 显示全部楼层
好东西,谢谢

出0入0汤圆

发表于 2014-6-3 14:24:23 | 显示全部楼层
非常好的帖子,保存了。

出0入0汤圆

发表于 2014-6-3 15:28:03 | 显示全部楼层
写的很是详细尼!!学习中!!

出0入0汤圆

发表于 2014-6-3 15:35:55 | 显示全部楼层
最近正想上手stm32,感谢分享收藏了,

出0入0汤圆

发表于 2014-6-3 15:58:04 | 显示全部楼层
请教LZ一个问题。 我自定义HID 。 MCU 会收到主机IN信号。然后发送64个字节 00. 我想做到只有PC 软件发送数据的时候,MCU才可以使能IN信号。 有没有好办法解决这个问题。

出0入10汤圆

 楼主| 发表于 2014-6-3 19:27:35 | 显示全部楼层
waterghost 发表于 2014-6-3 15:58
请教LZ一个问题。 我自定义HID 。 MCU 会收到主机IN信号。然后发送64个字节 00. 我想做到只有PC 软件发送数 ...

不好意思 ,我都没有自定义过HID,我的USB水平还是很有限的。

出0入0汤圆

发表于 2014-6-3 20:33:13 | 显示全部楼层
顶顶,。   

出0入0汤圆

发表于 2014-6-3 20:58:38 | 显示全部楼层
非常感谢,我要认真拜读啊。mark

出0入0汤圆

发表于 2014-6-3 21:14:09 来自手机 | 显示全部楼层
学习了      

出0入0汤圆

发表于 2014-6-3 21:26:53 | 显示全部楼层
学习!!

出0入17汤圆

发表于 2014-6-3 22:23:23 | 显示全部楼层
还是挺烦恼的,楼主的资料都是DEVICE的,没有HOST!

出0入0汤圆

发表于 2014-6-3 22:29:23 | 显示全部楼层
顶起,mark

出0入0汤圆

发表于 2014-6-4 14:01:18 | 显示全部楼层
关于USB的知识当然是果断标记了

出0入0汤圆

发表于 2014-6-4 14:10:54 | 显示全部楼层
没真正  研究过           

出0入0汤圆

发表于 2014-6-4 14:17:44 | 显示全部楼层
为LZ的热心叫好!

出0入10汤圆

 楼主| 发表于 2014-6-5 08:20:47 | 显示全部楼层
DOER 发表于 2014-6-3 22:23
还是挺烦恼的,楼主的资料都是DEVICE的,没有HOST!

host没有研究过,host用来做什么用的?一般都只用设备就好啦。

出0入0汤圆

发表于 2014-6-5 08:30:32 | 显示全部楼层
一片M8加一片mpu6050应该成本更低。

出0入0汤圆

发表于 2014-6-5 09:05:34 | 显示全部楼层
写的很详细不错!

出0入0汤圆

发表于 2014-6-5 09:05:49 | 显示全部楼层
写的很详细不错!

出0入0汤圆

发表于 2014-6-5 09:22:41 | 显示全部楼层
已经收藏,慢慢研究

出0入0汤圆

发表于 2014-6-5 09:34:31 | 显示全部楼层
谢谢楼主分享,赶紧来学习一下!

出0入0汤圆

发表于 2014-6-5 09:41:57 | 显示全部楼层
如此好贴,楼主的精神很好,写的很棒。

出0入0汤圆

发表于 2014-6-5 09:46:37 | 显示全部楼层
谢谢楼主分享,总结的很出色,期待来飞思卡尔讨论区分享USB知识!

出0入10汤圆

 楼主| 发表于 2014-6-5 10:17:30 | 显示全部楼层
FSL_TICS_ZP 发表于 2014-6-5 09:46
谢谢楼主分享,总结的很出色,期待来飞思卡尔讨论区分享USB知识!

没有用过,不过原理应该都是相通的。

出0入0汤圆

发表于 2014-6-5 10:28:34 | 显示全部楼层
路过支持一下

出0入0汤圆

发表于 2014-6-5 10:44:55 | 显示全部楼层
10xjzheng 发表于 2014-6-5 10:17
没有用过,不过原理应该都是相通的。

是的,通信过程遵循USB协议规定的步骤,只是落实具体MCU的处理过程有些差别。

出0入0汤圆

发表于 2014-6-5 10:45:30 | 显示全部楼层
期待楼主更多关于USB学习资料。

出0入0汤圆

发表于 2014-6-5 11:16:33 | 显示全部楼层
刚看完,欣赏楼主的态度,消化消化。

出0入0汤圆

发表于 2014-6-5 11:28:26 | 显示全部楼层
这个要顶一下以后学习用

出0入0汤圆

发表于 2014-6-9 14:58:10 | 显示全部楼层
正要用,MARK

出0入0汤圆

发表于 2014-6-9 15:08:32 | 显示全部楼层
MARK                                                      

出0入0汤圆

发表于 2014-6-9 17:14:05 | 显示全部楼层
文章很棒,但往往过一段时间,百度盘的一下链接容易失效,到时帖子就不完整了。

出0入10汤圆

 楼主| 发表于 2014-6-9 19:34:44 | 显示全部楼层
guoj 发表于 2014-6-9 17:14
文章很棒,但往往过一段时间,百度盘的一下链接容易失效,到时帖子就不完整了。 ...

没有办法啊,阿莫论坛上传东西太慢了,靠!!!!!!!!!!!!!!!!

出0入0汤圆

发表于 2014-6-9 19:51:23 | 显示全部楼层
一直在模仿,从未成功过           

出0入0汤圆

发表于 2014-6-9 20:26:15 来自手机 | 显示全部楼层
标记一下,

出0入10汤圆

 楼主| 发表于 2014-6-9 21:43:51 | 显示全部楼层
zl_123 发表于 2014-6-9 19:51
一直在模仿,从未成功过

本帖子中包含更多资源

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

x

出1000入0汤圆

发表于 2014-6-9 22:54:59 | 显示全部楼层
收藏学习了

出0入0汤圆

发表于 2014-6-10 06:28:34 来自手机 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2014-6-10 09:02:07 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2014-6-18 17:14:26 | 显示全部楼层
本帖最后由 yzb1019 于 2014-6-18 19:11 编辑

刚刚开始学习USB,正好赶上了.哈哈,搞不懂车的原理,但是会开车就好,这句话周航慈的嵌入式那本书里有哦。

出0入0汤圆

发表于 2014-6-18 23:33:34 | 显示全部楼层
感谢楼主的无私奉献精神

出0入0汤圆

发表于 2014-6-19 06:57:14 | 显示全部楼层
mark                                                                        

出0入0汤圆

发表于 2014-6-19 08:15:53 | 显示全部楼层
good 学习学习!

出0入0汤圆

发表于 2014-6-19 08:35:39 | 显示全部楼层
很不错,学习学习。

出0入0汤圆

发表于 2014-6-19 09:47:05 | 显示全部楼层
10xjzheng 发表于 2014-6-9 19:34
没有办法啊,阿莫论坛上传东西太慢了,靠!!!!!!!!!!!!!!!! ...


"USB源代码分析(很详细的)http://pan.baidu.com/s/1o6mbbyq"
这个链接已经挂掉了,楼主看到处理下?

出0入0汤圆

发表于 2014-6-19 09:50:35 | 显示全部楼层
好帖子, MARK

出0入0汤圆

发表于 2014-6-19 09:51:52 | 显示全部楼层
学习学习!可能会用到!!

出0入0汤圆

发表于 2014-6-19 09:54:33 | 显示全部楼层
楼主此乃用心良苦。非常感谢分享,暂时没用到。

出0入0汤圆

发表于 2014-6-19 10:02:23 | 显示全部楼层
mark ,顶一下

出0入0汤圆

发表于 2014-6-19 14:36:22 | 显示全部楼层
h很好的东西,顶!

出0入0汤圆

发表于 2014-6-19 14:42:02 | 显示全部楼层
标记
谢谢楼主
以后可能用得上

出0入0汤圆

发表于 2014-6-23 09:59:52 | 显示全部楼层
很好,收藏回家慢慢看

出0入0汤圆

发表于 2014-6-23 15:29:30 | 显示全部楼层
很好,收藏回家慢慢看

出0入0汤圆

发表于 2014-6-23 15:34:59 | 显示全部楼层
好贴  仔细学习中  mark

出0入0汤圆

发表于 2014-6-24 09:59:30 | 显示全部楼层
这个是好贴,留名,谢谢!

出0入0汤圆

发表于 2014-6-24 20:20:27 | 显示全部楼层
厉害哦,

出0入0汤圆

发表于 2014-6-24 22:34:41 | 显示全部楼层
很详细,谢谢!mark                                                         

出0入0汤圆

发表于 2014-6-24 23:08:38 | 显示全部楼层
mark,谢谢楼主分享

出0入0汤圆

发表于 2014-10-13 13:10:45 | 显示全部楼层
必须要写一个记号,此文档为初学而生。

出0入137汤圆

发表于 2014-10-13 13:13:35 | 显示全部楼层
usb 留个记号        

出0入0汤圆

发表于 2014-10-13 13:19:49 | 显示全部楼层
mark,标记。。。

出0入0汤圆

发表于 2014-10-13 14:11:06 | 显示全部楼层
好资料,谢谢分享

出0入0汤圆

发表于 2014-10-13 14:50:40 | 显示全部楼层

感谢分享

出0入0汤圆

发表于 2014-10-13 14:51:39 | 显示全部楼层
感谢楼主分享,谢谢

出0入0汤圆

发表于 2014-10-13 14:53:49 | 显示全部楼层
楼主费心了

出0入0汤圆

发表于 2014-10-13 14:59:01 | 显示全部楼层
mark 一下

出0入0汤圆

发表于 2014-10-13 15:01:17 | 显示全部楼层
mark下,想学USB,结果开头一半就停下了

出0入0汤圆

发表于 2014-10-13 15:22:28 | 显示全部楼层
这个一定要收藏好

出0入0汤圆

发表于 2014-10-13 15:45:35 来自手机 | 显示全部楼层
收藏,准备要着手USB

出0入0汤圆

发表于 2014-10-13 15:56:54 | 显示全部楼层
额,同学也买了圈圈的开发板来学习USB,很不错

出0入0汤圆

发表于 2014-10-13 16:18:02 | 显示全部楼层
晚上回家看看

出0入0汤圆

发表于 2014-10-15 11:44:20 | 显示全部楼层
收藏一下!

出0入0汤圆

发表于 2014-10-15 11:49:46 | 显示全部楼层

顶顶顶顶,学习了啊

出0入0汤圆

发表于 2014-10-15 12:02:14 | 显示全部楼层
我擦,火速留名啊

出0入0汤圆

发表于 2014-10-15 12:31:00 | 显示全部楼层
mark mark and mark

出0入0汤圆

发表于 2014-10-15 12:54:43 | 显示全部楼层
很好很详细的资料~~~

出0入0汤圆

发表于 2014-10-15 13:14:37 | 显示全部楼层
学习一下,

出0入0汤圆

发表于 2014-10-15 13:28:12 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2014-10-15 13:35:37 | 显示全部楼层
这个必须得收藏啊

出0入0汤圆

发表于 2014-10-15 13:35:52 | 显示全部楼层
学习学习一下啦

出0入0汤圆

发表于 2014-10-15 13:38:53 | 显示全部楼层
学习学习。谢谢
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 23:29

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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