stm32的USB(一) 主机模式下对MSC(大容量存储器)的识别

背景:

USB中文名称是通用串行总线,因其具有传输速度快,使用方便,支持热插拔,连接灵活,独立供电等优点而得到广泛应用。但是USB协议非常的复杂,完整的协议就有厚厚的一本,还好ST公司很体贴的提供一整套USB库以及例程,用户只需对其例程稍微修改移植到自己的项目就好。Stm32的MCU有三种带USB功能的IP:

•USB IP

可作为全速或低速的USB设备

存在于STM32F102、STM32F103

•FS OTG IP

可作为全速和低速USB主机

可作为全速USB设备

存在于STM32F105、STM32F107、STM32F2、STM32F4

•HS OTG IP

可作为高速、全速和低速USB主机

可作为高速和全速USB设备

存在于STM32F2、STSM32F4

这里基于USB OTG库做介绍,stm32的usb_otg库可以从http://www.stmcu.org/document/detail/index/id-213011下载。

移植例程:

STM32_USB-Host-Device_Lib_V2.2.0\Project\USB_Host_Examples\MSC

里有我们需要的例程,移植该例程可以实现对U盘、SD卡读卡器等大容量存储进行识别,再配合使用fatfs文件系统就可以对U盘/SD卡进行读写。

要完成移植需要对usb_bsb.c、usbh_usr.c等文件进行修改。usb_bsb.c提供了几个USB库需要用到的底层初始化函数,包括:IO设置、中断设置、VBUS配置以及延时函数等,需要我们自己实现,来看看这里面的几个函数。

void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev)完成对USB所使用的IO口的初始化,包括初始化端口时钟、端口模式等。voidUSB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev)配置USB全局中断。

usbh_usr.c是应用程序软件,用户通过对这个文件进行修改来实现自己的应用,重点介绍USR_cb这个元素为回调函数的结构体和int USBH_USR_MSC_Application(void)这个函数。

USR_cb的定义如下:

USBH_Usr_cb_TypeDef USR_cb =
{
  USBH_USR_Init,
  USBH_USR_DeInit,
  USBH_USR_DeviceAttached,
  USBH_USR_ResetDevice,
  USBH_USR_DeviceDisconnected,
  USBH_USR_OverCurrentDetected,
  USBH_USR_DeviceSpeedDetected,
  USBH_USR_Device_DescAvailable,
  USBH_USR_DeviceAddressAssigned,
  USBH_USR_Configuration_DescAvailable,
  USBH_USR_Manufacturer_String,
  USBH_USR_Product_String,
  USBH_USR_SerialNum_String,
  USBH_USR_EnumerationDone,
  USBH_USR_UserInput,
  USBH_USR_MSC_Application,
  USBH_USR_DeviceNotSupported,
  USBH_USR_UnrecoveredError
    
};

这是一个USBH_Usr_cb_TypeDef USR类型的结构体,USBH_Usr_cb_TypeDef USR的定义是:

typedef struct _USBH_USR_PROP
{
  void (*Init)(void);       /* HostLibInitialized */
  void (*DeInit)(void);       /* HostLibInitialized */  
  void (*DeviceAttached)(void);           /* DeviceAttached */
  void (*ResetDevice)(void);
  void (*DeviceDisconnected)(void); 
  void (*OverCurrentDetected)(void);  
  void (*DeviceSpeedDetected)(uint8_t DeviceSpeed);          /* DeviceSpeed */
  void (*DeviceDescAvailable)(void *);    /* DeviceDescriptor is available */
  void (*DeviceAddressAssigned)(void);  /* Address is assigned to USB Device */
  void (*ConfigurationDescAvailable)(USBH_CfgDesc_TypeDef *,
                                     USBH_InterfaceDesc_TypeDef *,
                                     USBH_EpDesc_TypeDef *); 
  /* Configuration Descriptor available */
  void (*ManufacturerString)(void *);     /* ManufacturerString*/
  void (*ProductString)(void *);          /* ProductString*/
  void (*SerialNumString)(void *);        /* SerialNubString*/
  void (*EnumerationDone)(void);           /* Enumeration finished */
  USBH_USR_Status (*UserInput)(void);
  int  (*UserApplication) (void);
  void (*DeviceNotSupported)(void); /* Device is not supported*/
  void (*UnrecoveredError)(void);

}
USBH_Usr_cb_TypeDef;

用户编写USR_cb里面的回调函数可以实现在插入u盘、拔出u盘时打印相关的提示信息,比如是否连接上了?是否枚举成功了?是否断开了?等等。int USBH_USR_MSC_Application(void)用来实现用户的具体应用,比如配合fatfs文件系统对u盘进行读写等。

以上就是移植过程中需要注意的地方,下面介绍具体怎么实现对u盘的识别。

具体实现:

Stm32usb功能的具体工作都是中断做的,用户要做的只有初始化usb和调用usb进程函数。

void USBH_Init(USB_OTG_CORE_HANDLE *pdev,

              USB_OTG_CORE_ID_TypeDef coreID,

              USBH_HOST *phost,              

              USBH_Class_cb_TypeDef *class_cb,

               USBH_Usr_cb_TypeDef *usr_cb)            

USBH_Init()中调用了上文所说的usb_bsb.c中USB_OTG_BSP_Init()、 USB_OTG_BSP_EnableInterrupt()等函数实现对USB硬件和中断的初始化,并登记用户定义的回调函数。

USBH_Process(&USB_OTG_Core, &USB_Host)这个函数以状态机的方式实现对u盘的识别并分配通道和u盘状态的转换。这个进程函数需要快速不停地调用,以便快速的对usb口状态的改变做出响应。下面是mian函数的一个demo:

int main(void)
{
	USBH_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID,
		&USB_Host, &USBH_MSC_cb, &USR_cb);
	While(1)
	{
		USBH_Process(&USB_OTG_Core, &USB_Host);
		Delay();
	}
}

实现起来是不是很简单?主要工作集中在移植阶段。



你可能感兴趣的:(stm32)