SD卡已经看了两天了,主要是因为测试出来的卡容量不对,所以一直找原因,最终还是发现了,总比不过是单位上面出现了问题,或许是之前没有接触到SD的缘故吧,所以对其中的一些寄存器很不了解,一切都是重新开始,对照这寄存器手册,理解程序,修改程序。一步步还是总结一下!

首先关于SD卡的协议是有必要了解的,我今天花了一上午的课堂时间来理解这个SD卡的协议,就是基于这个文档的,这个文档很适合入门SD协议的(个人认为)。http://download.csdn.net/detail/king_bingge/5218183

初识SD之后,就可以开始正式学习SD卡了!

一、要使用SD卡,那么首先肯定得对SD卡进行初始化,那么如何进行初始化呢?(命令的参数暂且不提)

1、这里涉及到很多指令了。协议规定了在给SD卡上电之后需要给出至少74个时钟脉冲后,才能进行相关的SD初始化工作,虽然是这么说,但是我不给74个时钟,他照样能初始化,看看。

;i<;i++)SD_SPI_ReadWriteByte(0XF);

但是,或许为了能够更加成功的初始化吧,所以有这个规定所以,我们还是规规矩矩的好,给它74个时钟,没关系的嘛!

2、然后就是协议中说到当我们复位或者上电的时候,SD卡的SD控制寄存器处于卡识别模式中的空闲模式的,暂且这样称吧。本来我们是不需要发送复位命令了的,但是我们不知道我们的SD所支持的电压范围。所以,我们最好还是先给出一条复位指令,然后紧接着一条获取工作电压的指令,这样也是比较保险,如果多SD卡工作电压有疑问的,那么就得去看芯片手册了。有了这个知识,那下面的代码就不成问题了

retry=;
    do
    {
        r1=SD_SendCmd(CMD0,,0x95);//进入IDLE状态
    }while((r1!=0X01) && retry--);
     SD_Type=;    //默认无卡
    if(r1==0X01)
    {
        )  //SD V2.0
        {
            ;i<;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);    //Get trailing return value of R7 resp
            ]==]==0XAA)              //卡是否支持2.7~3.6V

3、协议上还提到ACMD41命令的目的是给予 SD卡控制器一个识别 SD卡是否可以在所给Vdd 范围下工作的机制,如果 SD 卡无法在指定 Vdd 范围内工作,则它会进入非活动状态(Inactive state ),所以我们接下来需要发送这个命令,但是在发送这个命令之前,要知道这是一个应用型的命令,所以要加上CMD55命令,所以有了下面的代码。

]==]==0XAA)//卡是否支持2.7~3.6V
    {
        retry=0XFFFE;
        do
        {
            SD_SendCmd(CMD55,,0X01);    //发送CMD55
            r1=SD_SendCmd(CMD41,0x40000000,0X01);//发送CMD41
        }while(r1&&retry--);
        ,)//鉴别SD2.0卡版本开始        //获取供电状态
        {
            ;i<;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);//得到OCR值
            ]&0x40)SD_Type=SD_TYPE_V2HC;    //检查CCS
            else SD_Type=SD_TYPE_V2;
        }

这样就获取了卡的类型了,至此卡的初始化基本完成,当然根据协议上,我们还可以在这里修改相对地址之类的。如果有必要的话,可以这样做!

二、初始化完SD卡,接下来如果你想查看我们SD的容量,可以这样做!

之前就是因为卡容量的问题,所以郁闷了好久,理解了个大概!注意这里函数名是读取扇区数,实际上返回的值是我们卡的容量,这里得注意了。

1、首先看代码

u32 SD_GetSectorCount(void)
{
    u8 csd[];
    u32 Capacity_KB,Capacity_MB ;
    u8 n;
        u16 csize;
    //取CSD信息,如果期间出错,返回0
    ) ;
        n = (csd[] & ) + ((csd[] & ) >> ) + ((csd[] & ) << ) + ;
        csize = (csd[] >> ) + ((u16)csd[] << ) + ((u16)(csd[] & ) << ) + ;

        Capacity_KB= (u32)csize << (n - );//得到扇区数 ,这里的单位是KB
        Capacity_MB = Capacity_KB/;
    return Capacity_MB;
}

这个计算的问题必须得看SD卡的手册,也就是128位的CSD寄存器。这里我把我分析的过程贴出来,我不得不说比较乱,或许只有我自己能看懂了,懒得整理了,仅供参考!

//My SD_Card
//CSD寄存器中的值如下:
 7f ff     bit(-)            csd0 - csd3
5f   cb    bit(--)            csd4 - csd7
 db df ff    bit(--)            csd8 - csd11
       bit(---)            csd12 -csd15

csize  {,}
csize_muti{,}
read {,}
csize =    =
csize_muti =  =
read =  =
//计算公式:
//blocknr = (csize+1)*mult    =
//mult = (csize_muti < 8)*(2^(csize_muti + 2))
//block_len = (read < 12)*(2^(read))
//capacity = blocknr * block_len = 13*4*3516*98304
//依据下面代码来计算我的容量:
        n = (csd[] & ) + ((csd[] & ) >> ) + ((csd[] & ) << ) + ;
        csize = (csd[] >> ) + ((u16)csd[] << ) + ((u16)(csd[] & ) << ) + ;

        Capacity_KB= (u32)csize << (n - );//得到扇区数 ,这里的单位是KB  // 00 7f ff 32 5f 59 83 cb  76 db df ff 96 40 00 97
        Capacity_MB = Capacity_KB/;

        //1、(csd[8] >> 6) 得到的是 bit62和bit63的值                去掉2位
        //2、((u16)csd[7] << 2)得到的是bit64--bit69的值            去掉6位
        //3、((u16)(csd[6] & 3) << 10)得到的是bit70--bit73的值    
 

其实我的问题还是出现在单位上面!

这样我们就能看到显示的容量值了,我的是1G的。打印出来是971M,和windows下面的是一致的。其实我们可以通过读SD卡的引导扇区,从而把相关的信息读取出来,而不需要使用那些个寄存器。那么现在我们的计算公式就是(这只是我自己信手写的,如果想要理解,你必须得看扇区的内容咯,我就是对照着那个MBR来写的)

  x=(((buf_read[])**+(buf_read[])*+(buf_read[])))*//;    //打印大小
  printf("\n SD Sector Size:%d  Mb\n",x);

虽然不怎么雅观,但是能用就是了。

2、接下来看如何用SPI读一个扇区吧,先看代码

u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
{
    u8 r1;
    ;//转换为字节地址
    )
    {
        r1=SD_SendCmd(CMD17,sector,0X01);//读命令
        )//指令发送成功
        {
            r1=SD_RecvData(buf,);//接收512个字节
        }
    }else
    {
        r1=SD_SendCmd(CMD18,sector,0X01);//连续读命令
        do
        {
            r1=SD_RecvData(buf,);//接收512个字节
            buf+=;
        });
        SD_SendCmd(CMD12,,0X01);    //发送停止命令
    }
    SD_DisSelect();//取消片选
    return r1;//
}

这几行代码能实现单个和多个扇区的读写,跟踪进去可以能够看到这个函数

//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPIx_ReadWriteByte(u8 TxData)
{
    u8 retry=;
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
        {
        retry++;
        );
        }
    SPI_I2S_SendData(SPI1, TxData);                                                              //通过外设SPIx发送一个数据
    retry=;

    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); //检查指定的SPI标志位设置与否:接受缓存非空标志位
        {
        retry++;
        );
        }
    return SPI_I2S_ReceiveData(SPI1);                                                                 //返回通过SPIx最近接收的数据
}

这个函数的功能实现了既可以进行发送又可以进行读取数据,现在来总结一下!

读一个扇区的过程

1、先发命令r1=SD_SendCmd(CMD17,sector,0X01);//读单个扇区的命令

2、然后将接收到得数据存在临时数组里面

u8 SD_RecvData(u8*buf,u16 len)
{
    ;//等待SD卡发回数据起始令牌0xFE
    while(len--)//开始接收数据
    {
        *buf=SPIx_ReadWriteByte(0xFF);
        buf++;
    }
    //下面是2个伪CRC(dummy CRC)
    SD_SPI_ReadWriteByte(0xFF);
    SD_SPI_ReadWriteByte(0xFF);
    ;//读取成功
}

那么对应的写扇区也类似的

1、先发写单个扇区的命令 r1=SD_SendCmd(CMD24,sector,0X01);//写命令

2、将Buffer里面的内容写到对应的扇区里面去

u8 SD_SendBlock(u8*buf,u8 cmd)
{
    u16 t;
    ;//等待准备失效
    SD_SPI_ReadWriteByte(cmd);
    if(cmd!=0XFD)//不是结束指令
    {
        ;t<;t++)SPIx_ReadWriteByte(buf[t]);//提高速度,减少函数传参时间
        SD_SPI_ReadWriteByte(0xFF);//忽略crc
        SD_SPI_ReadWriteByte(0xFF);
        t=SD_SPI_ReadWriteByte(0xFF);//接收响应
        ;//响应错误
    }
    ;//写入成功
}

到这里,读写扇区就完成了,下一步就是,使用文件系统来进行操作了。

基于stm32f103zet6的FAT16文件系统学习0(读SD卡扇区)的更多相关文章

  1. 基于stm32f103zet6的FAT16文件系统学习1(初识FAT16)

    有了之前读写block的基础之后,准备弄个文件系统,之前没有接触过这东西,所以有很多都晕晕的,但是看到fat的源代码之后还是挺有信心的,因为之前一直过uboot,所以这个文件当然是小巫见大巫了.首先来 ...

  2. Android中向SD卡读写数据,读SD卡和手机内存

    package com.example.sdoperation; import java.io.BufferedReader; import java.io.File; import java.io. ...

  3. uboot里读sd卡内容

    1. sd卡升级命令 mmcinit 0 fatload mmc 0:1 0 uzImage.bin 80000 fatload mmc 0:1 1000000 initrd.gz 580000 bo ...

  4. FPGA之SPI SD卡读操作

    这几天在FPGA调试与SD通信,读SD卡里的图片,之前接触32时没有去研究过SD卡,不太熟悉操作流程,在网上找了很多资料,也看了几个32开发板的资料,但大多数都讲得不是特别清楚,只能瞎操作了一番,在别 ...

  5. 第37章 基于SD卡的FatFs文件系统—零死角玩转STM32-F429系列

    第37章     基于SD卡的FatFs文件系统 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.co ...

  6. Keil MDK STM32系列(九) 基于HAL和FatFs的FAT格式SD卡TF卡读写

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

  7. 玩转X-CTR100 l STM32F4 l SD卡FatFs文件系统

    我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] X-CTR100控制器具有SD卡接口,本教程使用免费 ...

  8. sd 卡驱动--基于高通平台

    点击打开链接 内容来自以下博客: http://blog.csdn.net/qianjin0703/article/details/5918041 Linux设备驱动子系统第二弹 - SD卡 (有介绍 ...

  9. SD卡与FAT32系统学习

    2011-06-06 23:04 前2天,我了解了一下SD卡驱动的原理及FAT32文件系统的结构.接着准备主要已移植为主.通过LCD显示SD卡中的图片.但我需要分步进行. 0,使sd卡能读写数据.1, ...

随机推荐

  1. Linux下使用VirtualBox安装Windows系统

    (文档比较长,只是写的详细,实际操作起来相对简单.) 由于一些特殊原因,我们并不能完全抛下Windows而使用Linux.VirtualBox 是一款虚拟机软件,支持多系统.在Linux下安装 Vir ...

  2. 一颗 45nm CPU的制造过程

    沙子 :硅是地壳内第二丰富的元素,而脱氧后的沙子(尤其是石英)最多包含25%的硅元素,以二氧化硅(SiO2)的形式存在,这也是半导体制造产业的基础. 硅熔炼: 12英寸/300毫米晶圆级,下同.通过多 ...

  3. 使用ownCloud搭建你的个人云服务(ubuntu 14.04 server)(ownCloud对文件不切片,Seafile对文件切片),owncloud没有存储的功能 只能同步 本地删除了服务器也会删除

    ownCloud是什么 ownCloud是一个自由且开源的个人云存储解决方案(类似百度网盘或者Dropbox),包括两个部分:服务器和客户端. ownCloud在客户端可通过网页界面,或者安装专用的客 ...

  4. 【转】win32,win64编程永恒;语言编程需要注意的64位和32机器的区别

    原文网址:http://www.cnblogs.com/kex1n/archive/2010/10/06/1844737.html 一.数据类型特别是int相关的类型在不同位数机器的平台下长度不同.C ...

  5. 【转】各个层次的gcc警告 #pragma GCC diagnostic ignored "-Wunused-parameter" --不错

    原文网址:http://blog.csdn.net/lizzywu/article/details/9419145 各个层次的gcc警告从上到下覆盖 变量(代码)级:指定某个变量警告 int a __ ...

  6. JavaScript实现网页右下角弹出窗口代码

    <script language="JavaScript"><!--var no = 50;var speed = 1;var ns4up = (document ...

  7. POJ 2182 Lost Cows (线段树)

    题目大意: 有 n 头牛,编号为 1 - n 乱序排成一列,现已知每头牛前面有多少头牛比它的编号小,从前往后输出每头牛的编号. 思路: 从后往前推,假如排在最后的一头牛比他编号小的数量为a,那么它的编 ...

  8. What’s the difference between an interface and an abstract class in Java?

    原文 What’s the difference between an interface and an abstract class in Java? It’s best to start answ ...

  9. boost格式化输出xml

    我的boost为1.56而不是1.55 boost在xml的例子给出了一段写xml文件的代码,我简化如下: void debug_settings::save(const std::string &a ...

  10. PyQt4中无边框窗口的移动(拖动)

    import sys from PyQt4.QtGui import * from PyQt4.Qt import * from PyQt4.QtCore import * class AboutUs ...