OpenEdv-开源电子网

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

SD卡实验的疑问(持续更新,对研究SD卡有帮助)

[复制链接]

39

主题

597

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2120
金钱
2120
注册时间
2011-9-3
在线时间
122 小时
发表于 2011-10-16 16:55:03 | 显示全部楼层 |阅读模式
 做这个实验的时候,看了好些SD的资料,但看原子光盘中的“SD卡.pdf”中说  要写入命令是,"其数值=命令+0X40",但我看原子的写入命令函数里用的是"数值=命令|0X40",可这两个算法是不一样的啊,例如:命令0X41,则如按相加的算法则就写入的值为0X81,即129;而用相或的算法得的是0X41,即65,哪个是对的呢?

//向SD卡发送一个命令
//输入: u8 cmd   命令
//      u32 arg  命令参数
//      u8 crc   crc校验值                               //另外,这里的CRC值是不是随意给它一个值都可以?
//返回值:SD卡返回的响应                
u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc)
{
    u8 r1; 
 u8 Retry=0;         
 SD_CS=1;
    SPIx_ReadWriteByte(0xff);//高速写命令延时
 SPIx_ReadWriteByte(0xff);    
  SPIx_ReadWriteByte(0xff);   
    //片选端置低,选中SD卡
    SD_CS=0;
    //发送
    SPIx_ReadWriteByte(cmd | 0x40);//分别写入命令     这里写入的命令数值=命令|0X40;可其它资料说是数值=命令+0X40的,这两个算法是不一样的
    SPIx_ReadWriteByte(arg >> 24);
    SPIx_ReadWriteByte(arg >> 16);
    SPIx_ReadWriteByte(arg >> 8);
    SPIx_ReadWriteByte(arg);
    SPIx_ReadWriteByte(crc);
    //等待响应,或超时退出
    while((r1=SPIx_ReadWriteByte(0xFF))==0xFF)
    {
        Retry++;    
        if(Retry>200)break;
    }  
    //关闭片选
    SD_CS=1;
    //在总线上额外增加8个时钟,让SD卡完成剩下的工作
    SPIx_ReadWriteByte(0xFF);
    //返回状态值
    return r1;
}           
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-10-16 17:44:21 | 显示全部楼层
回复【楼主位】螃蟹爱虫:
---------------------------------
1,CRC值不能随意的.有两个命令的CRC应该是必须要给的.其他命令好像忽略CRC,就可以随意.
2,命令|0X40,和命令+0X40,只要命令的数值不大于127,他们的结果就是一样的!!!

你看看SD卡有没有0X81这个指令吧.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

39

主题

597

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2120
金钱
2120
注册时间
2011-9-3
在线时间
122 小时
 楼主| 发表于 2011-10-16 18:10:11 | 显示全部楼层
谢谢原子。第2点已明白。第1点,我发现有些CRC的值为0X95,0XFF,0(其中0应该是忽略吧?),可看了好些资料都没具体说哪些命令需要哪些的CRC值,另外上述函数的CRC值是指多项式还是取余后的校验值?比如说:
   
//把SD卡设置到挂起模式
//返回值:0,成功设置
//       1,设置失败
u8 SD_Idle_Sta(void)
{
u16 i;
u8 retry;       
    for(i=0;i<0xf00;i++);//纯延时,等待SD卡上电完成  
    //先产生>74个脉冲,让SD卡自己初始化完成
    for(i=0;i<10;i++)SPIx_ReadWriteByte(0xFF); 
    //-----------------SD卡复位到idle开始-----------------
    //循环连续发送CMD0,直到SD卡返回0x01,进入IDLE状态
    //超时则直接退出
    retry = 0;
    do
    {    
        //发送CMD0,让SD卡进入IDLE状态
        i = SD_SendCommand(CMD0, 0, 0x95);                  //这里的CRC是0X95
        retry++;
    }while((i!=0x01)&&(retry<200));
    //跳出循环后,检查原因:初始化成功?or 重试超时?
    if(retry==200)return 1; //失败
return 0;//成功     
}     
//初始化SD卡
//如果成功返回,则会自动设置SPI速度为18Mhz
//返回值:0:NO_ERR
//       1:TIME_OUT
//      99:NO_CARD

u8 SD_GetCID(u8 *cid_data)
{
    u8 r1;    
    //发CMD10命令,读CID
    r1 = SD_SendCommand(CMD10,0,0xFF);                    //这里的CRC是0XFF,
    if(r1 != 0x00)return r1;  //没返回正确应答,则退出,报错  
    SD_ReceiveData(cid_data,16,RELEASE);//接收16个字节的数据  
    return 0;
}
回复 支持 反对

使用道具 举报

39

主题

597

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2120
金钱
2120
注册时间
2011-9-3
在线时间
122 小时
 楼主| 发表于 2011-10-16 20:37:07 | 显示全部楼层
 问题待定。。。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-10-16 21:11:42 | 显示全部楼层
第一个0x95是真正的CRC.而第二个,则是假的,不用给CRC的了.我是这么理解的.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

39

主题

597

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2120
金钱
2120
注册时间
2011-9-3
在线时间
122 小时
 楼主| 发表于 2011-10-16 23:19:57 | 显示全部楼层
  程序里有一句是这样的:r1 = SD_SendCommand_NoDeassert(8, 0x1aa,0x87);      即输入命令8,CRC码为0X87.
但我按照下面的方法却得不出CRC码为0X87,而是0X37请教?



回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-10-17 00:31:10 | 显示全部楼层
应该是你计算错了吧。呵呵,如果错了的话,早用不了了。你在看看咯,是不是少算了什么东西,或者是算错了。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

39

主题

597

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2120
金钱
2120
注册时间
2011-9-3
在线时间
122 小时
 楼主| 发表于 2011-10-17 19:47:07 | 显示全部楼层
应该不会错吧,我已经算了几遍了。。唉,,,
回复 支持 反对

使用道具 举报

39

主题

597

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2120
金钱
2120
注册时间
2011-9-3
在线时间
122 小时
 楼主| 发表于 2011-10-17 20:30:35 | 显示全部楼层
我是这样算的:M(x)=0X48000001AA;G(X)=X7+X3+1=0X89=137;
M(x)*X7=M(x)*X8/2=0x48000001AA00/2;
CRC[6...0]=M(x)*x7%0X89=(0x48000001AA00/2)%137=27=11011,
因为CRC所在字节第0位固定为1,所以CRC所在的字节为110111,即为0X37,原子这样算对吗?
回复 支持 反对

使用道具 举报

39

主题

597

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2120
金钱
2120
注册时间
2011-9-3
在线时间
122 小时
 楼主| 发表于 2011-10-17 21:51:00 | 显示全部楼层
比如说CMD0,前五字节应该为0X40 00 00 00 00,多项式为0X89,如何得出CRC值为0X95呢?请指教,谢谢。
我是把前五字节左移7位再除0X89,得余数换成二进制,另外在后面衔接上结束位‘1’,却得不出0X95
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-10-17 22:29:37 | 显示全部楼层
回复【10楼】螃蟹爱虫:
---------------------------------
这个我倒没有仔细研究呢。
copy过来的。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

39

主题

597

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2120
金钱
2120
注册时间
2011-9-3
在线时间
122 小时
 楼主| 发表于 2011-10-18 00:31:55 | 显示全部楼层
唉,怎么没有其它人对这个有疑问呢???
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2011-10-18 08:55:07 | 显示全部楼层
回复【12楼】螃蟹爱虫:
---------------------------------
其他人没你研究的深入.对这个.包括我也是.呵呵.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

46

主题

1579

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1970
金钱
1970
注册时间
2011-7-17
在线时间
4 小时
发表于 2011-10-18 12:05:28 | 显示全部楼层
回复【12楼】螃蟹爱虫:
---------------------------------
因为还没研究到这么远,哥还在研究中断的说,写的服务程序总运行不了,不知问题出在哪。
Time?And?Relative?Dimension?In?Space.
回复 支持 反对

使用道具 举报

39

主题

597

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2120
金钱
2120
注册时间
2011-9-3
在线时间
122 小时
 楼主| 发表于 2011-10-18 20:22:20 | 显示全部楼层
顶起来。。
回复 支持 反对

使用道具 举报

1

主题

29

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
375
金钱
375
注册时间
2011-10-20
在线时间
88 小时
发表于 2011-10-20 01:28:47 | 显示全部楼层
上次试着将sdio由1位改为4位数据线,没有成功;看网上资料说sdio挑卡,不知道是不是真的。
回复 支持 反对

使用道具 举报

39

主题

597

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2120
金钱
2120
注册时间
2011-9-3
在线时间
122 小时
 楼主| 发表于 2011-10-20 19:26:19 | 显示全部楼层
我这里SPI模式,不是SD模式。所以只胡DI,DO
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

初级会员

Rank: 2

积分
75
金钱
75
注册时间
2011-4-19
在线时间
16 小时
发表于 2011-10-21 15:15:11 | 显示全部楼层
回复【6楼】螃蟹爱虫:

---------------------------------
程序里有一句是这样的:r1 = SD_SendCommand_NoDeassert(8, 0x1aa,0x87);      即输入命令8,但是SD卡CMD8是保留的啊,也就是CMD8在SD卡中暂时没有作用啊,但是原子的程序中说通过此命令返回SD卡的版本信息,很困惑啊!
回复 支持 反对

使用道具 举报

39

主题

597

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2120
金钱
2120
注册时间
2011-9-3
在线时间
122 小时
 楼主| 发表于 2011-10-23 11:30:40 | 显示全部楼层
LS的看E文资料有介绍的。
回复 支持 反对

使用道具 举报

6

主题

114

帖子

0

精华

初级会员

Rank: 2

积分
180
金钱
180
注册时间
2011-2-28
在线时间
8 小时
发表于 2011-11-22 10:40:11 | 显示全部楼层
你对SD研究得好深入啊
我会很乐意与你交流的。
回复 支持 反对

使用道具 举报

27

主题

274

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
472
金钱
472
注册时间
2011-11-2
在线时间
11 小时
发表于 2011-11-24 16:17:48 | 显示全部楼层
好像说SD使用SPI模式不需要RCR校验 ,可能这样任何值都是可以的吧。只是我的板不知道为什么接5V不能下载 一定要接USB供电才能下载 不然帮你实验下看看是不是这样的。
回复 支持 反对

使用道具 举报

27

主题

274

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
472
金钱
472
注册时间
2011-11-2
在线时间
11 小时
发表于 2011-11-24 16:52:50 | 显示全部楼层
换了条串口线居然能下载了,那一条串口线必须使用USB供电才可以 天啊!!!  已经验证了冗余检验可以随便设定而不影响使用。
回复 支持 反对

使用道具 举报

39

主题

597

帖子

2

精华

金牌会员

Rank: 6Rank: 6

积分
2120
金钱
2120
注册时间
2011-9-3
在线时间
122 小时
 楼主| 发表于 2011-11-24 19:05:21 | 显示全部楼层
回复【22楼】zenghi:
---------------------------------
可能你的线质量太差了。有些命令不需要CRC校验的,有些必须要的。
回复 支持 反对

使用道具 举报

27

主题

274

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
472
金钱
472
注册时间
2011-11-2
在线时间
11 小时
发表于 2011-11-25 13:11:08 | 显示全部楼层
回复【23楼】螃蟹爱虫:
---------------------------------
看来我还是一知半解。昨天也就改了一处的CRC程序正常 以为就不需要了
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2012-8-24
在线时间
0 小时
发表于 2012-8-24 16:38:53 | 显示全部楼层

回复【9楼】 螃蟹爱虫 :

---------------------------------
"我是这样算的:M(x)=0X48000001AA;G(X)=X7+X3+1=0X89=137;
M(x)*X7=M(x)*X8/2=0x48000001AA00/2;
CRC[6...0]=M(x)*x7%0X89=(0x48000001AA00/2)%137=27=11011,
因为CRC所在字节第0位固定为1,所以CRC所在的字节为110111,即为0X37,原子这样算对吗?"

因为r1 = SD_SendCommand_NoDeassert(8, 0x1aa,0x87);中的参数crc其实不是真正的CRC校验码,应该理解成:CRC校验码<<1+最后一位结束位“1”。还有,你算出来的CRC校验码不对,应该是0x43才是,0x43<<1|1=0x87,所以原子哥的参数是对的。

回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2012-8-24
在线时间
0 小时
发表于 2012-8-24 16:40:52 | 显示全部楼层
我只是个菜鸟,也是无意中发现了这个问题,若有不对之处,请指点!
回复 支持 反对

使用道具 举报

27

主题

147

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
275
金钱
275
注册时间
2012-8-11
在线时间
0 小时
发表于 2012-8-24 20:20:02 | 显示全部楼层
学习了~~
回复 支持 反对

使用道具 举报

12

主题

216

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
313
金钱
313
注册时间
2011-4-7
在线时间
3 小时
发表于 2012-8-25 13:10:42 | 显示全部楼层
mark
回复 支持 反对

使用道具 举报

46

主题

1579

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1970
金钱
1970
注册时间
2011-7-17
在线时间
4 小时
发表于 2012-8-25 14:13:40 | 显示全部楼层
虫子哥,能不能用一个SDIO模式的SD卡驱动出来,官方的驱动太蛋痛,都挑卡很严重的。
Time?And?Relative?Dimension?In?Space.
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-8-25 19:23:00 | 显示全部楼层
回复【29楼】Tardis:
---------------------------------
找一下网络收音机的sdio驱动
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2012-10-5
在线时间
0 小时
发表于 2012-10-5 20:19:06 | 显示全部楼层
回复【楼主位】螃蟹爱虫:
---------------------------------
请问一下 SPIx_ReadWriteByte(arg >> 24);
    SPIx_ReadWriteByte(arg >> 16);
    SPIx_ReadWriteByte(arg >> 8);中
arg >> 24
arg >> 16
arg >> 8
为什么要这样,解答一下好吗
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-10-5 20:33:13 | 显示全部楼层
回复【31楼】源荣森:
---------------------------------
看SD卡的协议去。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

9

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2012-12-2
在线时间
0 小时
发表于 2013-3-27 15:11:48 | 显示全部楼层
应该是命令的数值小于63,命令|0x40和命令+0x40才是相等的啊!纠正一下原子哥的127.
不积跬步无以至千里,不积小流无以成江海!
回复 支持 反对

使用道具 举报

0

主题

9

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2012-12-2
在线时间
0 小时
发表于 2013-3-27 15:12:44 | 显示全部楼层
回复【2楼】正点原子:
回复【楼主位】螃蟹爱虫: --------------------------------- 1,CRC值不能随意的.有两个命令的CRC应该是必须要给的.其他命令好像忽略CRC,就可以随意. 2,命令|0X40,和命令+0X40,只要命令的数值不大于127,他们的结果就是一样的!!! 你看看SD卡有没有0X81这个指令吧.
---------------------------------
应该是命令的数值小于63,命令|0x40和命令+0x40才是相等的啊!纠正一下原子哥的127.
不积跬步无以至千里,不积小流无以成江海!
回复 支持 反对

使用道具 举报

9

主题

66

帖子

0

精华

初级会员

Rank: 2

积分
122
金钱
122
注册时间
2013-3-16
在线时间
0 小时
发表于 2013-4-2 22:03:24 | 显示全部楼层
mark
回复 支持 反对

使用道具 举报

63

主题

305

帖子

1

精华

高级会员

Rank: 4

积分
853
金钱
853
注册时间
2012-8-3
在线时间
79 小时
发表于 2014-2-20 16:15:48 | 显示全部楼层
回复【楼主位】 螃蟹爱虫 :
---------------------------------
第一点,因为CMD0的值(注意是值,CMD0只是名称)为0x40,而CMD0~CMD59的值是递增加1的,那么CMDx的值就等于CMD0 + x,所以CMDx = 0x40 + x;在二进制运算中,只要没有产生进位,可以用或运算来实现加法,0x40 二进制表示为0100 0000,因低6位为0,那么只要CMDx的值小于0111 1111(CMD63),就可以用|运算来表示CMDx,如CMD0 = 0x40 +0 = 0,CMD59 = 0x40 | 59 = 0x7B……
第二点,至于CRC运算,请看旧帖
http://openedv.com/posts/list/0/5585.htm?privmsg=1#146674
14楼已经说得很明白了
回复 支持 反对

使用道具 举报

2

主题

14

帖子

0

精华

新手上路

积分
42
金钱
42
注册时间
2013-11-7
在线时间
0 小时
发表于 2014-4-9 18:09:52 | 显示全部楼层
回复【36楼】EDA3rd:
---------------------------------
为什么cmd0的值是40呢,在sd卡的协议里我没有找到呢,请指教
回复 支持 反对

使用道具 举报

63

主题

305

帖子

1

精华

高级会员

Rank: 4

积分
853
金钱
853
注册时间
2012-8-3
在线时间
79 小时
发表于 2014-4-15 10:49:20 | 显示全部楼层
SanDisk Secure Digital Card Product Manual version 2.2, PAGE 70,其实CMD0本身的数值就是0,但完整的命令格式是6字节,从高位往低位看,第1位为起始位,固定为0,第二位表示主机,固定为1,接下来就是CMD,占6位。那么对于CMD0,就是01000000,红色部分就是CMDx,比如CMD2就是01000002。只是如果整体看第一个字节,那么CMD0就是0x40了。因为高两位都是固定为01了,所以编程的时候就以0x40表示CMD0,作为数据格式的第一个字节。

回复 支持 反对

使用道具 举报

22

主题

73

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
416
金钱
416
注册时间
2014-2-27
在线时间
71 小时
发表于 2015-1-22 18:52:09 | 显示全部楼层
回复【9楼】螃蟹爱虫:
---------------------------------
楼主是求余数的时候错了,这里应该是用模二除法,不是直接取余。
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-7-22 01:37

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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