Skip to content

SD卡

简介

SD卡的名字是Secure Digital Card 安全数字卡, 实际上就是nand flash加上控制芯片

只要有三种full size sd卡, Micro SD卡, 还有MiniSD卡

最常用的就是Micro SD卡

是在MMC卡的基础上面发展来的, 遵守的是SD协议, 下面使用的2.0版本的协议, 支持32G容量

容量大, 高安全性, 体积小, 传输速度快, 接口简单

image-20240107220417205

image-20240107220507955

image-20240107220917154

image-20240107221021830

image-20240107222241497

寄存器

image-20240107222709694

image-20240107222818446

image-20240107223229648

SDIO模式

常用的命令

image-20240107223901006

image-20240107224049323

image-20240107224309812

image-20240107225131594

RCA就是相对地址

响应

image-20240107225301911

image-20240107225453227

image-20240107225544390

image-20240107225633702

操作模式

image-20240108110949895

image-20240108111542740

image-20240108112235995

image-20240108112633096

image-20240108112751691

image-20240108112809095

image-20240108112913176

image-20240108113121040

SPI模式

命令

image-20240108113633384

image-20240108113856113

image-20240108114058082

image-20240108114709431

CMD9会在接收到respond之后返回16字节的CSD

相应

image-20240108114832934

image-20240108115229476

image-20240108115345960

数据Token

image-20240108115637988

主要通过返回的Token检查数据是否被正常接收

image-20240108115845745

实际通信

image-20240108120105929

各种模式

image-20240108121842550

image-20240108125541746

image-20240108125604050

image-20240108125710814

image-20240108125731821

需要等待MISO的状态变化, 标志着数据已经写入了

image-20240108130025768

编程实战

SPI模式

image-20240108130358447

image-20240108130438220

计算容量

获取csd寄存器值, 根据不同版本进行计算

c
/**
 * @brief       获取SD卡的总扇区数(扇区数)
 *   @note      每扇区的字节数必为512, 如果不是512, 则初始化不能通过
 * @param
 * @retval      SD卡容量(扇区数), 换成字节数要 * 512
 */
uint32_t sd_get_sector_count(void)
{
    uint8_t csd[16];
    uint32_t capacity;
    uint8_t n;
    uint16_t csize;

    if (sd_get_csd(csd) != 0)       /* 取CSD信息,如果期间出错,返回0 */
    {
        return 0;                   /* 返回0表示获取容量失败 */
    }

    /* 如果为SDHC卡,按照下面方式计算 */
    if ((csd[0] & 0xC0) == 0x40)    /* V2.00的卡 */
    {
        /* V2.0卡 计算容量的公式
         * memory capacity = (C_SIZE+1) * 512K byte 这个相当于2^19
         
           扇区数:memory capacity / 512byte 即 / 2^9
         */
           /* C_SIZE低8位       C_SIZE中8位                  C_SIZE高6位   */
        csize = csd[9] + ((uint16_t)csd[8] << 8) + ((uint32_t)(csd[7] & 63) << 16) + 1;
        capacity = (uint32_t)csize << 10;       /* 得到扇区数 */
    }
    else     /* V1.XX的卡 / MMC V3卡 */
    {
        /* V1.0卡 计算容量的公式
         * memory capacity = BLOCKNR                          * BLOCK_LEN
                             (C_SIZE+1)*MULT                  * (2^READ_BL_LEN)
                             (C_SIZE+1)*(2^(C_SIZE_MULT+2))
                           = (C_SIZE+1)*(2^(C_SIZE_MULT+2+READ_BL_LEN))
                           
           扇区数:memory capacity / 512byte 即 / 2^9
         */
    
          /* READ_BL_LEN     C_SIZE_MULT后1位          C_SIZE_MULT前2位 (移位操作是重新组合数据) */
        n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
                /* C_SIZE低2位     C_SIZE中8位                        C_SIZE高2位 (移位操作是重新组合数据) */
        csize = (csd[8] >> 6) + ((uint16_t)csd[7] << 2) + ((uint16_t)(csd[6] & 3) << 10) + 1; /* 公式中的(C_SIZE+1) */
        capacity = (uint32_t)csize << (n - 9);  /* 得到扇区数 */
    }

    return capacity;    /* 注意这里返回的是扇区数量, 不是实际容量的字节数, 换成字节数 得 * 512 */
}

SDIO模式

image-20240108174155984

image-20240108174312666

在初始化的时候设置的分频参数直接设置为正常情况下的参数就可以了, 因为在进行初始化的时候会调用函数HAL_SD_InitCard, 在这个函数里面会使用一个新的结构设置时钟为初始化的时钟, 使用默认的配置实现

之后会在函数SD_PowerON函数里面进行初始化发送命令, 根据不同的版本进行不同的操作, 发送命令ACMD41获取电压信息是否匹配, 以及获取SD卡的大小

然后调用SD_InitCard, 发送CMD2, CMD3, CMD9获取相对地址等信息

最后按照我们的配置进行设置时钟速度等