需要总体去浏览sd2.0协议的手册,大概了解每个章节写了什么,再看sd卡功能描述--》再看命令--》再看响应,响应对应的数据位---》响应对应的寄存器或者响应的Rx x==1、2、3、4、5、6
APB2对于F407来说等于168M/2=84M;
APB2等于PCLK2:提供给适配器寄存器和FIFO使用
SDIOCLK等于PCLK2:控制单元、命令路径、数据路径使用
SDIO_CK:提供给sd卡的时钟;通过SDIO_CLKCR时钟控制寄存器配置可得;公式如下
一些观察:状态位等一些和响应都通过SDIO响应寄存器得到;
只做一些关键性的东西记录;其他细节略;
cmd线:命令和响应都靠这根线;0开始,1结束。所以可以配置上拉
dat线:数据线,空闲为高
1、配置SDIO时钟
初始化时钟在2.0协议中配置为400k
配置时钟触发源
配置SD卡时钟源
配置数据线:1位数据线通用,支持卡多;
2、电源控制寄存器开启电源
3、使能sdio卡时钟
sd协议讲的操作(使用命令),在协议手册的第四章sd卡的功能描述:
fod卡识别模式的频率=400k
描述关键的信息,其他细节观察流程图;
2、ACMD41响应的ccs位中为1则表示SD卡为高容量卡;否则为普通SD卡
目的:软复位
4.7.2章的详细命令描述
无响应,复位所有的卡;
主要目的:有响应,卡支持sd2.0协议,否则为SD2.0之下或者mac卡;带参数:参数在2.0协议的4.3.13章节发送接口命令条件说明;推荐参数 0x1AA, 其中检查模式文中推荐AA,电压支持0x01;所以参数0x1AA
4.7.2章的详细命令描述
4.9.6章节的,R7响应
目标:在卡识别的流程图看到需要发送ACMD41,在发送之前应该发送CMD55,使得下个命令可以发送AMCD41;原文如下,4.2.2章节;并且在 4.7.2章的详细命令描述也重复提到ACMD使用之前,应该发送CMD55;
4.7.2章的详细命令描述,如下为简要解析:该命令详细使用在4.3.9章节
主要目标:响应就属于sd卡不响应就属于mac卡;区分SD和MAC卡;
4.7.2章的详细命令描述
返回OCR寄存器:寄存器如下
可以知道30、31位可以读取到卡的卡容量和卡上电状态;ACMD41之后响应中可以读取到卡容量和卡上电状态;
目标:返回卡的CID;
4.7.2章的详细命令描述
4.9.6章节的,R2响应
目标:让卡发布重新RCA相对地址;
4.7.2章的详细命令描述
4.9.6章节的,R6响应
2.0协议手册的的4.10.1章节的表4-36部分;
程序要检查19、22、23位是否发生错误;
目标:获取卡信息,CSD寄存器
4.7.2章的详细命令描述
4.9.6章节的,R2响应
目标: 通过相对地址RCA选中卡;
4.7.2章的详细命令描述
4.9.6章节的,R1响应
卡状态在2.0协议手册的4.10.1,这里略;
在stm32f4的28.9.6中,如果设置为短响应,那么返回的RESP1寄存器应该是32宽度的卡状态,所以不会是整个R1寄存器48位返回到主机,而是只有8-39的状态位;
在使用CMD2之后可以在获取到CID:
CMD2之后可以在SDIO响应1234寄存器可以读取到CID:
传输数据位高位到低位:每个SDIO响应寄存器32位宽度,所以有:
SDIO响应寄存器[0] CID 127--96
SDIO响应寄存器[1] CID 95--64
SDIO响应寄存器[2] CID 63--32
SDIO响应寄存器[3] CID 31--0
使用CMD9之后可以获得CSD寄存器;
CMD9之后可以在SDIO响应1234寄存器可以读取到CSD:
传输数据位高位到低位:每个SDIO响应寄存器32位宽度,所以有:
SDIO响应寄存器[0] CSD127--96
SDIO响应寄存器[1] CSD95--64
SDIO响应寄存器[2] CSD63--32
SDIO响应寄存器[3] CSD31--0
总线宽度选择,需要判断通过cmd9,获取的响应判断位25卡锁定状态,卡没有被锁定,就可以改变总线;
在卡寄存器SCR中可以,找到;所以要读取卡的SCR寄存器;如下顺序命令操作;
目标:设置块长度,因为要面向块的操作;需要先设置块;
4.7.2章的详细命令描述
4.9.6章节的,R1响应
在设置卡的块大小后,发送ACDM51之前也可以把主机的SDIO数据控制寄存器也进行相应的长度和块设置,应该是SCR比较特殊?只能用块FIFO传输;
为了发送ACMD命令
前提:发送ACDM51之前把主机的SDIO数据控制寄存器也进行相应的长度和块设置;
目标:读取卡SCR寄存器;
4.7.2章的详细命令描述
响应R1略:
短响应,RESP1只有状态位32宽;
读取SCR需要进行FIFO读取:
/* 因为fifo传输是按字节来传输,不像响应一样按照32位,字传输,所以FIFO:先传的是高字节进来像数组一样组成32位,组成一个字;所以最高字节在字的的前八位;
然后四个字节组成一个字,再到下一个字;在列程序是这样操作;
*/
此时可以带参数RCA卡相对地址,表明下一条为ACMD外,还使用RCA表明那张卡操作;
读到SCR之后,进行判断宽位支持,支持就进行发送ACMD,带参数宽度,
ACMD6进行修改卡总线宽;
附上SCR寄存器,详细解析在2.0协议中的5.3章节中
SDIO_CLKCR寄存器中;
在SDIO_CLKCR寄存器中
SDIO_CK 频率 = SDIOCLK / [CLKDIV + 2]。
在stmf4手册看到框图SDIOCLK =APB2:
APB2是多少,可以从工程文件中的启动文件中找到,上电默认84M
stm32的一些技巧+小总结_qq_36658033的博客-CSDN博客
参考 APB2默认分频查找
fpp数据传输模式时钟频率25M
cmd3命令后进入传输模式,cmd0和cmd15都可以返回到卡识别模式;
各种数据传输模式的关系总结如下:2.0协议的4.3章节,略
读取数据分为单块和多块读;
目标:读取一个块;
响应是R1,短响应返回32位宽状态,略;
1、数据控制寄存器清零
2、判断上个命令的响应返回的卡状态,卡锁不可以读;
3、校验块大小数据,需要是2的幂
4、cmd16给卡设置块大小,并响应正确;
6、设置主机块大小
7、cmd17发送读取块命令,附带单元地址,512个字节一个单元
8.1轮询接收
8.2DMA接收
目标:读取多个块,直到cmd12停止;
1、这与单块读取的实际操作的1-5都相同;校验长度不得超过SDIO数据长度寄存器的值;且长度为块大小的倍数
2、主机设置的块大小,以及块大小*块数的长度;
3、cmd18开始多块传输,带参数扇区地址(大容量卡一个单元512字节),直到cmd12结束,
4.1轮询接收
5.1DMA传输
没有数据传输dat总线拉高;
块长度和RCA错误时读命令不能执行;
cmd13
目标:让卡进入发送状态
R1响应略
cmd24一个块传输
cmd25 多个块传输,直到cmd12命令后才停止
R1响应略,R1中有返回的卡状态,详情在SD2.0协议中文手册的4.9章节
cmd12 次命令后多块传输才会停止
命令详情略;
1、清空数据控制寄存器
2、清除状态机配置
3、判断锁卡状态,锁卡无法操作
4、校验块大小,应该为2的幂;设置发送cmd16,带参数块的大小,设置卡的块大小
5、发送cmd13使得卡进入发送状态,查卡状态,R1响应,取得卡的状态,直到非空闲状态,进入发送态
6、主机设置块大小,长度等;
7、轮询发送
7.1 进入轮询 //数据块发送成功/下溢/CRC/超时/起始位错误 这些条件真则退出轮询体
7.2查询传输FIFO没半空,至少可以写入8个字
7.3 如果不够8个字,计算剩余的字长度,如果多出一个字节,字节,不是字,那么就增加一个发送字的长度;把数据送给发送fifo
如果够8个字,那么就把8个字直接放到发送fifo中
8、DMA发送
带参数,块数量
目标:设置块数量;
目标:开始多块传输
中断有有cmd12指令停止传输
实际操作:
1、清空数据控制寄存器
2、清除状态机配置
3、判断锁卡状态,锁卡无法操作
4、校验块大小,应该为2的幂;设置发送cmd16,带参数块的大小,设置卡的块大小
5、CMD23、CMD25
6、主机设置块大小,长度等
7、轮询发送
8、DMA发送