OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 14066|回复: 5

SPI模式下对SD卡的操作

[复制链接]

3

主题

18

帖子

0

精华

限制会员

积分
-106
金钱
-106
注册时间
2012-3-31
在线时间
0 小时
发表于 2012-3-31 19:50:10 | 显示全部楼层 |阅读模式

参考文献: SD Specifications Part 1 Physical Layer Simplified Specification Version 3.01

STM32的SPI设备简介:
STM32F107VC有3个SPI设备,SPI控制器在输出数据的同时采样输入数据,使用相同时钟线。

Master设备写操作的同时,读入寄存器同时采样填充,每次也需要清空寄存器。
Master设备的读操作,实际上是通过写数据输出时钟序列,采样MISO的信号。

SD卡简介:
SD卡的技术规范经过几次升级,与最初版本已有很大不同,本文基于Ver 3.01讨论
从容量上分
 容量 命名  简称 
 0G<容量<2G Standard Capacity SD Memory Card   SDSC或SD
 2G<容量<32G High Capacity SD Memory Card  SDHC
 32G<容量<2T Extended Capacity SD Memory Card  SDXC


SD卡支持SPI的Mode0和Mode3
SD卡支持50MHz总线,STM32的APB2总线最高72MHz,SPI分频?为36Mhz,理论上所有SD卡都可以正常操作,实际上一些低版本的卡缺乏稳定性

插入信号CD:
CD线是可选的信号线,没有卡时为高电位,有卡插入时CD为低电位

CD Waiting

while ((*gpiob_idr)&0x4000) {}

电位稳定延迟:
CS线为高的状态下输出若干时钟,延迟利于电位稳定

Init Stable

sd_cs(1);
//sending dummy data few times
for (ii=0; ii<0xF; ii++) {
sd_bytedata(0xFF);
}

SD卡的准备状态,初始化操作:
SD卡从上电到可读写状态需要一定序列命令的操作,这个过程包括选择SPI模式和判断卡的版本以及供电操作
SD规范中的流程图

CMD0
SD卡上电后使用CMD0进入SPI模式,CMD0的返回值是1字节的R1,R1应该为空闲0x01

CMD0

sd_cs(0);
sd_command(cmd, cc);
res=sd_response();
sd_cs(1);

while ((rtn!=0x01)

CMD8
版本2.0以上的SD卡支持CMD8命令,包括大部分SDHC的卡和所有SDXC卡,早期的SDHC卡有可能仍属于V1.0卡
命令返回值R7,第一字节为R1,Ver1.0的卡对R1的“非法命令”位2置位,Ver2.0以上卡应返回0x01

CMD8

rtn = sd_cmd8_version_check(&sdif);
if ((rtn&0x04)==0x04) {
rtn=sd_v1_process(&sdif);
} else {
rtn=sd_v2_process(&sdif);
}

ACMD41和CMD1
ACMD41是为卡供电命令,供电前卡的状态为空闲(idle),R1的返回值为0x01,供电后为动作状态(ready)
一些早期的卡认为ACMD41是非法命令,只能用MMC的CMD1命令供电

ACMD41 Ready

if (rtn == 0x01) {
while (rtn==0x01) {
rtn = sd_send_cond_acmd41_v1();
}
}

if ((rtn&0x04)==0x04) { // invalid command
rtn = 0x01;
while (rtn==0x01) {
rtn = sd_cmd1_mmc_ready();
}
}

CMD58
CMD58读取卡的状态,一个重要的标志位CCS,会影响到读写操作中地址数据的设定
CCS为1时为高版本卡,数据地址为页单位,512字节为一页
CCS为0时,地址为以字节为单位实际地址
CCS置位与否也取决于ACMD41中对HCS:30bit的置位请求

CMD58 CCS

rtn = sd_read_ocr_cmd58(sd_inf->rx.r3);
sd_inf->ccs = (sd_inf->rx.r3[0]>>6)&0x01;


CMD9
取得卡容量等信息,CSO寄存器,CSO是16个字节的结构体,加上2字节的CRC,应读取18字节的内容

Read CSO

sd_cs(0);
sd_command(cmd, cc);
rtn = sd_response();
if (rtn == 0x00) {
if(sd_data_token()==0xFE) {
sd_data(cso, 20);
} else {
rtn = 0xFF;
}
}
sd_cs(1);

卡的信息也有版本区别,需要分别处理

CSO Version

sd_inf->csd_version = (cso[0]>>6)&0x3;
if (sd_inf->csd_version==0x0) {
sd_inf->block = cso[5]&0xF;
sd_inf->unit = cso[6]&0x3;
sd_inf->unit <<= 8;
sd_inf->unit |= cso[7];
sd_inf->unit <<= 2;
sd_inf->unit |= (cso[8]&0xC0)>>6;
sd_inf->multi = (cso[9]&0x3);
sd_inf->multi <<= 1;
sd_inf->multi |= (cso[10]&0x80)>>7;
sd_inf->page = sd_inf->unit + 1;
sd_inf->page <<= (sd_inf->multi + 2);
sd_inf->size = sd_inf->page << sd_inf->block;
} else {
sd_inf->block = cso[5]&0xF;
sd_inf->unit = cso[7]&0x3F;
sd_inf->unit <<= 8;
sd_inf->unit |= cso[8];
sd_inf->unit <<= 8;
sd_inf->unit |= cso[9];
sd_inf->page = sd_inf->unit * 1024;
sd_inf->size = sd_inf->page << sd_inf->block;
}

CMD24 CMD17
CMD24写数据
CMD17读数据
SD的读写都要以页单位进行,无论是否是新版本。
老版本的地址设定也要从页的起始处,一般为512的倍数
数据块紧接在命令块的后面。
数据块长度515个字节,起始标志字节为0xFE,实际数据512字节,2字节CRC
CRC使用CRC-16算法,不计算时可以设置为0xFF
写操作之后要等待非忙信号,忙信号使MISO为低电位,接收数据一直为0

CMD17 Read Block

sd_cs(0);
sd_command(cmd, cc);
rtn = sd_response();
if (rtn==0x00) {
rtn = sd_data_token();
if(rtn==0xFE) {
for (cc=0; cc<512; cc++) {
data[cc] = 0xAA;
data[cc] = sd_bytedata(0xFF);
}
sd_bytedata(0xFF);
sd_bytedata(0xFF);
}
rtn=0;
}
sd_cs(1);

CMD24 Write Block

sd_cs(0);
sd_command(cmd, cc);
rtn = sd_response();
if (rtn==0x00) {
sd_bytedata(0xFF);
sd_bytedata(0xFE);
for (cc=0; cc<512; cc++) {
sd_bytedata(data[cc]);
}
sd_bytedata(0xFF);
sd_bytedata(0xFF);
rtn = sd_response();
cc = 0;
while (rtn == 0x00) { //R1b busy
rtn = sd_bytedata(0xFF);
cc++;
}

}
sd_cs(1);

run_simple_sd.zip

14.35 KB, 下载次数: 1607

http://sites.google.com/site/btvnlue/stm32
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165377
金钱
165377
注册时间
2010-12-1
在线时间
2111 小时
发表于 2012-3-31 21:24:28 | 显示全部楼层
回复 支持 反对

使用道具 举报

3

主题

18

帖子

0

精华

限制会员

积分
-106
金钱
-106
注册时间
2012-3-31
在线时间
0 小时
 楼主| 发表于 2012-5-12 18:07:04 | 显示全部楼层
发现一个错误

ACMD命令的发送实际上是两个命令,CMD55之后,片选信号需要重新复位后在发送
SD规范中没有找到相关描述,市面上一些卡也支持不重新复位
经过反复测试,以上方法适用于绝大多数情况
特此更正




http://sites.google.com/site/btvnlue/stm32
回复 支持 反对

使用道具 举报

3

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
55
金钱
55
注册时间
2011-10-25
在线时间
0 小时
发表于 2012-6-9 20:09:15 | 显示全部楼层
看帖顶帖
回复 支持 反对

使用道具 举报

2

主题

100

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
278
金钱
278
注册时间
2012-4-15
在线时间
0 小时
发表于 2012-6-10 00:33:02 | 显示全部楼层
看了一下楼主的程序,不像是新手写的,但为什么很少注释且没有分模块呢?想必这个程序日后读起来,或要进行移植都要多花费一些时间吧。
喜欢单片机,没什么道理,就像爱吃水煮鱼,对味而已。
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
23
金钱
23
注册时间
2012-5-19
在线时间
0 小时
发表于 2012-9-10 17:06:24 | 显示全部楼层
留个记号
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-27 19:59

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表