STM32F407作主机读写U盘(stm32_f105-07_f2_f4_usb-host-device_lib_V2.2.1及FatFs的R0.13C移植)

  • Post author:
  • Post category:其他


小白第一次开发USB,记录下。

开发平台:Keil uVision5

使用的库及原始资料:

1、STM32官方程序:stm32_f105-07_f2_f4_usb-host-device_lib_V2.2.1

用 USB host MSC模式

2、文件系统:FatFs用的是官方R0.13C版。

移植方法如下:

先上一个项目截图(.c文件只需要如下图所示的几个文件):

在这里插入图片描述

.h文件需要如下:

在这里插入图片描述

在这里插入图片描述

就只要提取这些文件,其它的都不需要!

一般地,USB_Host文件夹里的程序不需要改动,FatFs文件夹里的程序也不需要改动。

先修改usb_bsp.c里的void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE * pdev)函数,使自己的硬件USB接口和程序对应。

再配置USB全局中断void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE * pdev)

最后剩下的主要只修改了usbh_usr.c文件里的内容。(我的项目只需要接一个U盘就可以)。——好像也没什么要修改的东西。

开发过程中遇到过的 2个难题:

1、调试初始化函数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),

到其中的HCD_Init(pdev , coreID);就运行不下去了,不知道哪里出了问题…后来打印跟踪调试发现:忘了开例程的TIMER2中断,打开后就OK了。即别忘了写上这个函数(我现在忘了它当时在哪个文件里了。我就是完全采用STM32官方的延时方法)

void TIM2_IRQHandler(void)

{

	USB_OTG_BSP_TimerIRQ();

}

到此就全部Ok!可以读写U盘了!不过我这暂时只能识别2G的U盘,8G和16G 的U盘识别不了,因为时间关系,暂时没有去查找原因(我们项目2G暂时够用)。有知道的朋友请告诉我一声,免得我花时间去查找,谢谢!

2、因为我的项目还需要知道U盘的剩余容量,而官方例程中只有读取总容量,没有读取剩余容量的方法。于是我借鉴原子的例子(主要替换、修改int USBH_USR_MSC_Application(void) 函数)。

但是原子的例子挂载U盘在main的初始化程序里,而我的main函数如下(没有挂载U盘)

int main(void)

{

	peripherals_init();
	xDelay();
	xDelay(); 
	xDelay();
	xDelay();                           //等待LCM屏自身初始化完毕
	init_variable();	
	USBH_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID,&USB_Host, &USBH_MSC_cb, &USR_cb);
	for(;;)
	{ 									
			USBH_Process(&USB_OTG_Core, &USB_Host);
			xDelay();
	}

}

所以在调用函数FRESULT f_getfree (const TCHAR* path,DWORD* nclst,FATFS** fatfs)时总是出错。返回值要么是0x0b,要么是0x0c。我一直以为是自己的PATH写错了(也确实不知道它该是什么)。在网上查了很多资料,觉得自己就一个U盘,应该是默认的0通道。但是把原子例子里的res=exf_getfree(“2:”,&Utotal,&Ufree);改成res=exf_getfree(“0:”,&Utotal,&Ufree); 后还是不对。

最后发现要先挂载U盘,终于成功。

我修改了原子的程序如下:(只用了他这3个函数,其它的全是用的官方程序)

int USBH_USR_MSC_Application(void)

{

	u8 res=0;
	switch(USBH_USR_ApplicationState)
	{
			case USH_USR_FS_INIT:        //初始化文件系统 
					if(f_mount(&fatfs, "", 0) != FR_OK)   //挂载U盘----初始化时必须要有这一步,否正后面无法挂载成功
					{//efs initialisation fails
							printf("> Cannot initialize File System.\r\n");
							return (-1);
					}
					printf("> File System initialized.\r\n");	
					printf("> Disk capacity : %lu Bytes\r\n", USBH_MSC_Param.MSCapacit*USBH_MSC_Param.MSPageLength);					
					printf("开始执行用户程序!!!\r\n");
					USBH_USR_ApplicationState=USH_USR_FS_RW;
					break;
			case USH_USR_FS_RW:	     //执行USB OTG 读写操作程序
					res=USBH_user_App();   //用户主程序
					break;
			default:
					break;
	} 
	return res;

}

//返回值:0—正常;1—有问题

u8 USBH_user_App(void)

{

	u32 Utotal,Ufree;
	u8 res=0;
	printf("设备连接成功!.\r\n");	 				
	res=exf_getfree("0:",&Utotal,&Ufree);		
	if(res==0)
	{	   
			printf("FATFS OK!\r\n");		    
			//printf("U盘总容量(16进制): %04X  MB\r\n",Utotal>>10);     //显示U盘总容量 MB----打印16进制
			//printf("U盘剩余容量(16进制):%04X  MB\r\n",Ufree>>10);	  //U盘剩余容量 MB
			
			printf("U盘总容量(10进制): %04d  MB\r\n",Utotal>>10);     //显示U盘总容量 MB----打印10进制
			printf("U盘剩余容量(10进制):%04d  MB\r\n",Ufree>>10);	  //U盘剩余容量 MB
			
	} 		
	while(HCD_IsDeviceConnected(&USB_OTG_Core))//设备连接成功
	{	
			Toggle_USBLed();
			delay(200);
	} 		
	printf("设备连接中...\r\n");
	return res;

}

u8 exf_getfree(u8 *drv,u32 *total,u32 *free)

{//f_getfree函数获取驱动器上空闲簇的数目

	FATFS *fs1; 
	u8 res; 
	DWORD fre_clust=0, fre_sect=0, tot_sect=0; 
	//得到磁盘信息及空闲簇数量 
	f_mount(&fatfs,"0:",1);        // 重新挂载U盘
	res = f_getfree((const TCHAR*)drv, &fre_clust, &fs1);
	if(res==0) 
	{	    
			tot_sect=(fs1->n_fatent-2)*fs1->csize;	  //得到总扇区数 
			fre_sect=fre_clust*fs1->csize;	               //得到空闲扇区数	    
			#if FF_MAX_SS!=512	  	                            //扇区大小不是512字节,则转换为512字节 
			tot_sect*=(fs1->ssize)/512; 
			fre_sect*=(fs1->ssize)/512; 
			#endif	   
			*total=tot_sect>>1;	                            //单位为KB 
			*free=fre_sect>>1;	                            //单位为KB  
	} 
	return res; 

}

至此,全部OK!

在这里插入图片描述



版权声明:本文为u013121418原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。