SD卡从容量上讲分两种:标准容量和大容量,最小的是标准容量,小于等于2G

其中的访问关系如下:

SD卡分为两种模式:认证模式和传输模式,每一个模式包含着不同的状态,如下

以下主要讲其初始化过程:

SD卡初始化主要包含5条命令:CMD0,CMD8,ACMD41,CMD2,CMD3,初始化在认证模式下进行,此模式只用到CMDLine。

上电之后,所有卡均处于空闲状态,此时主机并不知道卡的适用电压是多少,所以,主机先假定一个电压并用其发送CMD0。

CMD0:reset指令,处于inactive状态的卡会无视掉这条命令,接收到这条命令或者上电之后,所有的卡处于输入模式,并处于一个默认的设置:RCA=0x0000,速度最低状态,最高的驱动电流忍耐力。

CMD8:用来验证接口操作条件(比如电压之类的,好吧,这个词我是直译的),什么意思呢,卡根据主机发过来的CMD8命令的参数来分析操作环境,同样,主机会根据CMD8的RESPONSE来再次确定操作环境的有效性。

但是卡有可能不会对CMD8命令进行一个RESPONSE,第一种原因:电压不符,因为主机并不知道卡的实际电压,只是假设了一个电压。第二种原因:卡的版本是2.0之前的。协议中说在2.00版本的协议强制在ACMD41之前发送CMD8,也就是说2.00之前的版本不需要发送,自然不会对这个命令做出响应。

CMD8命令告诉卡主机支持2.00版本协议,所以卡可以使能新功能。

ACMD41:是用来舍弃那些无法再主机想要的电压范围进行工作的卡,被舍弃的卡进入inactive状态。

如果没有得到CMD8的回应,则ACMD41的HCS(host capacity support)选项设置为0。

如果得到了CMD8的回应,则HCS可以设置为0也可以设置为1,但是大容量的卡如果接收到ACMD41命令发现HCS为0,则不会进入就绪(见前面的图,标准容量的主机不能访问大容量的卡)。标准容量的卡则不会关注HCS选项。所以如果主机支持大容量,则应该将HCS设置为1。

关于ACMD41的RESPONSE,含有CCS字段,若CCS==1,则卡是大容量,如果CCS==0,则卡是标准容量。

CMD2:CID回显

CMD3:设置RCA

具体的图如下所示:

---------------------------------------------------------------------------------------------------

工作图如下:

过了认证模式,进入传输模式之后,工作就如上图了。

主要解释一下各种命令:

CMD4:广播命令,广播给所有卡,功能为修改DSR寄存器,从而来设置驱动阶段的参数(总线宽度,卡的数量,传输频率从Fod到Fpp)

SDR寄存器的解释如下:

可以看出,对DSR的设置是可以选择的,也就是说这个指令并不是非选不可。

CMD7:主要功能为让卡在传输状态和stand-by state之间切换,卡接到命令之后,根据参数中的RCA:如果和自己的RCA相等,则选中自己,如果和自己的不同,则取消选中自己。

特殊情况:CMD7中RCA为零,取消选中所有卡。在这之后可能会做两件事:1)再次选择一个特定RCA的卡2)重新发送CMD3给卡,这种是为了应对初始化完后才加入的卡,这样的卡没经历认证过程,故没有RCA。这样做比全部reset的方式效率要高。

CMD16:设置BLOCK大小,在标容卡中:标准容量的SD卡默认的BLOCK大小是512Bytes。仅有当CSD中PARTIAL BLOCK READ OPERATION设置为允许的时候,标容卡才允许修改LENGTH。在大容量卡中:这条命令不影响读写的LENGTH,读写的LENGTH皆为512BYTES,如果强制修改则错误,但是大容量SD卡这条CMD16指令影响LOCK_UNLOCK指令。

CMD18 CMD12:这是一对指令,CMD18用来读连续的多个块,CMD12用来结束传输。

CMD17:CMD17用来读单个块。当数据线上没有数据传输的时候,数据线为高电平,每个传输的数据块需要以1或4为低电平为start bits,需要以1-4位高电平为end bits。

CMD24-27 42 56:均为写指令。当sd卡目前正在写入,写缓冲区已经满了的时候,会将DAT0置为低电平以示劳资很忙。不准写写保护区域。

CMD13:要求CARD发送状态,CARD响应的状态中有READY_FOR_DATA位,来显示CARD是否可以接受新的数据,如果卡不能接受新数据,则主机会通过CMD7指令来发送取消选中卡。并将卡置入未连接状态以及释放数据线。

ACMD23:此命令推荐在CMD25(写多个块)之前用,它可以定义将要写的块数,相比直接CMD25,可以加快速度。

ACMD22:得到有多少个块完好的写入,一般用于出错的时候。

(读写 具体看代码有待补齐)

三个和擦除有关的指令:CMD32(设置擦除起始地址),CMD33(设置擦除结束地址),CMD38(开始擦除),三个指令必须按照这个顺序一起用。如果擦除的范围中包含写保护区域,那么就只有其中的非保护区域可以被擦除。同样,当卡正在擦除的时候,也会把DAT线置为低电平(空闲的时候为高电平),检测到低电平的主机会对卡取消选中或者直接将其置为失去连接状态。SCR寄存器中的第55位规定了卡的擦除后的区域是0还是1(不同的制造商不一样)。

代码如下:

按块计算地址:

设置起始地址

设置终止地址

发送擦除指令

等待卡工作完毕

CMD42:上锁解锁命令,这个指令功能很强大,先上图一张:

3位:强制擦除,如有此位则忽略其他位

2位:0为lock  1为unlock

1位:为1则清除密码

0位:为1则设置密码

注意:在使用这个命令之前应该先设置block大小。

主要介绍一下四个操作:

1) 设置密码

①.CMD7命令,选中一个卡

②发送CMD16.

③发送LOCK/UNLOCK命令,如果修改密码的话需要同时提供旧密码新密码

④如果旧密码错误则将状态寄存器中的相应位置一

2) 重置密码

3) 锁定卡

4) 解锁卡

5)强制擦除

忘记密码者的福音,不研究了,看了这么多天文档,累了,用的时候再研究吧。

---------------------------------------------------------------------------------------------------

SD卡的内部构造看上去很简单,先上图一张,看到下面这张图我就有中豁然开朗的感觉:

感觉so nb,这么复杂的器件就只有6个寄存器。

然后看它的指令:

指令一共有四种:第一种,无回复广播指令,CMD0应该就是这种指令,第二种,有回复广播指令,这种指令只有在CMDline是分开的时候才可以用,第三种,点对点指令,第四种,

点对点数据传输指令。

指令的格式都一样的,48位,但是不同的指令的RESPONSE不同,每个指令起于起始位,终止于终止位,transmission bit代表传输方向,就是是主机到卡还是卡到主机,这几个再加上后面的CRC校验位都是硬件自动生成的,我们需要用软件生成的是COMMAND INDEX 和 ARGUMENT:

下面逐条详细介绍初始化过程中的命令:

CMD0

它的功能是复位所有的卡,从说明上可以看出它不需要回复。

对应到驱动里,其对命令的发送是修改stm32中的CMD寄存器和ARG寄存器:

Cmd寄存器分布如下,其最后的6位为命令的index:

ARG寄存器分布如下

我们软件填充好这两个寄存器的值,剩下的就是硬件SDIO要做的了。

其接受函数通过判断STA寄存器(状态寄存器)中的命令发送位来返回,如下:

CMD8

其参数为保留位(后面要求保留位要为零),VHS,和CHECK PATTERN,其中CHECK PATTERN会在CMD8的RESPONSE中再次被发回来,以证明没错。

可以看到CMD8的RESPONSE为R7,我们再去看一下R7是什么样的。

可以看出R7也是48位的,其中包含支持电压,以及CHECK PATTERN的回复那么所谓的支持电压时如何表现出来的呢,

这是驱动中接受R7 RESPONSE的函数

其实这个函数就是不停的去检查STA的0,2,6位,这几个位的意思如下:

好吧,可以看出接受RESPONSE的工作硬件SDIO全帮咱们完成了,咱们只是知道接没接收到RESPONSE以及其CRC校验是否正确。当然,对于CMD8来说,知道有没有RESPONSE就够了,从这一点就已经能判断出卡的类型了。

ACMD41

发送这条命令之前首先要发送CMD55,来证明这是一条应用命令。

这条指令首先通过HCS来告诉卡主机的容量,只有当卡接受到CMD8的时候HCS才被卡视为有效的。这条命令的RESPONSE是R3。

根据R3 RESPONSE,返回的是OCR寄存器的值,赶脚sd卡肯定是一群不和谐工程师设计的,RESPONSE没有感受到一丝一毫的规律,还是我太笨了?反正ACMD41主要就是要求卡返回OCR寄存器的值。

OCR寄存器存储着很多东西,但更多的是保留位。。。。。。。。。

OCR的15到24位里面存储着卡的支持电压

OCR第30位存储着card是标准容量还是大容量

OCR的第31位标志着卡现在是否是busy状态

寄存器分布如下:

别的都大同小异,在此把读取ACMD41 RESPONSE的驱动代码贴出来:

我猛然意识到,处理响应和读取响应的参数应该是分开的,上面的驱动代码只是处理了响应,而并没有读取响应的返回的OCR寄存器的值。

这才是读取响应中OCR的值得函数

根据地址,查找stm32中文参考手册

读取返回的寄存器的值,就是在stm32查询上面的那个寄存器了,咱们是短响应,所以只有第一个用得上。

CMD2

没啥说的,CID回显,R7如下:

要把回复设置为长类型:

CMD3

重新生成RCA

额。。看到这有个疑问,卡要怎么生成RCA,不同的卡怎么知道RCA不冲突呢?

。。。。。。。。算了。。。。。不纠结了,先看R6中16-31位是新的RCA,但是低16位是什么呢,他说让看***表,那就看呗:

看之前先说几句,这里面是卡的状态的0-12,19,22,23位:

之后再接受的时候要去判断这些位,如果都为零说明没有出错card的状态正常才可以。

---------------------------------------------------------------------------------------------------

我就擦了,写数据块的驱动写了好久,就是不能过,妈蛋,一开始貌似还能写进去,现在写都写不进去了,一直是缓冲区下溢错误,官方历程也只能跑DMA,妈蛋妈蛋妈蛋,靠!!!!!!!!!!!

擦出的驱动(核心代码):

就是三个命令依次发过去 ,按理说还应该有个读状态的命令,来读SD卡是否擦除完毕,不过图省事,没写

SD_Error qqk_erase()

{

SDIO_CmdInitStructure.SDIO_Argument = (u32)0x00;

SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_ERASE_GRP_START;

SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; //R1

SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

SDIO_SendCommand(&SDIO_CmdInitStructure);

errorstatus = CmdResp1Error(SD_CMD_SD_ERASE_GRP_START);

if (errorstatus != SD_OK)

{

return(errorstatus);

}

/*!< Send CMD33 SD_ERASE_GRP_END with argument as addr  */

SDIO_CmdInitStructure.SDIO_Argument = (u32)512;

SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_ERASE_GRP_END;

SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;

SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

SDIO_SendCommand(&SDIO_CmdInitStructure);

errorstatus = CmdResp1Error(SD_CMD_SD_ERASE_GRP_END);

if (errorstatus != SD_OK)

{

return(errorstatus);

}

/*!< Send CMD38 ERASE */

SDIO_CmdInitStructure.SDIO_Argument = 0;

SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_ERASE;

SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;

SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

SDIO_SendCommand(&SDIO_CmdInitStructure);

errorstatus = CmdResp1Error(SD_CMD_ERASE);

if (errorstatus != SD_OK)

{

return(errorstatus);

}

return(SD_OK);

结果图片:

读取CSD

经测试,貌似只能在未选中作为参数的RCA的卡的时候使用这个命令,也就是在使用CMD7选中以这个RCA为相对地址的卡之前,原因:因为CMD9是用在STAND-BY STATE状态的,而选中之后就进入了传输态。

SDIO_CmdInitStructure.SDIO_Argument = 557252608;

SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_CSD;

SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long;

SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;

SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;

SDIO_SendCommand(&SDIO_CmdInitStructure);

while (!( SDIO->STA & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CTIMEOUT | SDIO_FLAG_CMDREND)));

printf("\r\nµ°ÌÛ²âÊÔ¿ªÊ¼\r\n");

if(SDIO->STA & SDIO_FLAG_CMDREND)

{

printf("\r\n%32x\r\n",SDIO_GetResponse(SDIO_RESP1));

printf("\r\n%32x\r\n",SDIO_GetResponse(SDIO_RESP2));

printf("\r\n%32x\r\n",SDIO_GetResponse(SDIO_RESP3));

printf("\r\n%32x\r\n",SDIO_GetResponse(SDIO_RESP4));

}

}

stm32和sd卡的更多相关文章

  1. STM32之SD卡

    目录 一.SD卡概述 1.定义 2.容量等级 3.SD卡框图 4.SD卡与TF卡的区别 二. SD卡内部结构 1. SD卡内部结构简图 2. 存储阵列结构图 3.Buffer 4.“存储阵列Block ...

  2. STM32平台SD卡的FatFS文件系统开发

    STM32平台SD卡的FatFS文件系统开发 系统平台: STM32系列的STM32F103ZE SPI方式与SD卡通信 SD上移植FatFS系统 1 FatFS文件系统 1.1 FatFS简介 Fa ...

  3. 野火STM32 Flash&sd卡模拟U盘

    在USB库文件mass_mal.c中添加对flash和sd读写的函数,USB库调用这些函数从而实现模拟U盘的功能 //mass_mal.c /* Includes ------------------ ...

  4. STM32 Unicode 与 GBK 转换 .bin文件放到SD卡是啥意思

    2个数组 : }; }; 一个是Unicode 编码,一个是GBK编码: 用c2b软件转成.bin 二进制文件放到SD卡里: SD卡放入字库 .FON STM32 代码: 代码中SD卡字库和二进制路径 ...

  5. 【STM32】使用SDIO进行SD卡读写,包含文件管理FatFs(终)-配合内存管理来遍历SD卡

    [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(一)-初步认识SD卡 [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(二)-了解SD总线,命令的相关介绍 [STM3 ...

  6. 【STM32】使用SDIO进行SD卡读写,包含文件管理FatFs(八)-认识内存管理

    [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(一)-初步认识SD卡 [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(二)-了解SD总线,命令的相关介绍 [STM3 ...

  7. 【STM32】使用SDIO进行SD卡读写,包含文件管理FatFs(七)-准备移植FatFs

    [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(一)-初步认识SD卡 [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(二)-了解SD总线,命令的相关介绍 [STM3 ...

  8. 【STM32】使用SDIO进行SD卡读写,包含文件管理FatFs(六)-FatFs使用的思路介绍

    [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(一)-初步认识SD卡 [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(二)-了解SD总线,命令的相关介绍 [STM3 ...

  9. 【STM32】使用SDIO进行SD卡读写,包含文件管理FatFs(五)-文件管理初步介绍

    其他链接 [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(一)-初步认识SD卡 [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(二)-了解SD总线,命令的相关介绍 ...

随机推荐

  1. 查询数据,从链接地址中爬取文章内容jsoup

    查询数据,从链接地址中爬取文章内容 protected void doGet(HttpServletRequest request, HttpServletResponse response) thr ...

  2. Dart 中常用的数组操作方法总结

    这里总结了一些在 Dart 中常用的数组操作方法,以便查阅. 首先,我们准备两组数据,以方便后面使用: List<Map> students = [ { 'name': 'tom', 'a ...

  3. Source Insight 4.0配置格式化工具AStyle.exe

    Source Insight 4.0配置格式化工具AStyle.exe 摘自:https://blog.csdn.net/u012156133/article/details/81566871 1. ...

  4. Qt编写气体安全管理系统5-数据监控

    一.前言 本项目对设备的监控有四种视图模式,可以任意切换,数据监控.地图监控.设备监控.曲线监控,其中数据监控是最常用的,所以在主界面导航中也排在第一位,综合观察分析了很多气体安全或者组态监控软件,大 ...

  5. 为什么在MySQL数据库中无法创建外键?(MyISAM和InnoDB详解)

    问题描述:为什么在MySQL数据库中不能创建外键,尝试了很多次,既没有报错,也没有显示创建成功,真实奇了怪,这是为什么呢? 问题解决:通过查找资料,每次在MySQL数据库中创建表时默认的情况是这样的: ...

  6. 了解有后门的sshd服务是如何劫持密码的

    在服务器上安装一个打了后门补丁的sshd服务,当用户连接时,直接把密码记录下来,然后使用脚本发送到邮箱中. (1).实验环境 使用CentOS6.2作为系统环境,查看sshd和gcc的版本 [root ...

  7. Find minimum number of people to reach to spread a message across all people in twitter

    Considering that I'ld would like to spread a promotion message across all people in twitter. Assumin ...

  8. SQL网页端在线自定义查询工具

    TreeSoft数据库管理系统,是用JAVA开发,基于网页的数据库SQL查询工具.功能包括:数据库的展示,库表的展示,表字段结构的展示,SQL语句的在 线编辑批量执行,表结构的在线设计维护,数据的在线 ...

  9. Mac下WordPress4.1安装使用笔记

    WordPress简介         WordPress是一种使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站.也可以把 WordPress当作一个内 ...

  10. 安装AWX

    1.安装最新版python 2.安装最新版docker 设置国内docker镜像源 curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | ...