SD底层驱动c代码.docx

上传人:b****4 文档编号:3775045 上传时间:2022-11-25 格式:DOCX 页数:14 大小:558.62KB
下载 相关 举报
SD底层驱动c代码.docx_第1页
第1页 / 共14页
SD底层驱动c代码.docx_第2页
第2页 / 共14页
SD底层驱动c代码.docx_第3页
第3页 / 共14页
SD底层驱动c代码.docx_第4页
第4页 / 共14页
SD底层驱动c代码.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

SD底层驱动c代码.docx

《SD底层驱动c代码.docx》由会员分享,可在线阅读,更多相关《SD底层驱动c代码.docx(14页珍藏版)》请在冰豆网上搜索。

SD底层驱动c代码.docx

SD底层驱动c代码

SD卡底层驱动程序,c代码

硬件平台:

stm32

编译环境:

MDK401

驱动方式:

SPI总线

下载(12.88KB)

2010-11-819:

50

编写的函数如下:

1、u8SD_Init()                                      SD卡初始化(复位和激活)

2、u8SD_SendCommand(u8cmd,u32arg,u8crc)    向SD卡发送一个命令

3、u32SD_GetCapacity(void)                        获取SD卡的容量

4、u8SD_GetCID(u8*cid_data)                      获取SD卡的CID信息,包括制造商信息

5、u8SD_GetCSD(u8*csd_data)                    获取SD卡的CSD信息,包括容量和速度信息

6、u8SD_ReadMultiBlock(u32sector,u8*buffer,u8count)  读SD卡的多个block

7、u8SD_ReadSingleBlock(u32sector,u8*buffer)    读SD卡的一个block

8、u8SD_ReceiveData(u8*data,u16len,u8release)  从SD卡中读回指定长度的数据,放置在给定位置

9、u8SD_WaitReady(void)                            等待SD卡Ready

10、u8SD_WriteMultiBlock(u32sector,constu8*data,u8count)  写入SD卡的N个block

11、u8SD_WriteSingleBlock(u32sector,constu8*data)  写入SD卡的一个block

SD卡命令  推荐SD卡命令共分为12类,分别为class0到class11,不同的SDd卡,主控根据其功能,支持不同的命令集如下:

Class0(卡的识别、初始化等基本命令集)

CMD0:

复位SD卡.

CMD1:

读OCR寄存器.

CMD9:

读CSD寄存器.

CMD10:

读CID寄存器.

CMD12:

停止读多块时的数据传输

CMD13:

读Card_Status寄存器

Class2(读卡命令集):

CMD16:

设置块的长度

CMD17:

读单块.

CMD18:

读多块,直至主机发送CMD12为止.

Class4(写卡命令集):

CMD24:

写单块.

CMD25:

写多块.

CMD27:

写CSD寄存器.

Class5(擦除卡命令集):

CMD32:

设置擦除块的起始地址.

CMD33:

设置擦除块的终止地址.

CMD38:

擦除所选择的块.

Class6(写保护命令集):

CMD28:

设置写保护块的地址.

CMD29:

擦除写保护块的地址.

CMD30:

Askthecardforthestatusofthewriteprotectionbits

class7:

卡的锁定,解锁功能命令集  

class8:

申请特定命令集。

class10-11:

保留

其中 class1,  class3,class9:

SPI模式不支持

SD卡命令格式如下:

下载(48.37KB)

2010-11-819:

45

解释:

6个字节,第一个字节最高两个BIT为01,2-5BYTE为参数,还有一个字节的CRC校验

SD卡SPI模式硬件连接:

(典型连接)

下载(30.29KB)

2010-11-819:

50

SD卡两种模式,引角使用情况(注意:

本帖所用SPI模式)

下载(78.52KB)

2010-11-819:

48

SPI时序如下:

下载(57.03KB)

2010-11-819:

48

下载(48.2KB)

2010-11-819:

48

SD卡时序如下:

下载(76.34KB)

2010-11-819:

48

下载(72.82KB)

2010-11-819:

48

下载(19.86KB)

2010-11-819:

48

下载(108.18KB)

2010-11-819:

48

下载(104.43KB)

2010-11-819:

48

时序分析(这里我举一个例子)

SD卡读扇区时序

1、拉低CS,选中SD卡

2、发送命令17(从本帖的上面查)

3、命令发送完毕后不断的读取输出线,读到0xFE,表示命令成功

4、准备接收数据,0xFE是数据的开始,此后就可以接收512个字节了  (当然在初始化的时候有用命令16设置块的大小为512)

5、数据接收完毕,拉高CS线

6、最后等8个时钟,你可以随便发一个BYTE就可以了(严格按照时序,大家别偷懒哦)

SD卡读扇区时序

1.u8SD_ReceiveData(u8*data,u16len,u8release)

2.{

3.u16retry;

4.u8r1;

5.SD_CS_Reset();  //启动一次传输

6.//等待SD卡发回数据起始令牌0xFE

7.retry=0;

8.do

9.{

10.r1=SPI_ReadWriteByte(0xFF);

11.retry++;

12.if(retry>200)//200次等待后没有应答,退出报错

13.{

14.SD_CS_Set();

15.return1;

16.}

17.}while(r1!

=0xFE);

18.//开始接收数据

19.while(len--)

20.{

21.*data=SPI_ReadWriteByte(0xFF);

22.data++;

23.}

24.//下面是2个伪CRC(dummyCRC)

25.SPI_ReadWriteByte(0xFF);

26.SPI_ReadWriteByte(0xFF);

27.//按需释放总线,将CS置高

28.if(release==RELEASE)

29.{

30.//传输结束

31.SD_CS_Set();

32.SPI_ReadWriteByte(0xFF);

33.}

34.return0;

35.}

复制代码

SD_SendCommand

1.u8SD_SendCommand(u8cmd,u32arg,u8crc)

2.{

3.unsignedcharr1;

4.unsignedcharRetry=0;

5.//SPI_ReadWriteByte(0xff);

6.//片选端置低,选中SD卡

7.SD_CS_Reset();

8.//发送

9.SPI_ReadWriteByte(cmd|0x40);//分别写入命令

10.SPI_ReadWriteByte(arg>>24);

11.SPI_ReadWriteByte(arg>>16);

12.SPI_ReadWriteByte(arg>>8);

13.SPI_ReadWriteByte(arg);

14.SPI_ReadWriteByte(crc);

15.//等待响应,或超时退出

16.while((r1=SPI_ReadWriteByte(0xFF))==0xFF)

17.{

18.Retry++;

19.if(Retry>200)

20.{

21.break;

22.}

23.}

24.//关闭片选

25.//在总线上额外增加8个时钟,让SD卡完成剩下的工作

26.SPI_ReadWriteByte(0xFF);

27.SD_CS_Set();

28.//返回状态值

29.returnr1;

30.}

复制代码

SD卡初始化代码:

这里我不敢保证大家的卡都能初始化成功,我自己的是可以,我发送CMD0和CMD1就可以初始化啦

网上有更兼容的初始化代码,大家可以看看哦!

调试的时候大家看返回值就可以了,哪里没成功就修改哪里哦!

1.u8SD_Init()

2.{

3.unsignedchartime,temp,i;

4.SD_CS_Set();//关闭片选

5.for(i=0;i<0x0A;i++)//初始时,首先要发送最少74个时钟信号,这是必须的!

6.{

7.SPI_ReadWriteByte(0xff);//120个时钟

8.}

9.SD_CS_Reset();//打开片选

10.time=0;

11.do

12.{

13.temp=SD_SendCommand(CMD0,0,0x95);//写入CMD0  复位SD卡

14.time++;

15.if(time==200)

16.{

17.SD_CS_Set();//关闭片选

18.}

19.}while(temp!

=0x01);

20.

21.time=0;

22.do

23.{

24.temp=SD_SendCommand(CMD1,0,0xff);//写入CMD1激活SD卡

25.time++;

26.if(time==200)

27.{

28.SD_CS_Set();//关闭片选

29.}

30.}while(temp!

=0);

31.

32.SPI_SetSpeed

(1);

33.temp=SD_SendCommand(CMD59,0,0x01);

34.if(temp!

=0x00)

35.{

36.returntemp;//命令错误,返回r1

37.}

38.temp=SD_SendCommand(CMD16,512,0xff);

39.if(temp!

=0x00)

40.{

41.returntemp;

42.//命令错误,返回r1

43.}

44.SD_CS_Set();//关闭片选

45.SPI_ReadWriteByte(0xff);//按照SD卡的操作时序在这里补8个时钟

46.return0;

47.}

复制代码

写入SD卡的N个block

1.u8SD_WriteMultiBlock(u32sector,constu8*data,u8count)

2.{

3.u8r1;

4.u16i;

5.//设置为高速模式

6.SPI_SetSpeed(SPI_SPEED_HIGH);

7.//如果不是SDHC,给定的是sector地址,将其转换成byte地址

8.if(SD_Type!

=SD_TYPE_V2HC)

9.{

10.sector=sector<<9;

11.}

12.//如果目标卡不是MMC卡,启用ACMD23指令使能预擦除

13.if(SD_Type!

=SD_TYPE_MMC)

14.{

15.r1=SD_SendCommand(ACMD23,count,0x00);

16.}

17.//发多块写入指令

18.r1=SD_SendCommand(CMD25,sector,0x00);

19.if(r1!

=0x00)

20.{

21.returnr1;//应答不正确,直接返回

22.}

23.//开始准备数据传输

24.SD_CS_Reset();

25.//先放3个空数据,等待SD卡准备好

26.SPI_ReadWriteByte(0xff);

27.SPI_ReadWriteByte(0xff);

28.//--------下面是N个sector写入的循环部分

29.do

30.{

31.//放起始令牌0xFC表明是多块写入

32.SPI_ReadWriteByte(0xFC);

33.//放一个sector的数据

34.for(i=0;i<512;i++)

35.{

36.SPI_ReadWriteByte(*data++);

37.}

38.//发2个Byte的dummyCRC

39.SPI_ReadWriteByte(0xff);

40.SPI_ReadWriteByte(0xff);

41.//等待SD卡应答

42.r1=SPI_ReadWriteByte(0xff);

43.if((r1&0x1F)!

=0x05)

44.{

45.SD_CS_Set();//如果应答为报错,则带错误代码直接退出

46.returnr1;

47.}

48.//等待SD卡写入完成

49.if(SD_WaitReady()==1)

50.{

51.SD_CS_Set();//等待SD卡写入完成超时,直接退出报错

52.return1;

53.}

54.//本sector数据传输完成

55.}while(--count);

56.//发结束传输令牌0xFD

57.r1=SPI_ReadWriteByte(0xFD);

58.if(r1==0x00)

59.{

60.count=0xfe;

61.}

62.if(SD_WaitReady())

63.{

64.while

(1)

65.{

66.}

67.}

68.//写入完成,片选置1

69.SD_CS_Set();

70.SPI_ReadWriteByte(0xff);

71.returncount;//返回count值,如果写完则count=0,否则count=1

72.}

复制代码

后记:

关于SPI读写,我就不发了,大家自己写就是了,当然读扇区,写扇区都是差不多的,只是命令不同,所以我只列举了其中一个,大家把函数都写好。

IO设置好,初始化成功后,就可以读一个扇区了,大家取出来,可以用WINHEX对比一下数据是否一致,一般命令成功后就没有什么大问题的。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1