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. AD 常用策略

    配置WSUS 配置NTPS 配置用户配置文件漫游 配置漫游区磁盘配额 配置修改本地管理员用户名 配置修改本地管理员密码 配置网络验证(提示是否联网错误) 配置允许开设永久共享 配置允许开设共享打印机 ...

  2. Python第一阶段05

    1.内置方法: 2.Json序列化: import json info = { 'name': 'sisi', } f = open("test.text", "w&qu ...

  3. 【kubernetes 自带监控】 container级别cadvisor+kubelet,集群级别apiserver

    apiserver https://feisky.gitbooks.io/kubernetes/components/apiserver.html kube-apiserver 支持同时提供 http ...

  4. LODOP关联后眉脚条码的遮挡的一种情况

    前面的博文中,有介绍层级关系,最先输出的打印项在下层,后输出的在上层,但是最近发现了一种例外,就是前面有关联的情况下,后面把一个条码设置为页眉页脚项,眉脚项和前面关联其他的项的那个项位置重合,虽然这个 ...

  5. JS的正则表达式限定开始和结尾等测试

    []:匹配该区间内人任意一个字符^:匹配以某内容开头的$:匹配以模拟内容结尾的字符\w:测试是英文字母,数字,下划线.{}:设置区间,可出现几次到几次该文学习和测试几个正则的方法,测试结果如图,不加多 ...

  6. Windows2008R2+iis7.5环境下的dz论坛X3版伪静态设置教程

    Windows2008R2+iis7.5环境下的dz论坛X3版伪静态设置教程 因为2008R2不是那么的普及,加上X3版新出不久,所以伪静态的设置教程比较少,今天搞出来了,其实很简单,那么下面给大家简 ...

  7. 对ThreadLocal的理解

      参考文档:https://www.cnblogs.com/moonandstar08/p/4912673.html   一.定义:线程本地变量,每个线程中的变量相互独立,互不影响. 官方定义: 1 ...

  8. 【计算机视觉】基于Shading Model(对光照变化一定不变性)的运动目标检测算法

    光照模型(Shading Model)在很多论文中得到了广泛的应用,如robust and illumination invariant change detection based on linea ...

  9. 最新 蓝鲸人java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿. 蓝鲸人等10家互联网公司的校招Offer,因为某些自身原因最终选择了 蓝鲸人.6.7月主要是做系统复习.项目复盘.Leet ...

  10. PHP 菠菜木马代码

    <?php error_reporting(E_ERROR);@ini_set('display_errors', 'Off');@ini_set('max_execution_time', 2 ...