DRESULT disk_read ( BYTE pdrv, /* Physical drive nmuber to identify the drive */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address in LBA */ UINT count /* Number of sectors to read */ ) { DRESULT res; uint8_t result; if(!count){ return RES_PARERR; } switch (pdrv) { case SD_CARD: result = SD_ReadDisk(buff, sector, count); while(result){ SD_Init(); result = SD_ReadDisk(buff, sector, count); } break; default: result = 1; } if (result == 0x00){ return RES_OK; } else{ return RES_ERROR; } }
DRESULT disk_read ( BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address (LBA) */ UINT count /* Number of sectors to read (1..128) */ ) { u8 res; // int result; // int i; if (!count)return RES_PARERR;//count????0,???????? switch (pdrv) { case SDCARD : res=SD_ReadDisk(buff,sector,count); while(res)//??? { SD_Init(); //?????SD? ForDelay_nms(1); res=SD_ReadDisk(buff,sector,count); // printf("sd rd error:%d\r\n",res); } // break; // translate the reslut code here res=RES_OK; return (DRESULT)res; } return RES_PARERR; }
//FAT初始化,不含SD的初始化,用之前应先调用sd的初始化 //返回值:0,初始化成功 // 其他,初始化失败 unsigned char FAT_Init(void)//Initialize of FAT need initialize SD first { bootsector710 *bs = 0; //定义DBR结构体,包含BPB部分(12~90字节是BPB) bpb710 *bpb = 0; //定义BPB结构体 partrecord *pr = 0; //定义硬盘信息 结构休 (16字节) DWORD hidsec=0; //隐藏的扇区数即为DBR在物理扇区的偏移量 long long Capacity; Capacity =(long long)SD_GetSectorCount()*512; //得到SD容量,单位为字节 if(Capacity<0xff)return 1; if(SD_ReadDisk(fat_buffer,0,1))return 2; //读物理扇区0。即MBR(其中MBR内的硬盘分区表中有DBR的地址信息),如没有MBR,则为DBR。经测试,我的SD卡是有MBR的 if(fat_buffer[0]!=0XEB&&fat_buffer[0]!=0XE9) //如物理0扇区第一字节不为0XEB或0XE9,则存在MBR,否则不存在 { //printf("此SD卡的物理扇区0为MBR\n"); pr = (partrecord *)((partsector *)fat_buffer)->psPart;//first partition 第一分区 hidsec=pr->prStartLBA; //隐藏的扇区 即DBR的物理扇区偏移 //printf("此SD卡的DBR的物理扇区为=%d\n",hidsec) ; } else { hidsec=0; //无MBR,物理扇区0即为DBR //printf("此SD卡不存在MBR,物理扇区0即为DBR,物理扇区0即为逻辑扇区0.\n"); } if(SD_ReadDisk(fat_buffer,hidsec,1))return 3; //printf("DBR物理扇区偏移量:%d \n",hidsec); bs = (bootsector710 *)fat_buffer; bpb = (bpb710 *)bs->bsBPB; if(bpb->bpbFATsecs)//detemine thd FAT type do not support FAT12 { FAT32_Enable=0; //FAT16 FATsectors = bpb->bpbFATsecs; //FAT表占用的扇区数 FirstDirClust = 2; } else { FAT32_Enable=1; //FAT32 FATsectors = bpb->bpbBigFATsecs;//FAT占用的扇区数 FirstDirClust = bpb->bpbRootClust; } BytesPerSector = bpb->bpbBytesPerSec; //每扇区字节数 SectorsPerClust = (BYTE)bpb->bpbSecPerClust; //每簇扇区数 FirstFATSector = bpb->bpbResSectors+hidsec; //第一个FAT表扇区 RootDirCount = bpb->bpbRootDirEnts; //根目录项数 RootDirSectors = (RootDirCount*32)>>9; //根目录占用的扇区数 FirstDirSector = FirstFATSector+bpb->bpbFATs*FATsectors; //第一个目录扇区 FirstDataSector = FirstDirSector+RootDirSectors; //第一个数据扇区 //printf("每扇区字节数:%d \n",BytesPerSector); //printf("每簇扇区数:%d \n",SectorsPerClust); //printf("第一个FAT表扇区:%d \n",FirstFATSector); //printf("根目录项数:%d \n",RootDirCount); //printf("根目录占用的扇区数:%d \n",RootDirSectors); return 0; }
//读扇区 //drv:磁盘编号0~9 //*buff:数据接收缓冲首地址 //sector:扇区地址 //count:需要读取的扇区数 DRESULT disk_read ( BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address (LBA) */ UINT count /* Number of sectors to read (1..128) */ ) { u8 res=0; if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误 switch(pdrv) { case SD_CARD://SD卡 res=SD_ReadDisk(buff,sector,count); if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常 { SD_SPI_SpeedLow(); SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟 SD_SPI_SpeedHigh(); } break; default: res=1; } //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值 if(res==0x00)return RES_OK; else return RES_ERROR; }
/******************************************************************************* * Function Name : Read_Memory * Description : Handle the Read operation from the STORAGE card. * Input : None. * Output : None. * Return : None. *******************************************************************************/ int8_t STORAGE_Read (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { int res=0; USB_STATUS_REG|=0X02; res=SD_ReadDisk(buf,blk_addr,blk_len); if(res)USB_STATUS_REG|=0X08;//SD卡读错误! return res; }
DRESULT disk_read ( BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address (LBA) */ UINT count /* Number of sectors to read (1..128) */ ) { u8 res=0; if (!count)return RES_PARERR; switch(pdrv) { #ifdef USE_SD_CARD case SD_CARD: res=SD_ReadDisk(buff,sector,count); while(res) { SD_Init(); res=SD_ReadDisk(buff,sector,count); //printf("sd rd error:%d\r\n",res); } break; #endif case EX_FLASH: for(;count>0;count--) { W25QXX_Read(buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE); sector++; buff+=FLASH_SECTOR_SIZE; } res=0; break; case USB_DISK: res=USBH_UDISK_Read(buff,sector,count); break; default: res=1; } if(res==0x00)return RES_OK; else return RES_ERROR; }
//读扇区 //drv:磁盘编号0~9 //*buff:数据接收缓冲首地址 //sector:扇区地址 //count:需要读取的扇区数 DRESULT disk_read ( BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address (LBA) */ UINT count /* Number of sectors to read (1..128) */ ) { u8 res=0; if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误 switch(pdrv) { case SD_CARD://SD卡 res=SD_ReadDisk(buff,sector,count); while(res)//读出错 { SD_Init(); //重新初始化SD卡 res=SD_ReadDisk(buff,sector,count); //printf("sd rd error:%d\r\n",res); } break; #if SPIFlash case EX_FLASH://外部flash for(;count>0;count--) { W25QXX_Read(buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE); sector++; buff+=FLASH_SECTOR_SIZE; } res=0; break; #endif default: res=1; } //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值 if(res==0x00)return RES_OK; else return RES_ERROR; }
int main(void) { u32 sector_size; u8 t=0; SystemInit(); delay_init(72); //延时初始化 NVIC_Configuration(); uart_init(9600); LED_Init(); KEY_Init(); LCD_Init(); POINT_COLOR=RED;//设置字体为红色 LCD_ShowString(60,50,"Mini STM32"); LCD_ShowString(60,70,"SD Card TEST"); LCD_ShowString(60,90,"ATOM@ALIENTEK"); LCD_ShowString(60,110,"2011/1/1"); while(SD_Initialize()!=0)//检测不到SD卡 { LCD_ShowString(60,130,"SD Card Failed!"); delay_ms(500); LCD_ShowString(60,130,"Please Check! "); delay_ms(500); LED0=!LED0;//DS0闪烁 } //检测SD卡成功 LCD_ShowString(60,130,"SD Card Checked OK "); sector_size=SD_GetSectorCount(); printf(" SD Sector Size:%x\n",sector_size); LCD_ShowString(60,150,"SD Card Size: Mb"); LCD_ShowNum(164,150,sector_size>>12,4,16); while(1) { if(t==30)//每6s钟执行一次 { if(SD_ReadDisk(buf,0,1)==0)//读取MBR扇区 { LCD_ShowString(60,170,"USART1 Sending Data..."); printf("SECTOR 0 DATA:\n"); for(sector_size=0;sector_size<512;sector_size++)printf("%x ",buf[sector_size]);//打印MBR扇区数据 printf("\nDATA ENDED\n"); LCD_ShowString(60,170,"USART1 Send Data Over!"); } t=0; } t++; delay_ms(200); LED0=!LED0; } }
//读取512个字节 //FileInfo:要读取的文件 //buf :数据缓存区 //返回值 :0,操作失败,1,操作成功 unsigned char F_Read(FileInfoStruct *FileInfo,u8 *buf) { DWORD sector; sector=fatClustToSect(FileInfo->F_CurClust);//得到当前簇号对应的扇区号 if(SD_ReadDisk(buf,sector+FileInfo->F_Offset,1))return 0;//读数错误 FileInfo->F_Offset++; if(FileInfo->F_Offset==SectorsPerClust) //簇的尽头,换簇 { FileInfo->F_Offset=0; FileInfo->F_CurClust=FAT_NextCluster(FileInfo->F_CurClust);//读取下一个簇号 if((FAT32_Enable==0&&FileInfo->F_CurClust==0xffff) \ ||FileInfo->F_CurClust==0x0ffffff8||FileInfo->F_CurClust == 0x0fffffff)return 0;//error } return 1;//读取成功 }
/******************************************************************************* * 函数名:主函数 * 功 能: * 参 数: * 返 回: *******************************************************************************/ int main(void) { SystemInit(); Delay_init(72); NVIC_Configuration(); USART1_Init(9600); Delayms(5000); while( SD_Initialize() != 0 ) { USART1_PrintString("SD Initialize Fail \r\n"); } USART1_PrintString("SD Initialize OK \r\n"); sector_num = SD_GetSectorNum(); USART1_PrintString("The SD sector num is: "); USART1_PrintChar(sector_num>>24); USART1_PrintChar(sector_num>>16); USART1_PrintChar(sector_num>>8); USART1_PrintChar(sector_num>>0); USART1_PrintString("\r\n"); USART1_PrintString("The SD size is: "); sector_num >>= 12; USART1_PrintChar(sector_num>>24); USART1_PrintChar(sector_num>>16); USART1_PrintChar(sector_num>>8); USART1_PrintChar(sector_num>>0); if( 0 == SD_WriteDisk(buf1, 1, 1) ) { USART1_PrintString("Write OK \r\n"); } while(1) { Delayms(4000); if(0 == SD_ReadDisk(buf,0,2)) { for(n=0; n<1024; n++) { USART1_PrintChar(buf[n]); } } } }
DRESULT disk_read ( BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address (LBA) */ BYTE count /* Number of sectors to read (1..128) */ ) { DRESULT res; int result; if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误 switch (pdrv) { case SD_CARD : // translate the arguments here result = SD_ReadDisk(buff, sector, count); // translate the reslut code here if (result == SD_OK)res = RES_OK; return res; // case MMC : // // translate the arguments here // result = MMC_disk_read(buff, sector, count); // // translate the reslut code here // return res; // case USB : // // translate the arguments here // result = USB_disk_read(buff, sector, count); // // translate the reslut code here // return res; } return RES_PARERR; }
//在SD卡上的FAT表中查找下一簇号 //cluster:当前簇号 //返回值:0x0ffffff8,表示没有后续簇了 // 其他值,下一簇号 unsigned long FAT_NextCluster(unsigned long cluster) { DWORD sector; DWORD offset; if(FAT32_Enable)offset = cluster/128;//FAT32的FAT表中,用四个字节表示一个簇地址.512/4=128 else offset = cluster/256; //FAT16的FAT表中,用两个字节表示一个簇地址.512/2=256 if(cluster<2)return 0x0ffffff8; //簇0,1不能用于存放 sector=FirstFATSector+offset;//计算该簇实际所在扇区 if(SD_ReadDisk(fat_buffer,sector,1))return 0x0ffffff8;//读取FAT表,发生错误是返回0x0ffffff8 if(FAT32_Enable) { offset=cluster%128;//计算在扇区内的偏移 sector=((unsigned long *)fat_buffer)[offset];//u32 } else { offset=cluster%256;//计算在扇区内的偏移 sector=((unsigned short *)fat_buffer)[offset];//u16 } return (unsigned long)sector;//return the cluste number }
//查找系统文件 //在指定目录下,找寻一个指定类型的指定名字的文件 //cluster:文件夹的簇号!!! //Name :文件的名字 //type :文件类型 //返回值 :该文件的详细信息/如果 FileInfo.F_StartCluster=0 则说明此次寻找失败 FileInfoStruct F_Search(u32 cluster,unsigned char *Name,u32 type) { DWORD sector; DWORD tempclust; unsigned char cnt; unsigned int offset; direntry *item = 0; FileInfoStruct FileInfo; if(cluster==0 && FAT32_Enable==0)//FAT16根目录读取 { for(cnt=0;cnt<RootDirSectors;cnt++) { if(SD_ReadDisk(fat_buffer,FirstDirSector+cnt,1)) { FileInfo.F_StartCluster=0;//读数错误 return FileInfo; } for(offset=0;offset<512;offset+=32) { item=(direntry *)(&fat_buffer[offset]);//指针转换 //找到一个可用的文件 if((item->deName[0] != 0x00) && (item->deName[0] != 0xe5))//找到一个合法文件 { if(item->deAttributes != AM_LFN)//忽略长文件名 { CopyDirentruyItem(&FileInfo,item);//复制目录项,提取详细信息 if(FileInfo.F_Type&type)//找到一个合适的类型了 { // //printf("File Name:%s\n",FileInfo.F_Name); //找到了文件,返回这个文件的首簇 if(mystrcmp(Name,FileInfo.F_Name)) { return FileInfo; } } LongNameFlag=0;//清空长文件名 } } } } }else//其他文件夹/FAT32系统 { tempclust=cluster; while(1) { sector=fatClustToSect(tempclust); for(cnt=0;cnt<SectorsPerClust;cnt++) { if(SD_ReadDisk(fat_buffer,sector+cnt,1)) { FileInfo.F_StartCluster=0;//读数错误 return FileInfo; } for(offset=0;offset<512;offset+=32) { item=(direntry *)(&fat_buffer[offset]); if((item->deName[0] != 0x00) && (item->deName[0] != 0xe5)) { if(item->deAttributes != AM_LFN) //忽略长文件名 { CopyDirentruyItem(&FileInfo,item);//复制目录项,提取详细信息 if(FileInfo.F_Type&type)//找到一个合适的类型了 { /* //printf("F_Info->F_Name:%s\n",FileInfo.F_Name); //printf("F_Info->F_Type:%d\n",FileInfo.F_Type); //printf("F_Info->F_Size:%d\n",FileInfo.F_Size); //printf("F_Info->F_StartClusterH:%x\n",FileInfo.F_StartCluster>>8); //printf("F_Info->F_StartClusterL:%x\n\n",FileInfo.F_StartCluster&0xff); */ //找到了文件,返回这个文件的首簇 if(mystrcmp(Name,FileInfo.F_Name)) { return FileInfo; } } LongNameFlag=0;//清空长文件名 } } } } tempclust=FAT_NextCluster(tempclust);//查找下一个簇号 if(tempclust==0x0fffffff||tempclust==0x0ffffff8 ||(FAT32_Enable==0&&tempclust==0xffff))break; } } FileInfo.F_StartCluster=0;//读数错误 return FileInfo; }
//浏览目标文件夹下面的一个文件类 //dir_clust:当前目录所在簇号 //FileInfo :目标文件的实体对象(FileInfoStruct体) //type :要查找的文件类型:1<<0,mp1;1<<1,mp2;1<<2,mp3;1<<3,mp4;1<<4,m4a;1<<5,3gp; // 1<<6,3g2;1<<7,ogg;1<<8,acc;1<<9,wma;1<<10,wav;1<<11,mid; // 1<<12,flac;1<<13,lrc;1<<14,txt;1<<15,c;1<<16,h;1<<17,file; // 1<<18,fon;1<<19,sys;1<<20,bmp;1<<21,jpg;1<<22,jpeg; //count :0,返回当前目录下,该类型文件的个数;不为零时,返回第count个文件的详细信息 //返回值 :1,操作成功.0,操作失败 u8 Get_File_Info(u32 dir_clust,FileInfoStruct *FileInfo,u32 type,u16 *count) { DWORD sector; DWORD cluster=dir_clust; DWORD tempclust; unsigned char cnt; unsigned int offset; unsigned short cont=0;//文件索引标志 <65536 unsigned char j; //long name fat_buffer offset; unsigned char *p;//long name fat_buffer pointer direntry *item = 0; winentry *we =0; cont=0; LongNameFlag = 0;//清空长文件名标志 //SD_Init();//初始化SD卡,在意外拔出之后可以正常使用 //goto SD; if(cluster==0 && FAT32_Enable==0)//FAT16根目录读取 { for(cnt=0;cnt<RootDirSectors;cnt++) { if(SD_ReadDisk(fat_buffer,FirstDirSector+cnt,1))return 0;//读数错误 for(offset=0;offset<512;offset+=32) { item=(direntry *)(&fat_buffer[offset]);//指针转换 //找到一个可用的文件 if((item->deName[0]!=0x2E)&&(item->deName[0]!=0x00)&&(item->deName[0]!=0xe5) ||((item->deName[0]==0x2E)&&(item->deName[1]==0x2E)))//找到一个合法文件.忽略".",使用".." { if(item->deAttributes == 0x0f)//找到一个长文件名 { we = (winentry *)(&fat_buffer[offset]); j = 26 *( (we->weCnt-1) & WIN_CNT);//长文件名的长度 if(j<MAX_LONG_NAME_SIZE-25) { p = &LongNameBuffer[j];//偏移到目标地址 for (j=0;j<10;j++) *p++ = we->wePart1[j]; for (j=0;j<12;j++) *p++ = we->wePart2[j]; for (j=0;j<4;j++) *p++ = we->wePart3[j]; if (we->weCnt & 0x40) (*(unsigned int *)p) = 0; if ((we->weCnt & WIN_CNT) == 1) LongNameFlag = 1;//最后一个长文件项找到了 } }else { if(type&FileType_Tell(item->deExtension))//找到一个目标文件 { cont++;//文件索引增加 } //查找该目录下,type类型的文件个数 if(*count&&cont==*count) { ////printf("\ncount:%d",*count); CopyDirentruyItem(FileInfo,item);//复制目录项,提取详细信息 return 1;//找到目标文件成功 } LongNameFlag=0;//清空长文件名 } } } } } else//其他文件夹/FAT32系统 { tempclust=cluster; while(1) { sector=fatClustToSect(tempclust); for(cnt=0;cnt<SectorsPerClust;cnt++) { if(SD_ReadDisk(fat_buffer,sector+cnt,1))return 0; for(offset=0;offset<512;offset+=32) { item=(direntry *)(&fat_buffer[offset]); if((item->deName[0]!=0x2E)&&(item->deName[0]!=0x00)&&(item->deName[0]!=0xe5) ||((item->deName[0]==0x2E)&&(item->deName[1]==0x2E)))//找到一个合法文件.忽略".",使用".." { if(item->deAttributes == 0x0f) //得到一个长文件名 { we = (winentry *)(&fat_buffer[offset]); j = 26 *( (we->weCnt-1) & WIN_CNT); if(j<MAX_LONG_NAME_SIZE-25) { p = &LongNameBuffer[j];//p指向长文件名的存放地址 for (j=0;j<10;j++) *p++ = we->wePart1[j]; for (j=0;j<12;j++) *p++ = we->wePart2[j]; for (j=0;j<4;j++) *p++ = we->wePart3[j]; if (we->weCnt & 0x40) (*(unsigned int *)p) = 0; if ((we->weCnt & WIN_CNT) == 1) LongNameFlag = 1; } } else { if(type&FileType_Tell(item->deExtension))//找到一个目标文件 { cont++;//文件索引增加 } //查找该目录下,type类型的文件个数 if(*count&&cont==*count) { CopyDirentruyItem(FileInfo,item);//复制目录项,提取详细信息 return 1;//找到目标文件成功 } LongNameFlag=0;//清空长文件名 } } } } tempclust=FAT_NextCluster(tempclust);//查找下一个簇号 if(tempclust==0x0fffffff||tempclust==0x0ffffff8 ||(FAT32_Enable==0&&tempclust==0xffff))break; } } if(*count==0) { *count=cont;//得到总共文件数目 return 1; //操作成功,找到cont个符合条件的文件了 }else return 0; //操作失败,没找到文件,或者出错 }