SD卡驱动

一、介绍

1.SD 卡

安全数码卡, 它是在 MMC 的基础上发展而来, 是一种基于半导体快闪记忆器的新一代记忆设备。按容量分类,可以将SD 卡分为 3 类: SD 卡、 SDHC 卡、 SDXC 卡。SD卡(SDSC):0~2G SDHC卡:2~32G SDXC卡:32G~2T

2. SD的通讯模式

  • SD 卡模式(通过 SD 总线通信):允许 4 线的高速数据传输,只能使用 3.3V 的 IO 电平,所以, MCU 一定要能够支持 3.3V 的 IO 端口输出。
  • SPI 模式:同 SD 卡模式相比就是丧失了速度,在 SPI 模式下, CS/MOSI/MISO/CLK 都需要加 10~100K 左右的上拉电阻。
    请添加图片描述

3.SD引脚定义

请添加图片描述

二、SD卡驱动介绍

1.SD寄存器介绍

名称 宽度 描述
CID 128 卡识别寄存器
CSD 128 卡描述数据寄存器:卡操作条件相关的信息数据。
OCR 32 操作条件寄存器
RCA 16 相对卡地址寄存器:本地系统中卡的地址,动态变化,在卡的初始化时确定。(SPI模式中没有)
SCR 64 SD配置寄存器:SD卡特定信息数据

2、SD卡识别流程

请添加图片描述

初始化过程

  1. 初始化与 SD 卡连接的硬件条件(MCU 的 SPI 配置, IO 口配置;
  2. 上电延时(>74 个 CLK)(因为 SD 卡内部有个供电电压上升时间,大概为 64 个 CLK,剩下的 10 个 CLK 用于 SD 卡同步,之后才能开始 CMD0 的操作);
  3. 复位卡(CMD0),进入 IDLE 状态;
  4. 发送 CMD8,检查是否支持 2.0 协议;
  5. 根据不同协议检查 SD 卡(命令包括: CMD55、 CMD41、 CMD58 和 CMD1 等);
  6. 取消片选,发多 8 个 CLK(提供 SD 卡额外的时钟,完成某些操作),结束初始化;

3、读写SD卡

请添加图片描述

SD卡读取数据(CMD17):

  • 发送 CMD17;
  • 接收卡响应 R1;
  • 接收数据起始令牌 0XFE;
  • 接收数据;
  • 接收 2 个字节的 CRC,如果不使用 CRC,这两个字节在读取后可以丢掉。
  • 禁止片选之后,发多 8 个 CLK;

SD卡写数据(CMD24):

  • 发送 CMD24;
  • 接收卡响应 R1;
  • 发送写数据起始令牌 0XFE;
  • 发送数据;
  • 发送 2 字节的伪 CRC;
  • 禁止片选之后,发多 8 个 CLK;

三、SD卡驱动源码

源文件

#include "mmc_sd.h"

uint8_t  SD_Type = 0;//SD卡的类型
uint32_t Capacity = 0; //可用扇区数

移植修改区///
//SPI初始化
void hal_spi_init(void)
{
   

}

/*****************************************************************************
** 描  述:写入一个字节 
** 入  参:Dat:待写入的数据
** 返回值:读出的数据
******************************************************************************/
uint8_t SD_SPI_ReadWriteByte(uint8_t Dat)
{
   
	/**
		根据不同平台进行实现
		****/
}

//取消选择,释放SPI总线
void SD_DisSelect(void)
{
   
    SD_CS_HIGH_HRS();
    SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
}

//选择sd卡,并且等待卡准备OK
//返回值:0,成功;1,失败;
uint8_t SD_Select(void)
{
   
    SD_CS_LOW_HRS();
    if(SD_WaitReady()==0)return 0;//等待成功
    SD_DisSelect();
    return 1;//等待失败
}
///

//等待卡准备好
//返回值:0,准备好了;其他,错误代码
uint8_t SD_WaitReady(void)
{
   
    uint32_t t=0;
    do
    {
   
        if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;//OK
        t++;
    }
    while(t<0XFFFFFF); //等待
    return 1;
}
//等待SD卡回应
//Response:要得到的回应值
//返回值:0,成功得到了该回应值
//    其他,得到回应值失败
uint8_t SD_GetResponse(uint8_t Response)
{
   
    uint16_t Count=0xFFF;//等待次数
    while ((SD_SPI_ReadWriteByte(0XFF)!=Response)&&Count)Count--;//等待得到准确的回应
    if (Count==0)return MSD_RESPONSE_FAILURE;//得到回应失败
    else return MSD_RESPONSE_NO_ERROR;//正确回应
}
//从sd卡读取一个数据包的内容
//buf:数据缓存区
//len:要读取的数据长度.
//返回值:0,成功;其他,失败;
uint8_t SD_RecvData(uint8_t*buf,uint16_t len)
{
   
    if(SD_GetResponse(0xFE))return 1;//等待SD卡发回数据起始令牌0xFE
    while(len--)//开始接收数据
    {
   
        *buf=SD_SPI_ReadWriteByte(0xFF);
        buf++;
    }
    //下面是2个伪CRC(dummy CRC)
    SD_SPI_ReadWriteByte(0xFF);
    SD_SPI_ReadWriteByte(0xFF);
    return 0;//读取成功
}
//向sd卡写入一个数据包的内容 512字节
//buf:数据缓存区
//cmd:指令
//返回值:0,成功;其他,失败;
uint8_t SD_SendBlock(uint8_t*buf,uint8_t cmd)
{
   
    uint16_t t;
    if(SD_WaitReady())return 1;//等待准备失效
    SD_SPI_ReadWriteByte(cmd);
    if(cmd!=0XFD)//不是结束指令
    {
   
        for(t=0; t<512; t++)SD_SPI_ReadWriteByte(buf[t]); //提高速度,减少函数传参时间
        SD_SPI_ReadWriteByte(0xFF);//忽略crc
        SD_SPI_ReadWriteByte(0xFF);
        t=SD_SPI_ReadWriteByte(0xFF);//接收响应
        if((t&0x1F)!=0x05)return 2;//响应错误
    }
    return 0;//写入成功
}

//向SD卡发送一个命令
//输入: uint8_t cmd   命令
//      uint32_t arg  命令参数
//      uint8_t crc   crc校验值
//返回值:SD卡返回的响应
uint8_t SD_SendCmd(uint8_t cmd, uint32_t arg, uint8_t crc)
{
   
    uint8_t r1;
    
  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值