ST MCU Finder
安装免费手机应用,
寻找理想的ST MCU

[STM32F4] 傻瓜式开发USB:STM32F407作主机读写U盘

[复制链接]
417|7
 楼主 | 2019-9-20 14:23 | 显示全部楼层 |阅读模式
本帖最后由 无为之益 于 2019-9-20 16:49 编辑

小白第一次开发USB,现在初步能用STM32读写U盘。本人经常请教大家,现在也为论坛贡献点力量。
该方法简单易移植,初次接触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文件只需要如下图所示的几个文件):


1.png
.h文件需要如下:
2.png
3.png


就只要提取这些文件,其它的都不需要!
一般地,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();                           //等待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.MSCapacity *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;

}


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!(没有优化)

4.png








使用特权

评论回复
| 2019-9-20 15:21 | 显示全部楼层
这个学习下。。。

使用特权

评论回复
| 2019-9-20 22:14 | 显示全部楼层

使用特权

评论回复
| 2019-10-15 12:12 | 显示全部楼层
非常感谢楼主分享

使用特权

评论回复
| 2019-10-15 12:15 | 显示全部楼层
非常感谢楼主分享

使用特权

评论回复
| 2019-10-15 12:16 | 显示全部楼层
非常感谢楼主分享

使用特权

评论回复
| 2019-10-15 12:42 | 显示全部楼层
非常感谢楼主分享

使用特权

评论回复
| 2019-10-15 12:48 | 显示全部楼层
非常感谢楼主分享

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表