好久没有写过任何东西了,这篇文章送给所有纠结在STM32F107 USB开发上的童鞋。
在STM32F107的官方库中,已经给好了USB的开发库,直接调用就可以。在使用之前,我们需要做一些了解。请参照文档《USB-FS-Device development kit.pdf》。
文档下载地址:http://download.csdn.net/detail/wwdlk/5122909
有了库,我们就可以很容易的做出一个像模像样的USB自定义设备的开发。
以下,以自定义bulk设备为例说明。
我也懒得写太多代码,直接改动USB-Mass_Storage-SD Card例程,例程下载地址http://download.csdn.net/detail/wwdlk/4704371。
1、描述符。
USB设备的描述符,是整个USB开发的核心,关系到上位机能否识别USB设备并加载相应USB驱动。
我要做一个VID为0x8886,PID为0x0001的自定义设备。
const uint8_t MASS_DeviceDescriptor[MASS_SIZ_DEVICE_DESC] = { 0x12, /* bLength */ 0x01, /* bDescriptorType */ 0x00, /* bcdUSB, version 2.00 */ 0x02, 0xFF, /* bDeviceClass :>0xFF表示自定义设备 */ 0x00, /* bDeviceSubClass */ 0x00, /* bDeviceProtocol */ 0x40, /* bMaxPacketSize0 0x40 = 64 */ 0x86, /* idVendor 自己定义的VID(8888) */ 0x88, 0x01, /* idProduct 自己定义的PID(0001)*/ 0x00, 0x00, /* bcdDevice 2.00*/ 0x02, 1, /* index of string Manufacturer */ /**/ 2, /* index of string descriptor of product*/ /* */ 3, /* */ /* */ /* */ 0x01 /*bNumConfigurations */ }; const uint8_t MASS_ConfigDescriptor[MASS_SIZ_CONFIG_DESC] = { 0x09, /* bLength: Configuation Descriptor size */ 0x02, /* bDescriptorType: Configuration */ MASS_SIZ_CONFIG_DESC, /*这里应该是32 */ 0x00, 0x01, /* bNumInterfaces: 1 interface */ 0x01, /* bConfigurationValue: */ /* Configuration value */ 0x00, /* iConfiguration: */ /* Index of string descriptor */ /* describing the configuration */ 0xC0, /* bmAttributes: */ /* bus powered */ 0x32, /* MaxPower 100 mA */ /******************** Descriptor of Mass Storage interface ********************/ /* 09 */ 0x09, /* bLength: Interface Descriptor size */ 0x04, /* bDescriptorType: */ /* Interface descriptor type */ 0x00, /* bInterfaceNumber: Number of Interface */ 0x00, /* bAlternateSetting: Alternate setting */ 0x02, /* bNumEndpoints*/ 0x00, /* bInterfaceClass:这里为0x00*/ 0x00, /* bInterfaceSubClass : 这里为0x00*/ 0x00, /* nInterfaceProtocol */ 0x00, /* iInterface: */ /* 18 */ 0x07, /*Endpoint descriptor length = 7*/ 0x05, /*Endpoint descriptor type */ 0x81, /*Endpoint address (IN, address 1) IN端口,地址为1*/ 0x02, /*Bulk endpoint type */ 0x40, /*Maximum packet size (64 bytes) */ 0x00, 0x00, /*Polling interval in milliseconds */ /* 25 */ 0x07, /*Endpoint descriptor length = 7 */ 0x05, /*Endpoint descriptor type */ 0x02, /*Endpoint address (OUT, address 2)OUT端口,地址为2 */ 0x02, /*Bulk endpoint type */ 0x40, /*Maximum packet size (64 bytes) */ 0x00, 0x00 /*Polling interval in milliseconds*/ /*32*/ };如果说对USB描述符不了解,请参考http://www.baiheee.com/Documents/090518/090518112619.htm
2、FW侧USB通信接口。
细心的代码阅读着会发现,库中有一下函数:
uint32_t USB_SIL_Init(void); uint32_t USB_SIL_Write(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize); uint32_t USB_SIL_Read(uint8_t bEpAddr, uint8_t* pBufferPointer);
USB_SIL_Init USB初始化函数。
USB_SIL_Write向USB IN buffer中写数据。
USB_SIL_Read 从USB OUT buffer中读数据。
就这么简单。USB_SIL_Read和USB_SIL_Write就是USBbulk通讯的主要函数了。在USB初始化完成后就可以使用。具体怎么用,请参考库函数说明。
3、USB通讯接口调用时机
有人会疑问,我不知道什么时机调用,没关系,刚开始我也不知道。
STM32_USB-FS-Device_Lib 中,在完成一包数据的接收后、在发送一包数据结束后,会调用相应的callback函数。callback原理请参考实际代码。(注意,不是STM32_USB-Host-Device_Lib_V2.1.0库,此库的使用另有方法)。
/******************************************************************************* * Function Name : EP1_IN_Callback * Description : EP1 IN Callback Routine * Input : None. * Output : None. * Return : None. *******************************************************************************/ void EP1_IN_Callback(void) { // 段点1 IN callback函数,假如需要在发送完成一包数据后,有后续操作,请在这里添加代码。 } /******************************************************************************* * Function Name : EP2_OUT_Callback. * Description : EP2 OUT Callback Routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void EP2_OUT_Callback(void) { //段点2 OUT callback函数,在接收到一包数据后,走这里。可以在这里读取USB数据。 }
总体来说,FW侧在USB库的帮助下,最基本的收发都可以完成了。
差一点忘了,因为改的是USB-Mass_Storage-SD Card例程,所以,usb_prop.c文件中带Bot和CBW字样的句子,都可以删除了。
-----------------------------------------------------------------------------------------
个人觉得,很多工作USB库都给做了,中断不用自己定义,中断处理不用自己写。改好描述符后,只要轻松调用读写接口,再加上您需要的处理,USB模块就这么搞定了。
以上方法是在金牛板STM32F107VC板子上摸索出来的。深入了解还需要靠自己阅读代码来完成。有问题请指点。