OpenEdv-开源电子网

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

有关SD卡学习中的一些疑问

[复制链接]

38

主题

2061

帖子

6

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3273
金钱
3273
注册时间
2012-1-16
在线时间
37 小时
发表于 2012-2-5 01:23:24 | 显示全部楼层 |阅读模式

//获取SD卡的总扇区数(扇区数)  
//返回值:0: 取容量出错
//       其他:SD卡的容量(扇区数/512字节) 返回值单位KB
//每扇区的字节数必为512,因为如果不是512,则初始化不能通过.               
u32 SD_GetSectorCount(void)
{
    u8 csd[16];
    u32 Capacity; 
    u8 n;
 u16 csize;          
 //取CSD信息,如果期间出错,返回0
    if(SD_GetCSD(csd)!=0) return 0;    
    //如果为SDHC卡,按照下面方式计算
    if((csd[0]&0xC0)==0x40)  //V2.00的卡   //cisize最大只有16位。所以最大支持容量为32GB,还有6位没算本来可以支持到2TB
    { 
  csize = csd[9] + ((u16)csd[8] << 8) + 1;
  Capacity = (u32)csize << 9;   //CISIZE*512KB    显示时>>10位化成MB好些
    }else//V1.XX的卡   
    { 
  n = (csd[5] & 0xf) + ((csd[10] & 0x80) >> 7) + ((csd[9] & 0x03) << 1) + 2;
  csize = (csd[8] >> 6) + ((u16)csd[7] << 2) + ((u16)(csd[6] & 3) << 10) + 1;
  Capacity= (u32)csize << (n - 9);   //CAPACITY化成单位为KB,所以我觉得N-10好些
    }
    return Capacity;
}

第1个问题就是我改的地方

//等待卡准备好
//返回值:0,准备好了;其他,错误代码
u8 SD_WaitReady(void)    //个人理解,这里目的是为了保证cmd发出前out线为高电平
{
 u32 t=0;
 do
 {
  if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;//OK
  t++;     
 }while(t<0XFFFFFF);//等待
 return 1;
}

第二个问题是这里的个人理解

//写SD卡
//buf:数据缓存区
//sector:起始扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt)
{
 u8 r1;
 if(SD_Type!=SD_TYPE_V2HC)sector *= 512;//转换为字节地址
 if(cnt==1)
 {
  r1=SD_SendCmd(CMD24,sector,0X01);//写命令
  if(r1==0)//指令发送成功
  {
   r1=SD_SendBlock(buf,0xFE);//写512个字节   
  }
 }else
 {
  if(SD_Type!=SD_TYPE_MMC)   //SD卡发送特定命令,为MMC不需要直接发送CMD25
  {         //不知道SD卡可不可以直接发送CMD25
   SD_SendCmd(CMD55,0,0X01); 
   SD_SendCmd(CMD23,cnt,0X01);//发送指令 
  }
   r1=SD_SendCmd(CMD25,sector,0X01);//连续读命令
  if(r1==0)
  {
   do
   {
    r1=SD_SendBlock(buf,0xFC);//0xfc为开始写入令牌 
    buf+=512; 
   }while(--cnt && r1==0);
   r1=SD_SendBlock(0,0xFD);//0xfd为结束令牌
  }
 }  
 SD_DisSelect();//取消片选
 return r1;//
}

第三个问题是上面划线部分,MMC卡值支持基本指令,而SD卡V1.0的规范应该也兼容吧,可不可以不写CMD55+ACMD23而用CMD25代替呢?就像ACMD41和CMD1在激活时,用法相同

第四个问题:为什么初始化为什么没禁止CRC校验?貌似spi初始化后,没用到CRC

第五个问题,原子哥有没有测试过V1.0规范的SD卡和SPI模式的MMC卡?

注:以上问题都基于SPI模式,是在论坛下载修改后的代码,希望原子哥予以点评和解答

站在巨人的肩膀上不断的前进。。。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165516
金钱
165516
注册时间
2010-12-1
在线时间
2116 小时
发表于 2012-2-5 10:32:20 | 显示全部楼层
回复【楼主位】xiaoyan:
---------------------------------
1,是数据转换问题,如果返回KB不能满足要求,当然可以通过大单位MB甚至GB来满足你的要求.
2,本质是SD卡执行某些操作需要比较长时间,如果一个操作还没搞完就来下一个操作,就会引起混乱.和IIC总线类似,IIC也有等待ack的过程,这个可以理解为等待SD卡空闲/上一次操作完成.
3,你自己试试就知道了.
4,这个问题我也没研究了.照搬FATFS的.
5,手头没有MMC卡,所以没测试过.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

7

主题

69

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2013-4-6
在线时间
0 小时
发表于 2013-5-12 22:36:02 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
u8 SD_GetCSD(u8 *csd_data)
{
    u8 r1;  
    r1=SD_SendCmd(CMD9,0,0x01);//发CMD9命令,读CSD
    if(r1==0)
{
     r1=SD_RecvData(csd_data, 16);//接收16个字节的数据 
    }
SD_DisSelect();//取消片选
if(r1)return 1;
else return 0;
}  
这个函数为什么要用SD_RecvData()来读取返回数据,因为SD_RecvData(csd_data, 16)里面需要SD卡发回数据起始令牌0xFE,而这并不是读取sector啊。。
回复 支持 反对

使用道具 举报

6

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
79
金钱
79
注册时间
2012-6-25
在线时间
0 小时
发表于 2013-11-27 16:31:37 | 显示全部楼层

回复【2楼】正点原子:
---------------------------------
原子哥 SD卡连续读扇区写扇区 那边,连续读写扇区会出现bug ,有时候起始令牌响应错误,有时候写扇区数据接收错误。单个扇区操作时正常的 。
u8 SD_SendBlock(u8*buf,u8 cmd)

 u16 t;
// u16 n;

  
 if(SD_WaitReady())return 1;//等待准备失效
 SPI_SendByte(cmd);
 if(cmd!=0XFD)//不是结束指令
 {
  for(t=0;t<512;t++)SPI_SendByte(buf[t]);//提高速度,减少函数传参时间
   SPI_SendByte(0xFF);//忽略crc
   SPI_SendByte(0xFF);
  
 // n=0xfff;
   // TimeDelayus(100);
  t=SPI_ReadWriteByte(0xFF);//接收响应此处      t是0XFF?有时

 
if((t&0x1F)!=0x05)return 2;//响应错误   
             
 }                          
    return 0;//写入成功
}

回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165516
金钱
165516
注册时间
2010-12-1
在线时间
2116 小时
发表于 2013-11-28 16:25:18 | 显示全部楼层
回复【4楼】天明:
---------------------------------
用什么开发板测试的?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

36

主题

100

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
265
金钱
265
注册时间
2013-8-3
在线时间
0 小时
发表于 2013-12-14 21:10:14 | 显示全部楼层
回复【5楼】正点原子:
---------------------------------
原子哥,我也遇到这个问题,读写一个扇区是对的,可是多个扇区就错了,错误的地方是等待错误,
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2014-2-11
在线时间
1 小时
发表于 2014-2-11 09:11:01 | 显示全部楼层
写的是真真好
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2014-2-17
在线时间
0 小时
发表于 2014-2-17 19:26:18 | 显示全部楼层
回复【6楼】1756143812:
---------------------------------
那你最后怎么解决的,我也碰到“等待卡准备好”
回复 支持 反对

使用道具 举报

80

主题

268

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
441
金钱
441
注册时间
2014-8-11
在线时间
84 小时
发表于 2014-9-3 14:52:30 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
第二个问题中SD_SPI_ReadWriteByte(0XFF)==0XFF,为什么从机返回0xff就表示SD卡空闲/上一次操作完成
我是一只菜鸟,但我会大鹏展翅
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165516
金钱
165516
注册时间
2010-12-1
在线时间
2116 小时
发表于 2014-9-4 00:20:11 | 显示全部楼层
回复【9楼】战舰水手:
---------------------------------
想研究透,那就看SD卡白皮书。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

3

主题

12

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2015-1-11
在线时间
2 小时
发表于 2015-1-11 15:01:14 | 显示全部楼层
回复【10楼】正点原子:
---------------------------------
u8 SD_WaitReady(void)    //个人理解,这里目的是为了保证cmd发出前out线为高电平
{
 u32 t=0;
 do
 {
  if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;//OK
  t++;     
 }while(t<0XFFFFFF);//等待 
 return 1;
}

原子哥  我的程序死在这里了  SPI返回的不是FF  是0  会是哪里出了问题呢
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165516
金钱
165516
注册时间
2010-12-1
在线时间
2116 小时
发表于 2015-1-11 22:14:20 | 显示全部楼层
回复【11楼】panjiadi586:
---------------------------------
这不好说啊
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2015-2-6
在线时间
0 小时
发表于 2015-2-6 17:07:37 | 显示全部楼层
回复【11楼】panjiadi586:
---------------------------------
这个是因为你的SPI的读取引脚没有加入上拉电阻造成的  你试试加一个10K的电阻 应该就能解决   要注意你的SD卡模块是不是带有电平转换模块,如果有的话上拉电阻一定要加在电平转换IC和SD卡槽之间
回复 支持 反对

使用道具 举报

36

主题

94

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
275
金钱
275
注册时间
2015-3-29
在线时间
3 小时
发表于 2015-8-7 11:08:07 | 显示全部楼层
回复【9楼】战舰水手:
---------------------------------
第二个问题中SD_SPI_ReadWriteByte(0XFF)==0XFF,为什么从机返回0xff就表示SD卡空闲/上一次操作完成

这个现在明白了嘛???求教!
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2018-7-18
在线时间
11 小时
发表于 2020-3-21 16:34:42 | 显示全部楼层
wodezpyzz 发表于 2015-8-7 11:08
回复【9楼】战舰水手:
---------------------------------
第二个问题中SD_SPI_ReadWriteByte(0XFF)==0XFF ...

兄弟,你弄明白了吗?我来挖坟了
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-5-23 05:12

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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