用文件系统获取SD卡总容量 已用容量 可用容量

先看结果吧。下面分别开发板上实现的效果和电脑上插上SD卡的效果截图。

FatFs容量1

电脑上读取的SD卡容量

怎么样?数字丝毫不差吧?

买了开发板的朋友,还等什么,猛击下面的链接下载源程序吧。拿出你的SD卡试试,我只有2G的和8G的卡,都没有问题,按道理最大支持32G的卡。哪位朋友有64G以上的卡,试完结果以后请在留言框里面告知我一声结果,瑞生在这里先谢了。

点击下载源程序:模拟WIN7显示SD卡容量

下面详解实现原理:

程序移植目前为止的最新版FatFs(0.10c版本)。挂载了文件系统以后,总的容量就已经知道了,然后再执行一下f_getfree()函数,可用容量就知道了。总的容量减去可用容量就是已用容量,用已用容量和总容量就可以做仿WIN7电脑硬盘的“已使用进度条”了。

原理听起来很简单吧。

获取容量的函数如下所示:

BYTE GET_FreeCAP(void)
{
  FATFS fs;
  FATFS *pfs;
  DWORD fre_clust;
  BYTE res;

  pfs=&fs;
  f_mount(&fs, "" , 1); // 挂载文件系统

  res = f_getfree("", &fre_clust, &pfs);
  if (res) return res; // 如果f_getfree函数执行错误,返回错误值
  else // 如果成功获得容量
  {
    TOT_SIZE = (pfs->n_fatent - 2) * pfs->csize/2; //总容量 单位byte
    FRE_SIZE = fre_clust * pfs->csize/2; // 可用容量 单位byte
  }
  f_mount(0, 0, 1); //卸载文件系统
  return 0;
}

FatFs 0.10版本的挂载文件系统函数f_mount较之前的有变化,参数由原来的2个变为3个,路径不能直接写0了,要写成””或者”0:”,最后一个参数1,表示是否立即挂载文件系统,1就立即挂载,0是稍后挂载。

TOT_SIZE和FRE_SIZE是定义的全局变量,用来放总容量和可用容量,注意最后的单位是字节(byte),如果要转换成MB,就要除以1024,如果要转换成GB,就再除以1024。

进度条实现起来也简单,就是“已用容量”占“总容量”的百分比。

主函数如下所示:

int main()
{
  double fraction, integer;
  double temp;
  uint16_t jindu=0;

  LCD_Init(); // 液晶显示器初始化
  W25Q16_Init(); // W25Q16初始化
  LCD_Clear(WHITE); // 全屏显示白色

  /*----- 检测并初始化SD卡 ------*/
  while(SD_Init()!=0)//循环检测SD卡是否存在
  {
    LCD_ShowString(20,60,"没有检测到SD卡");
    delay_main();
  }

  GET_FreeCAP();
  LCD_ShowString(20,10,"可移动磁盘:");
  LCD_DrawRectage(20,30,220,50,GRAY); // 画进度条边框
  LCD_Fill(21 ,31 ,219,49,LGRAY); // 填充底色
  jindu = (TOT_SIZE-FRE_SIZE)*200/TOT_SIZE;
  LCD_Fill(21 ,31 ,jindu+21,49,DARKBLUE); // 填充已用进度
  POINT_COLOR = BLACK;

  // 计算可用容量
  temp = (double)FRE_SIZE/1024/1024;
  fraction = modf(temp, &integer);
  // 结果保留2位,观察第3位大于5就进1,小于5就不进1
  if(((uint16_t)(fraction*1000)%10)<5) fraction = fraction*100;
  else fraction = fraction*100 + 1;
  LCD_ShowNum(20,55,integer,3); // 这个显示数字,会把前面的0去掉
  LCD_ShowChar(44,55,'.');
  LCD_ShowNumDZ(52,55,fraction,2); // 这个显示数字,不会去掉前面的0,
  LCD_ShowString(68,55,"GB可用,");

  //计算总容量
  LCD_ShowString(132,55,"共 GB");
  temp = (double)TOT_SIZE/1024/1024;
  fraction = modf(temp, &integer);
  // 结果保留2位,观察第3位大于5就进1,小于5就不进1
  if(((uint16_t)(fraction*1000)%10)<5) fraction = fraction*100;
  else fraction = fraction*100 + 1;
  LCD_ShowNum(148,55,integer,3);
  LCD_ShowChar(172,55,'.');
  LCD_ShowNumDZ(180,55,fraction,2);

  while(1)
  {
    ;
  }
}

程序中用到了modf函数,用来提取转换成GB以后的小数和整数。使用此函数,需要调用头文件math.h。例如一个数12.345,利用modf提取出小数和整数以后,整数为12,小数为0.345,所以程序中由把小数乘了100,结果保留2位小数,为了结果准确,判断小数点后面的第三位,采用四舍五入,来保留2位小数点后面的数。