zoukankan      html  css  js  c++  java
  • [转]SD卡引脚 电路图及工作原理介绍

    SD卡引脚 电路图及工作原理介绍

    转自:http://blog.csdn.net/zhangyanquen/article/details/6658802

    SD卡在现在的日常生活与工作中使用非常广泛,时下已经成为最为通用的数据存储卡。在诸如MP3、数码相机等设备上也都采用SD卡作为其存储设备。 SD卡之所以得到如此广泛的使用,是因为它价格低廉、存储容量大、使用方便、通用性与安全性强等优点。既然它有着这么多优点,那么如果将它加入到单片机应 用开发系统中来,将使系统变得更加出色。这就要求对SD卡的硬件与读写时序进行研究。对于SD卡的硬件结构,在官方的文档上有很详细的介绍,如SD卡内的 存储器结构、存储单元组织方式等内容。要实现对它的读写,最核心的是它的时序,笔者在经过了实际的测试后,使用51单片机成功实现了对SD卡的扇区读写, 并对其读写速度进行了评估。下面先来讲解SD卡的读写时序。

    (1) SD卡的引脚定义

    SD卡引脚功能详述:

    引脚
    编号
    SD模式
            SPI模式
    名称
    类型
    描述
    名称
    类型
    描述
    1
    CD/DAT3
    IO或PP
    卡检测/
    数据线3
    #CS
    I
    片选
    2
    CMD
    PP
    命令/
    回应
    DI
    I
    数据输入
    3
    VSS1
    S
    电源地
    VSS
    S
    电源地
    4
    VDD
    S
    电源
    VDD
    S
    电源
    5
    CLK
    I
    时钟
    SCLK
    I
    时钟
    6
    VSS2
    S
    电源地
    VSS2
    S
    电源地
    7
    DAT0
    IO或PP
    数据线0
    DO
    O或PP
    数据输出
    8
    DAT1
    IO或PP
    数据线1
    RSV
     
     
    9
    DAT2
    IO或PP
    数据线2
    RSV
     
     

    注:S:电源供给  I:输入 O:采用推拉驱动的输出
    PP:采用推拉驱动的输入输出

    SD卡SPI模式下与单片机的连接图:

    SD卡支持两种总线方式:SD方式与SPI方式。其中SD方式采用6线制,使用CLK、CMD、DAT0~DAT3进行数据通信。而SPI方式采用 4线制,使用CS、CLK、DataIn、DataOut进行数据通信。SD方式时的数据传输速度与SPI方式要快,采用单片机对SD卡进行读写时一般都 采用SPI模式。采用不同的初始化方式可以使SD卡工作于SD方式或SPI方式。这里只对其SPI方式进行介绍。

    (2) SPI方式驱动SD卡的方法
         SD卡的SPI通信接口使其可以通过SPI通道进行数据读写。从应用的角度来看,采用SPI接口的好处在于,很多单片机内部自带SPI控制器,不光给开发 上带来方便,同时也见降低了开发成本。然而,它也有不好的地方,如失去了SD卡的性能优势,要解决这一问题,就要用SD方式,因为它提供更大的总线数据带 宽。SPI接口的选用是在上电初始时向其写入第一个命令时进行的。以下介绍SD卡的驱动方法,只实现简单的扇区读写。
    1) 命令与数据传输
    1. 命令传输
    SD卡自身有完备的命令系统,以实现各项操作。命令格式如下:

    命令的传输过程采用发送应答机制,过程如下:

    每一个命令都有自己命令应答格式。在SPI模式中定义了三种应答格式,如下表所示:

    字节
    含义
     
     
     
    1
    7
    开始位,始终为0
    6
    参数错误
    5
    地址错误
    4
    擦除序列错误
    3
    CRC错误
    2
    非法命令
    1
    擦除复位
    0
    闲置状态
    字节
    含义
     
     
     
    1
    7
    开始位,始终为0
    6
    参数错误
    5
    地址错误
    4
    擦除序列错误
    3
    CRC错误
    2
    非法命令
    1
    擦除复位
    0
    闲置状态
     
     
     
    2
    7
    溢出,CSD覆盖
    6
    擦除参数
    5
    写保护非法
    4
    卡ECC失败
    3
    卡控制器错误
    2
    未知错误
    1
    写保护擦除跳过,锁/解锁失败
    0
    锁卡
    字节
    含义
     
     
     
    1
    7
    开始位,始终为0
    6
    参数错误
    5
    地址错误
    4
    擦除序列错误
    3
    CRC错误
    2
    非法命令
    1
    擦除复位
    0
    闲置状态
    2~5
    全部
    操作条件寄存器,高位在前


    写命令的例程:
    //-----------------------------------------------------------------------------------------------
      向SD卡中写入命令,并返回回应的第二个字节
    //-----------------------------------------------------------------------------------------------
    unsigned char Write_Command_SD(unsigned char *CMD)
    {
       unsigned char tmp;
       unsigned char retry=0;
       unsigned char i;

       //禁止SD卡片选
       SPI_CS=1;
       //发送8个时钟信号
       Write_Byte_SD(0xFF);
       //使能SD卡片选
       SPI_CS=0;

       //向SD卡发送6字节命令
       for (i=0;i<0x06;i++)
       {
          Write_Byte_SD(*CMD++);
       }
      
       //获得16位的回应
       Read_Byte_SD(); //read the first byte,ignore it.
       do
       {  //读取后8位
          tmp = Read_Byte_SD();
          retry++;
       }
       while((tmp==0xff)&&(retry<100));
       return(tmp);
    }

    2) 初始化
    SD卡的初始化是非常重要的,只有进行了正确的初始化,才能进行后面的各项操作。在初始化过程中,SPI的时钟不能太快,否则会造初始化失败。在初始化成 功后,应尽量提高SPI的速率。在刚开始要先发送至少74个时钟信号,这是必须的。在很多读者的实验中,很多是因为疏忽了这一点,而使初始化不成功。随后 就是写入两个命令CMD0与CMD1,使SD卡进入SPI模式
               初始化时序图:

       初始化例程:
    //--------------------------------------------------------------------------
        初始化SD卡到SPI模式
    //--------------------------------------------------------------------------
    unsigned char SD_Init()

       unsigned char retry,temp;
       unsigned char i;
       unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
    SD_Port_Init(); //初始化驱动端口
      
       Init_Flag=1; //将初始化标志置1

       for (i=0;i<0x0f;i++)
       {
          Write_Byte_SD(0xff); //发送至少74个时钟信号
       }
     
       //向SD卡发送CMD0
       retry=0;
       do
       { //为了能够成功写入CMD0,在这里写200次
         temp=Write_Command_SD(CMD);
         retry++;
         if(retry==200)
         { //超过200次
           return(INIT_CMD0_ERROR);//CMD0 Error!
         }
       }
       while(temp!=1);  //回应01h,停止写入
      
       //发送CMD1到SD卡
       CMD[0] = 0x41; //CMD1
       CMD[5] = 0xFF;
       retry=0;
       do
       { //为了能成功写入CMD1,写100次
         temp=Write_Command_SD(CMD);
         retry++;
         if(retry==100)
         { //超过100次
           return(INIT_CMD1_ERROR);//CMD1 Error!
         }
       }
       while(temp!=0);//回应00h停止写入
      
       Init_Flag=0; //初始化完毕,初始化标志清零
      
       SPI_CS=1;  //片选无效
       return(0); //初始化成功
    }
    3) 读取CID
    CID寄存器存储了SD卡的标识码。每一个卡都有唯一的标识码。
    CID寄存器长度为128位。它的寄存器结构如下:
     

    名称
    数据宽度
    CID划分
    生产标识号
    MID
    8
    [127:120]
    OEM/应用标识
    OID
    16
    [119:104]
    产品名称
    PNM
    40
    [103:64]
    产品版本
    PRV
    8
    [63:56]
    产品序列号
    PSN
    32
    [55:24]
    保留
    4
    [23:20]
    生产日期
    MDT
    12
    [19:8]
    CRC7校验合
    CRC
    7
    [7:1]
    未使用,始终为1
    1
    [0:0]

    它的读取时序如下:

    与此时序相对应的程序如下:
    //------------------------------------------------------------------------------------
        读取SD卡的CID寄存器   16字节   成功返回0
    //-------------------------------------------------------------------------------------
    unsigned char Read_CID_SD(unsigned char *Buffer)
    {
       //读取CID寄存器的命令
       unsigned char CMD[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
       unsigned char temp;
       temp=SD_Read_Block(CMD,Buffer,16); //read 16 bytes
       return(temp);
    }

    4)读取CSD
    CSD(Card-Specific Data)寄存器提供了读写SD卡的一些信息。其中的一些单元可以由用户重新编程。具体的CSD结构如下:

    名称
    数据宽度
    单元类型
    CSD划分
    CSD结构
    CSD_STRUCTURE
    2
    R
    [127:126]
    保留
    -
    6
    R
    [125:120]
    数据读取时间1
    TAAC
    8
    R
    [119:112]
    数据在CLK周期内读取时间2(NSAC*100)
    NSAC
    8
    R
    [111:104]
    最大数据传输率
    TRAN_SPEED
    8
    R
    [103:96]
    卡命令集合
    CCC
    12
    R
    [95:84]
    最大读取数据块长
    READ_BL_LEN
    4
    R
    [83:80]
    允许读的部分块
    READ_BL_PARTIAL
    1
    R
    [79:79]
    非线写块
    WRITE_BLK_MISALIGN
    1
    R
    [78:78]
    非线读块
    READ_BLK_MISALIGN
    1
    R
    [77:77]
    DSR条件
    DSR_IMP
    1
    R
    [76:76]
    保留
    -
    2
    R
    [75:74]
    设备容量
    C_SIZE
    12
    R
    [73:62]
    最大读取电流@VDD min
    VDD_R_CURR_MIN
    3
    R
    [61:59]
    最大读取电流@VDD max
    VDD_R_CURR_MAX
    3
    R
    [58:56]
    最大写电流@VDD min
    VDD_W_CURR_MIN
    3
    R
    [55:53]
    最大写电流@VDD max
    VDD_W_CURR_MAX
    3
    R
    [52:50]
    设备容量乘子
    C_SIZE_MULT
    3
    R
    [49:47]
    擦除单块使能
    ERASE_BLK_EN
    1
    R
    [46:46]
    擦除扇区大小
    SECTOR_SIZE
    7
    R
    [45:39]
    写保护群大小
    WP_GRP_SIZE
    7
    R
    [38:32]
    写保护群使能
    WP_GRP_ENABLE
    1
    R
    [31:31]
    保留
    -
    2
    R
    [30:29]
    写速度因子
    R2W_FACTOR
    3
    R
    [28:26]
    最大写数据块长度
    WRITE_BL_LEN
    4
    R
    [25:22]
    允许写的部分部
    WRITE_BL_PARTIAL
    1
    R
    [21:21]
    保留
    -
    5
    R
    [20:16]
    文件系统群
    FILE_OFRMAT_GRP
    1
    R/W
    [15:15]
    拷贝标志
    COPY
    1
    R/W
    [14:14]
    永久写保护
    PERM_WRITE_PROTECT
    1
    R/W
    [13:13]
    暂时写保护
    TMP_WRITE_PROTECT
    1
    R/W
    [12:12]
    文件系统
    FIL_FORMAT
    2
    R/W
    [11:10]
    保留
    -
    2
    R/W
    [9:8]
    CRC
    CRC
    7
    R/W
    [7:1]
    未用,始终为1
    -
    1
     
    [0:0]

    读取CSD 的时序:

    相应的程序例程如下:
    //-----------------------------------------------------------------------------------------
        读SD卡的CSD寄存器   共16字节    返回0说明读取成功
    //-----------------------------------------------------------------------------------------
    unsigned char Read_CSD_SD(unsigned char *Buffer)

       //读取CSD寄存器的命令
       unsigned char CMD[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
       unsigned char temp;
       temp=SD_Read_Block(CMD,Buffer,16); //read 16 bytes
       return(temp);
    }


    4) 

    读取SD卡信息
    综合上面对CID与CSD寄存器的读取,可以知道很多关于SD卡的信息,以下程序可以获取这些信息。如下:
    //-----------------------------------------------------------------------------------------------
    //返回
    //  SD卡的容量,单位为M
    //  sector count and multiplier MB are in
    u08 == C_SIZE / (2^(9-C_SIZE_MULT))
    //  SD卡的名称
    //-----------------------------------------------------------------------------------------------
    void SD_get_volume_info()
    {  
        unsigned char i;
        unsigned char c_temp[5];
        VOLUME_INFO_TYPE SD_volume_Info,*vinf;
        vinf=&SD_volume_Info; //Init the pointoer;
    /读取CSD寄存器
        Read_CSD_SD(sectorBuffer.dat);
    //获取总扇区数
     vinf->sector_count = sectorBuffer.dat[6] & 0x03;
     vinf->sector_count <<= 8;
     vinf->sector_count += sectorBuffer.dat[7];
     vinf->sector_count <<= 2;
     vinf->sector_count += (sectorBuffer.dat[8] & 0xc0) >> 6;
     // 获取multiplier
     vinf->sector_multiply = sectorBuffer.dat[9] & 0x03;
     vinf->sector_multiply <<= 1;
     vinf->sector_multiply += (sectorBuffer.dat[10] & 0x80) >> 7;
    //获取SD卡的容量
     vinf->size_MB = vinf->sector_count >> (9-vinf->sector_multiply);
     // get the name of the card
     Read_CID_SD(sectorBuffer.dat);
     vinf->name[0] = sectorBuffer.dat[3];
     vinf->name[1] = sectorBuffer.dat[4];
     vinf->name[2] = sectorBuffer.dat[5];
     vinf->name[3] = sectorBuffer.dat[6];
     vinf->name[4] = sectorBuffer.dat[7];
     vinf->name[5] = 0x00; //end flag 
    }
             以上程序将信息装载到一个结构体中,这个结构体的定义如下:
    typedef struct SD_VOLUME_INFO
    { //SD/SD Card info
      unsigned int  size_MB;
      unsigned char sector_multiply;
      unsigned int  sector_count;
      unsigned char name[6];
    } VOLUME_INFO_TYPE;

  • 相关阅读:
    二进制数组ArrayBuffer
    iperf3测量一个网络最大带宽
    Proxy与Reflect
    Symbol
    Iterator
    Set与Map
    Generator
    Android 共享参数 SharedPreferences
    DDMS files not found: xxxhprof-conv.exe
    Android 状态栏通知 Notification
  • 原文地址:https://www.cnblogs.com/pengzhiwei/p/2887259.html
Copyright © 2011-2022 走看看