移植STM32固件库用于HID双向通信

原文地址::http://blog.csdn.net/madrabbit1987/article/details/67690661


USB的应用中HID类是比较常见的方式。通过修改STM32 USB固件库V4.0的JOYSTICK应用,我们实现一个双向USB通信。
一、移植
使用STM32源程序为点亮LED灯程序。
首先将USB固件库中有用的函数复制到源函数中,
建立LIB文件夹其中放入USB2.0协议函数


建立CFG文件夹放入USB应用函数

将两个文件夹都放到源工程目录下将文件添加进来,设置好,配置好KEIL软件设置。

二、修改文件
1、首先修改platform_config.h函数。
    该文件是对于多种芯片对于USB库的支持。我们使用STM32F103ZET6芯片,所以只保留与之相关的ID项,与USB_DISCONNECT线(PG11)的配置。修改之后的头文件如下所示


2、然后修改hw_config.c中Set_System函数

    实际上STM32F103zet6不需要对USB端口进行单独的配置,删掉Set_System函数中没用的部分,只对USB_DISCONNECT线(PG11)进行初始化。修改后的函数如下图所示。

3、接下来修改hw_config.c文件中USB_Cable_Config函数因为我使用的是比较老的神舟III开发板,当PG11为高电平时实现上拉,所以修改后的函数为

4、修改USB_Interrupt_Config函数,配置USB_LP_CAN1_RX0_IRQn和USBWakeUp_IRQn中断修改后的函数如下图所示。

5、接下来删掉hw_config.c文件中GPIO_AINConfig函数,没有什么用,只会报错

6、删掉与按键相关的设置,因为我们并没有用到,主要是先清除JoyState和Joystick_Send函数中内容,不用管。

7、最后我们处理USB挂起相关的问题。在USB固件库中提供挂起相关的处理函数,主要有2个函数需要修改。它们是Suspend函数和Enter_LowPowerMode函数。其中,在Suspend函数中注释掉PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);语句。修改Suspend函数,如下图所示

OK接下来应该就没有什么需要修改的地方了(如果有的话请酌情修改)
三、描述符修改
使用USB HID类进行通信调试。所以要对USB的描述符要做部分修改(usb_desc.c)。下面我们贴程序说明(只对重要修改做说明)

设备描述符
修改idVendor和idProduct的值,为任意其他值,我里我用给的是0x0413和0x5724,修改的时候注意大小端

配置描述符集合

[cpp]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:10px;">const uint8_t Joystick_ConfigDescriptor[JOYSTICK_SIZ_CONFIG_DESC] =  
  2.   {  
  3.     0x09, /* bLength: Configuration Descriptor size */  
  4.     USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */  
  5.     JOYSTICK_SIZ_CONFIG_DESC,  
  6.     /* wTotalLength: Bytes returned */  
  7.     0x00,  
  8.     0x01,         /*bNumInterfaces: 1 interface*/  
  9.     0x01,         /*bConfigurationValue: Configuration value*/  
  10.     0x00,         /*iConfiguration: Index of string descriptor describing 
  11.                                      the configuration*/  
  12.     0xE0,         /*bmAttributes: Self powered */  
  13.     0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*/  
  14.   
  15.     /************** Descriptor of Joystick Mouse interface ****************/  
  16.     /* 09 */  
  17.     0x09,         /*bLength: Interface Descriptor size*/  
  18.     USB_INTERFACE_DESCRIPTOR_TYPE,/*bDescriptorType: Interface descriptor type*/  
  19.     0x00,         /*bInterfaceNumber: Number of Interface*/  
  20.     0x00,         /*bAlternateSetting: Alternate setting*/  
  21.     0x02,         /*bNumEndpoints除端点0外,需要1输入1输出*/  
  22.     0x03,         /*bInterfaceClass: HID*/  
  23.     0x00,         /*bInterfaceSubClass : 1=BOOT, 0=no boot选择no boot*/  
  24.     0x00,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse选择none*/  
  25.     0,            /*iInterface: Index of string descriptor*/  
  26.     /******************** Descriptor of Joystick Mouse HID ********************/  
  27.     /* 18 */  
  28.     0x09,         /*bLength: HID Descriptor size*/  
  29.     HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/  
  30.     0x00,         /*bcdHID: HID Class Spec release number*/  
  31.     0x01,  
  32.     0x00,         /*bCountryCode: Hardware target country*/  
  33.     0x01,         /*bNumDescriptors: Number of HID class descriptors to follow*/  
  34.     0x22,         /*bDescriptorType*/  
  35.     JOYSTICK_SIZ_REPORT_DESC,/*wItemLength: Total length of Report descriptor*/  
  36.     0x00,  
  37.     /******************** Descriptor of Joystick Mouse endpoint ********************/  
  38.     /* 27 */  
  39.     0x07,          /*bLength: Endpoint Descriptor size*/  
  40.     USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/  
  41.   
  42.     0x81,          /*bEndpointAddress: Endpoint Address (IN)*/  
  43.     0x03,          /*bmAttributes: Interrupt endpoint*/  
  44.     0x40,          /*wMaxPacketSize: 64 Byte max修改最大包大小为64字节 */  
  45.     0x00,  
  46.     0x0A,          /*bInterval: Polling Interval (10 ms)修改轮询间隔为10ms*/  
  47. /******************** Descriptor of Joystick Mouse endpoint ********************/  
  48.     /* 34 */  
  49.     0x07,          /*bLength: Endpoint Descriptor size*/  
  50.     USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/  
  51.   
  52.     0x01,          /*bEndpointAddress: Endpoint Address (OUT)*/  
  53.     0x03,          /*bmAttributes: Interrupt endpoint*/  
  54.     0x40,          /*wMaxPacketSize: 64 Byte max修改最大包大小为64字节 */  
  55.     0x00,  
  56.     0x20,          /*bInterval: Polling Interval (10 ms) 修改轮询间隔为10ms */  
  57. /*41 */  
  58.   } ; </span><span style="font-family:SimSun;font-size:14px;">  
  59. </span>  

报告描述符

[cpp]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:10px;">const uint8_t Joystick_ReportDescriptor[JOYSTICK_SIZ_REPORT_DESC] =  
  2.   {  
  3.     0x05, 0xFF,          /*Usage Page(User Define)*/  
  4.     0x09, 0xFF,          /*Usage(User Define)*/  
  5.     0xA1, 0x01,          /*Collection(application)*/  
  6.     0x05, 0x01,          /*Usage Page(1)*/  
  7.     0x19, 0x00,          /*Usage Minimum(0)*/  
  8.     0x29, 0xFF,          /*Usage Maximum(255)*/  
  9.     0x15, 0x00,          /*Logical Minimum(0)*/  
  10.     0x25, 0xFF,          /*Logical Maximum(255)*/  
  11.     0x95, 0x40,          /*Report Count(3)*/  
  12.     0x75, 0x08,          /*Report Size(1)*/  
  13. 0x81, 0x02,          /*Input(Data,Var,Abs)*/  
  14. 0x05, 0x02          /*Usage Page(2)*/  
  15. 0x19, 0x00,          /*Usage Minimum(0)*/  
  16.     0x29, 0xFF,          /*Usage Maximum(255)*/  
  17.     0x15, 0x00,          /*Logical Minimum(0)*/  
  18.     0x25, 0xFF,          /*Logical Maximum(255)*/  
  19.     0x95, 0x40,          /*Report Count(64)*/  
  20.     0x75, 0x08,          /*Report Size(8)*/  
  21. 0x91, 0x02,          /*Input(Data,Var,Abs)*/  
  22. 0xc0               /*关集合*/  
  23.   }; /* Joystick_ReportDescriptor */</span><span style="font-family:SimSun;font-size:14px;">  
  24. </span>  

上面我们修改了数组内容,导致数组大小发生变化,所以根据变化做响应修改,在usb_desc.c中

[cpp]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:10px;">#define JOYSTICK_SIZ_CONFIG_DESC                41  
  2. #define JOYSTICK_SIZ_REPORT_DESC                39</span>  

四、修改函数

    修改设备RESET函数Joystick_Reset,这个函数是在RESET中断中被调用,用于端口的初始化。因为我们增加了端点1的输出,修改了包大小,所以要做响应的修改。这个函数位于usb_prop.c中,修改后的函数为

[cpp]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:10px;">void Joystick_Reset(void)  
  2. {  
  3.   /* Set Joystick_DEVICE as not configured */  
  4.   pInformation->Current_Configuration = 0;  
  5.   pInformation->Current_Interface = 0;/*the default Interface*/  
  6.   
  7.   /* Current Feature initialization */  
  8.   pInformation->Current_Feature = Joystick_ConfigDescriptor[7];  
  9.   SetBTABLE(BTABLE_ADDRESS);  
  10.   /* Initialize Endpoint 0 */  
  11.   SetEPType(ENDP0, EP_CONTROL);  
  12.   SetEPTxStatus(ENDP0, EP_TX_STALL);  
  13.   SetEPRxAddr(ENDP0, ENDP0_RXADDR);  
  14.   SetEPTxAddr(ENDP0, ENDP0_TXADDR);  
  15.   Clear_Status_Out(ENDP0);  
  16.   SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);  
  17.   SetEPRxValid(ENDP0);  
  18.   
  19.   /* Initialize Endpoint 1 */  
  20.   SetEPType(ENDP1, EP_INTERRUPT);  
  21.   SetEPTxAddr(ENDP1, ENDP1_TXADDR);  
  22.   SetEPTxCount(ENDP1, 64);//修改大小为64  
  23.   SetEPTxStatus(ENDP1, EP_TX_NAK);  
  24.   
  25.   /* Initialize Endpoint 1 */  
  26.   //SetEPType(ENDP1, EP_INTERRUPT);  
  27.   SetEPTxAddr(ENDP1, ENDP1_RXADDR);  
  28.   SetEPTxCount(ENDP1, 64); //修改大小为64  
  29.   SetEPRxStatus(ENDP1, EP_RX_VALID);  
  30.   /* Set this device to response on default address */  
  31.   SetDeviceAddress(0);  
  32.   bDeviceState = ATTACHED;  
  33. }</span><span style="font-family:SimSun;font-size:14px;">  
  34. </span>  
在上面中ENDP1_RXADDR是我们新加的,需要我们在usb_conf.h中添加对于它的定义
[cpp]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:10px;">/* EP1  */  
  2. /* tx buffer base address */  
  3. #define ENDP1_TXADDR        (0x100)  
  4. #define ENDP1_RXADDR        (0x140)</span><span style="font-family:SimSun;font-size:14px;">  
  5. </span>  
最后我们编写对于USB输出数据的处理函数,即
[cpp]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:10px;">void EP1_OUT_Callback(void)  
  2. {  
  3.     DataLen = USB_SIL_Read(ENDP1,kk);//kk是个64字节的数组  
  4.       
  5.     if(kk[0]&&0x01 == 0x01)  
  6.         LED(LED1,1);  
  7.     else  
  8.         LED(LED1,0);  
  9.     if(kk[0]&&0x02 == 0x02)  
  10.         LED(LED2,1);  
  11.     else  
  12.         LED(LED2,0);  
  13.     if(kk[0]&&0x04 == 0x04)  
  14.         LED(LED3,1);  
  15.     else  
  16.         LED(LED3,0);  
  17.     if(kk[0]&&0x08 == 0x08)  
  18.         LED(LED4,1);  
  19.     else  
  20.         LED(LED4,0);     
  21.     SetEPRxValid(ENDP1);  
  22. }</span><span style="font-family:SimSun;font-size:14px;">  
  23. </span>  

在主函数中我们添加USB IN的相关操作,因为设置的是interrupt端点,所以每过10ms主机就是问询设备是否有数据要发送,我们只需要在stm32的主函数中填装数据即可。具体的while循环中代码是

[cpp]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:10px;">if(GetEPTxStatus(ENDP1)==EP_TX_NAK)  
  2. {  
  3.     if(DataLen !=0)  
  4.     {  
  5.         USB_SIL_Write(ENDP1,kk,DataLen);                
  6.         SetEPTxValid(ENDP1);  
  7.         DataLen=0;  
  8.     }                 
  9. }</span><span style="font-family:SimSun;font-size:14px;">  
  10. </span>  
最后的最后不要忘了在stm32f10x_it.c中添加中断处理

[cpp]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-family:SimSun;font-size:10px;">void USB_LP_CAN1_RX0_IRQHandler(void)  
  2. {  
  3.   USB_Istr();  
  4. }    
  5. void USBWakeUp_IRQHandler(void)  
  6. {  
  7.    EXTI_ClearITPendingBit(EXTI_Line18);  
  8. }</span><span style="font-family:SimSun;font-size:14px;">  
  9. </span>  

至此整个移植过程就完成了,程序实现的功能是,通过电脑给USB设备发送数据,USB设备收到数据,然后再把数据发送回电脑,为了检验USB的发送与接收,使用Labview编写了一个简单的上位机。大概就是这个样子,发送哈哈,收到哈哈。



关于上位机就在下一篇博文里写吧

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值