小白第一次开发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文件只需要如下图所示的几个文件):
就只要提取这些文件,其它的都不需要!
一般地,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;