获取当前sd卡的总线宽度_STM32学习笔记20—SD卡基础读写实验

20.1 概述

SD卡是嵌入式系统中最常见的存储器,不仅容量可以做的很大,并且接口通用,支持SPI/SDIO驱动,尺寸可供选择,能满足不同应用的要求。STM32F1系列自带了标准的4位SDIO接口,最高通信速度可达24MHz,最高每秒能传输12M字节的数据。

20.1.1 SDIO框图

    STM32F1的SDIO控制器包括2部分,SDIO适配器模块和AHB总线接口,功能框图如下图所示。

54d2009fc3068c833857fdefb65ece05.png

其中SDIO适配器模块主要用于实现所有MMC/SD卡的相关功能,如时钟的产生,命令和数据的传输,AHB总线接口则用于操作SDIO适配器模块中的寄存器并产生中断和DMA请求信号。复位后默认情况下SDIO_D0用于数据传输。初始化后主机可以改变数据总线的宽度。

如果一个多媒体卡接到了总线上,则SDIO_D0、SDIO_D[3:0]或SDIO_D[7:0]可以用于数据传输。MMC版本V3.31和之前版本的协议只支持1位数据线,所以只能用SDIO_D0(为了通用性考虑,在程序里面我们只要检测到是MMC卡就设置为1位总线数据)。

如果一个SD卡接到了总线上,可以通过主机配置数据传输使用SDIO_D0或SDIO_D[3:0]。所有的数据线都工作在推挽模式。

SDIO_CMD有两种操作模式:

(1)用于初始化时的开路模式(仅用于MMC版本V3.31或之前版本)

(2)用于命令传输的推挽模式(SD卡和MMCV4.2在初始化时也使用推挽驱动)

20.1.2 SDIO时钟

从SDIO框图我们可以看到SDIO总共有3个时钟,分别是:

(1)卡时钟SDIO_CK:每个时钟周期在命令和数据线上传输1位命令或数据。对于多媒体卡V3.31协议,时钟频率可以在0MHz至20MHz间变化;对于多媒体卡V4.0/4.2协议,时钟频率可以在0MHz至48MHz间变化;对于SD卡,时钟频率可以在0MHz至25MHz间变化。

(2)SDIO适配器时钟SDIOCLK:该时钟用于驱动SDIO适配器,其频率等于AHB总线频率HCLK,并用于产生SDIO_CK时钟

(3)AHB总线接口时钟HCLK/2:该时钟用于驱动SDIO的AHB总线接口,其频率为HCLK/2。

我们的SD卡时钟SDIO_CK,根据卡的不同,可能有好几个区间,这就涉及到时钟频率的设置,SDIO_CK与SDIOCLK的关系为:

SDIO_CK=SDIOCLK/(2+CLKDIV)

其中,SDIOCLK为HCLK,一般是72MHz,而CLKDIV则是分配系数,可以通过SDIO的SDIO_CLKCR寄存器进行设置,确保SDIO_CK不超过卡的最大操作频率。

注:在SD卡刚刚初始化的时候,其时钟频率SDIO_CK不能超过400KHz,否则可能无法完成初始化。在初始化以后,就可以设置时钟频率到最大了,但不可超过SD卡的最大操作时钟频率。

20.1.3 SDIO的命令与响应

SDIO的命令分为应用相关命令ACMD和通用命令CMD两部分,应用相关命令ACMD的发送,必须先发送通用命令CMD55,然后才能发送应用相关命令ACMD。SDIO的所有命令和响应都是通过SDIO_CMD引脚传输的,任何命令的长度都是固定为48位,SDIO的命令格式如下表所示。

Bit位

宽度

说明

47

1

0

起始位

46

1

1

传输位

45:40

6

-

命令索引

39:8

32

-

参数

7:1

7

-

CRC7

0

1

1

结束位

所有的命令都是由STM32F1发出,其中开始位、传输位、CRC7和结束位由SDIO硬件控制,我们需要设置的就只有命令索引和参数部分。其中命令索引在SDIO_CMD寄存器里面设置,命令参数则由寄存器SDIO_ARG设置。一般情况下,选中的SD卡在接收到命令之后,都会回复一个应答(但是CMD0无应答),这个应答我们称之为响应,响应也是在CMD线上串行传输的。STM32F1的SDIO控制器支持2种响应类型,48位的短响应和136位的长响应,这两种响应类型都带CRC错误检测,不带CRC的响应应该忽略CRC错误标志,如CMD1的响应。

短响应的格式如下表所示。

Bit位

宽度

说明

47

1

0

起始位

46

1

0

传输位

45:40

6

-

命令索引

39:8

32

-

参数

7:1

7

-

CRC7或者1111111

0

1

1

结束位

长响应的格式如下表所示。

Bit位

宽度

说明

135

1

0

起始位

134

1

0

传输位

133:128

6

111111

保留

127:1

127

-

CID或CSD(包括内部CRC7)

0

1

1

结束位

硬件为我们滤除了开始位、传输位、CRC7以及结束位等信息,对于短响应,命令索引存放在SDIO_RESPCMD寄存器,参数则存放在SDIO_RESP1寄存器里面。对于长响应,则仅留CID/CSD位域,存放在SDIO_RESP1到SDIO_RESP4等4个寄存器。SD卡总共有5类响应(R1、R2、R3、R6、R7),这里以R1为例简单介绍一下。R1(普通响应命令)响应属于短响应,其长度为48位,R1响应的格式如下表所示。

Bit位

宽度

说明

47

1

0

起始位

46

1

1

传输位

45:40

6

X

命令索引

39:8

32

X

参数

7:1

7

X

CRC7

0

1

1

结束位

在收到R1响应后,我们可以从SDIO_RESPCMD寄存器和SDIO_RESP1寄存器分别读出命令索引和卡状态信息。

20.1.4 数据块读操作

对于SD卡,数据是以数据块的形式传输的,我们常用的卡就是SD卡,所以不考虑MMC形式的读写操作,因为MMC卡数据以数据块或者数据流的形式传输。

从机在收到主机相关命令后,开始发送数据块给主机,所有数据块都带有CRC校验值,CRC由SDIO硬件自动处理,单个数据块读的时候,在收到1个数据块以后即可以停止了,不需要发送停止命令CMD12。但是多块数据读的时候,SD卡将一直发送数据给主机,直到接到主机发送的STOP命令CMD12。

SDIO多数据块的读操作如下图所示。

76a9630f2d929773ec9b1b39aaf669ee.png

20.1.5 数据块写操作

数据块写操作同数据块读操作基本类似,只是数据块写的时候,多了一个忙判断,新的数据块必须在SD卡非忙的时候发送。这里的忙信号由SD卡拉低SDIO_D0,以表示忙,SDIO硬件自动控制,不需要我们软件处理。

ae91236389a847913c924e4ec3543c42.png

20.2 SDIO相关寄存器

20.2.1 SDIO电源控制寄存器:SDIO_POWER

31

30

29

28

27

26

25

24

23

22

21

20

19

18

17

16

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

-

CTRL

Bit 1~Bit 0:电源控制位

00:电源关闭,卡的时钟停止

01:保留

10:保留的上电状态

11:上电状态,卡的时钟开启

20.2.2 SDIO时钟控制寄存器:SDIO_CLKCR

31

30

29

28

27

26

25

24

23

22

21

20

19

18

17

16

-

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

-

HWFC_EN

NEGEDGE

WIDBUS

BYPASS

PWRSAV

CLKEN

CLKDIV

Bit 14:硬件流控制使能

0:关闭硬件流控制

1:使能硬件流控制

Bit 13:SDIO_CK相位选择位

0:在主时钟SDIOCLK的上升沿产生SDIO_CK

1:在主时钟SDIOCLK的下降沿产生SDIO_CK

Bit 12~Bit 11:宽总线模式使能位

00:默认总线模式,使用SDIO_D0

01:4位总线模式,使用SDIO_D[3:0]

10:8位总线模式,使用SDIO_D[7:0]

Bit 10:旁路时钟分频器

0:关闭旁路:驱动SDIO_CK输出信号之前,依据CLKDIV数值对SDIOCLK分频

1:使能旁路:SDIOCLK直接驱动SDIO_CK输出信号

Bit 9:省电配置位(为了省电,当总线为空闲时,设置PWRSAV位可以关闭SDIO_CK时钟输出)

0:始终输出SDIO_CK

1:仅在有总线活动时才输出SDIO_CK

Bit 8:时钟使能位

0:SDIO_CK关闭

1:SDIO_CK使能

Bit 7~Bit 0:时钟分频系数

这个域定义了输入时钟(SDIOCLK)与输出时钟(SDIO_CK)间的分频系数:SDIO_CK频率=SDIOCLK/[CLKDIV+2]

20.2.3 SDIO参数寄存器:SDIO_ARG

31

30

29

28

27

26

25

24

23

22

21

20

19

18

17

16

CMDARG[31:16]

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

CMDARG[16:0]

Bit 31~Bit 0:命令参数

属于发送到卡中命令的一部分,如果一个命令包含一个参数,必须在写命令到命令寄存器之前加载这个寄存器

20.2.4 SDIO命令响应寄存器:SDIO_RESPCMD

31

30

29

28

27

26

25

24

23

22

21

20

19

18

17

16

-

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

-

RESPCMD

Bit 5~Bit 0:响应的命令索引

只读位,包含最后收到的命令响应中的命令索引

20.2.5 SDIO相应寄存器组:SDIO_RESP1~SDIO_RESP4

寄存器

短响应

长响应

SDIO_RESP1

卡状态[31:0]

卡状态[127:96]

SDIO_RESP2

未使用

卡状态[95:64]

SDIO_RESP3

未使用

卡状态[31:0]

SDIO_RESP4

未使用

卡状态[31:0]

注:总是先收到卡状态的最高位,SDIO_RESP3寄存器的最低位始终为0。

20.2.6 SDIO命令寄存器:SDIO_CMD

31

30

29

28

27

26

25

24

23

22

21

20

19

18

17

16

-

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

-

CE_ATACMD

nIEN

ENCMDcomp1

SDIOSuspend

CPSMEN

WAITPEND

WAITINT

WAITRESP

CMDINDEX

Bit 14:CE-ATA命令

如果设置该位,CPSM转至CMD61

Bit 13:不使能中断

如果未设置该位,则使能CE-ATA设备的中断

Bit 12:使能CMD完成

如果设置该位,则使能命令完成信号

Bit 11:SDIO暂停命令

如果设置该位,则将要发送的命令是一个暂停命令(只能用于SDIO卡)

Bit 10:命令通道状态机使能位

如果设置该位,则使能CPSM

Bit 9:CPSM等待数据传输结束(CmdPend内部信号)

如果设置该位,则CPSM在开始发送一个命令之前等待数据传输结束

Bit 8:CPSM等待中断请求

如果设置该位,则CPSM关闭命令超时控制并等待中断请求

Bit 7~Bit 6:等待响应位

00:无响应,期待CMDSENT标志

01:短响应,期待CMDREND或CCRCFAIL标志

10:无响应,期待CMDSENT标志

11:长响应,期待CMDREND或CCRCFAIL标志

Bit 5~Bit 0:命令索引,作为命令的一部分发送到卡中

20.2.7 SDIO数据定时器:SDIO_DTIMER

31

30

29

28

27

26

25

24

23

22

21

20

19

18

17

16

DATATIME[31:16]

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

DATATIME[15:0]

Bit 31~Bit 0:数据超时时间,以卡总线时钟周期为单位的数据超时时间

20.2.8 SDIO数据长度寄存器:SDIO_DLEN

31

30

29

28

27

26

25

24

23

22

21

20

19

18

17

16

-

DATALENGTH[24:16]

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

DATALENGTH[15:0]

Bit 24~Bit 0:数据长度,要传输的数据字节数目

20.2.9 SDIO数据控制寄存器:SDIO_DCTRL

31

30

29

28

27

26

25

24

23

22

21

20

19

18

17

16

-

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

-

SDIOEN

RWMOD

RWSTOP

RWSTART

DBLOCKSIZE

DMAEN

DTMODE

DTDIR

DTEN

Bit 11:SDIO使能功能

如果设置了该位,则DPSM执行SDIO卡特定的操作

Bit 10:读等待模式

0:停止SDIO_CK控制读等待

1:使用SDIO_D2控制读等待

Bit 9:读等待停止

0:如果设置了RWSTART,执行读等待

1:如果设置了RWSTART,停止读等待

Bit 8:读等待开始

设置该位开始读等待操作

Bit 7~Bit 4:数据块长度,当选择了块数据传输模式,该域定义数据块长度

0000:块长度=1字节

0001:块长度=2字节

0010:块长度=4字节

0011:块长度=8字节

0100:块长度=16字节

0101:块长度=32字节

0110:块长度=64字节

0111:块长度=128字节

1000:块长度=256字节

1001:块长度=512字节

1010:块长度=1024字节

1011:块长度=2048字节

1100:块长度=4096字节

1101:块长度=8192字节

1110:块长度=16384字节

1111:保留

Bit 3:DMA使能位

       0:关闭DMA

       1:使能DMA

Bit 2:数据传输模式

       0:块数据传输

       1:流数据传输

Bit 1:数据传输方向

       0:控制器至卡

       1:卡至控制器

Bit 0:数据传输使能位

       如果设置该位为1,则开始数据传输。根据DTSIR方向位,DPSM进入Wait_S或Wait_R状态,如果在传输的一开始就设置了RWSTART位,则DPSM进入读等待状态。不需要在数据传输结束后清除使能位,但必须更改SDIO_DCTRL以允许新的数据传输。

20.2.10 SDIO状态寄存器:SDIO_STA

31

30

29

28

27

26

25

24

23

22

21

20

19

18

17

16

-

CEATAEND

SDIOIT

RXDAVL

TXDAVL

RXFIFOE

TXFIFOE

RXFIFOF

TXFIFOF

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

RXFIFOHF

TXFIFOHF

RXACT

TXACT

CMDACT

DBCKEND

STBITERR

DATAEND

CMDSENT

CMDREND

RXOVERR

TXUNDERR

DTMEOUT

CTIMEOUT

DCRCFAIL

CCRCFAIL

Bit 23:在CMD61接收到CE-ATA命令完成信号

Bit 22:收到SDIO中断

Bit 21:在接收FIFO中的数据可用

Bit 20:在发送FIFO中的数据可用

Bit 19:接收FIFO空

Bit 18:发送FIFO空

       若使用了硬件流控制,当FIFO包含2个字时,TXFIFOE信号变为有效。

Bit 17:接收FIFO满

       若使用了硬件流控制,当FIFO还差2个字满时,RXFIFOF信号变为有效。

Bit 16:发送FIFO满

Bit 15:接收FIFO半满,FIFO中至少还有8个字

Bit 14:发送FIFO半空,FIFO中至少还可以写入8个字。

Bit 13:正在接收数据

Bit 12:正在发送数据

Bit 11:正在传输命令

Bit 10:已发送/接收数据块(CRC检测成功)

Bit 9:在宽总线模式,没有在所有数据信号上检测到起始位

Bit 8:数据结束(数据计数器,SDIO_DCOUNT=0)

Bit 7:命令已发送(不需要响应)

Bit 6:已接收到响应(CRC检测成功)

Bit 5:接收FIFO上溢错误

Bit 4:发送FIFO下溢错误

Bit 3:数据超时

Bit 2:命令响应超时

       命令超时时间是一个固定的值,为64个SDIO_CK时钟周期。

Bit 1:已发送/接收数据块(CRC检测失败)

Bit 0:已收到命令响应(CRC检测失败)

注:状态寄存器可以用来查询SDIO控制器的当前状态。比如SDIO_STA的位2表示命令响应超时,说明SDIO的命令响应出了问题。我们通过设置SDIO_ICR的位2则可以清除这个超时标志,而设置SDIO_MASK的位2,则可以开启命令响应超时中断,设置为0关闭。

20.2.11 SDIO数据FIFO寄存器:SDIO_FIFO

31

30

29

28

27

26

25

24

23

22

21

20

19

18

17

16

FIFODATA[31:16]

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

FIFODATA[15:0]

Bit 31~Bit 0:接收或发送FIFO数据

FIFO数据占据32个32位的字,地址为:SDIO基址+0x80至SDIO基址+0xFC

数据FIFO寄存器包括接收和发送FIFO,他们由一组连续的32个地址上的32个寄存器组成,CPU可以使用FIFO读写多个操作数。例如我们要从SD卡读数据,就必须读SDIO_FIFO寄存器,要写数据到SD卡,则要写SDIO_FIFO寄存器。SDIO将这32个地址分为16个一组,发送接收各占一半。而我们每次读写的时候,最多就是读取发送FIFO或写入接收FIFO的一半大小的数据,也就是8个字(32个字节),在操作SDIO_FIFO(不论读出还是写入)必须是以4字节对齐的内存进行操作,否则将导致出错。

20.3 SD卡初始化

20.3.1 卡上电流程

c63afeddddbfed4853619e22cc4d4d69.png

20.3.2 卡初始化流程

eed5147291a3a32e64694f5edcb4fc7b.png

20.4 实验例程

功能:利用STM32F1的SDIO模块读取SD的容量并通过TFTLCD显示。

(1)创建sdio_sdcard.h文件,并输入以下代码。

#ifndef _SDIO_SDCARD_H_#define _SDIO_SDCARD_H_#include "sys.h"/*********************************************************************************************************                SD    卡    数    据    定    义*********************************************************************************************************///用户配置区#define SDIO_INIT_CLK_DIV        0x76                                  //SDIO初始化频率,最大400Kh#define SDIO_TRANSFER_CLK_DIV    0x00                                  //SDIO传输频率,该值太小可能会导致读写文件出错//SDIO工作模式定义,通过SD_SetDeviceMode函数设置#define SD_POLLING_MODE      0                                      //查询模式,该模式下,如果读写有问题,建议增大SDIO_TRANSFER_CLK_DIV的设置#define SD_DMA_MODE        1                                      //DMA模式,该模式下,如果读写有问题,建议增大SDIO_TRANSFER_CLK_DIV的设置//SDIO 各种错误枚举定义typedef enum{     //特殊错误定义   SD_CMD_CRC_FAIL                    = 1,                                //收到命令响应(CRC校验失败)  SD_DATA_CRC_FAIL                   = 2,                                //发送/接收数据块(CRC校验失败)  SD_CMD_RSP_TIMEOUT                 = 3,                                //命令响应超时  SD_DATA_TIMEOUT                    = 4,                                //数据超时  SD_TX_UNDERRUN                     = 5,                                //传输FIFO运行  SD_RX_OVERRUN                      = 6,                                //接收FIFO运行  SD_START_BIT_ERR                   = 7,                                //在宽总线模式下的所有数据信号上未检测到起始位  SD_CMD_OUT_OF_RANGE                = 8,                                //CMD的参数超出范围  SD_ADDR_MISALIGNED                 = 9,                                //地址没有对齐  SD_BLOCK_LEN_ERR                   = 10,                              //卡不允许传输的块长度,或者传输的字节数与块长度不匹配  SD_ERASE_SEQ_ERR                   = 11,                              //擦除命令序列中发生错误  SD_BAD_ERASE_PARAM                 = 12,                              //删除组的无效选择  SD_WRITE_PROT_VIOLATION            = 13,                              //试图对写保护块进行编程  SD_LOCK_UNLOCK_FAILED              = 14,                              //在unlock命令中检测到序列或密码错误,或者试图访问锁定的卡  SD_COM_CRC_FAILED                  = 15,                              //前一个命令的CRC校验失败  SD_ILLEGAL_CMD                     = 16,                              //命令对卡状态无效  SD_CARD_ECC_FAILED                 = 17,                              //已应用卡内部ECC,但未能更正数据  SD_CC_ERROR                        = 18,                              //内部卡控制错误  SD_GENERAL_UNKNOWN_ERROR           = 19,                              //通用或未知错误  SD_STREAM_READ_UNDERRUN            = 20,                              //卡无法在流读取操作中维持数据传输  SD_STREAM_WRITE_OVERRUN            = 21,                              //卡无法维持流模式下的数据编程  SD_CID_CSD_OVERWRITE               = 22,                              //CID/CSD覆盖错误  SD_WP_ERASE_SKIP                   = 23,                              //只删除了部分地址空间  SD_CARD_ECC_DISABLED               = 24,                              //命令已在不使用内部ECC的情况下执行  SD_ERASE_RESET                     = 25,                              //在执行之前清除了擦除序列,因为收到了一个超出擦除序列的命令  SD_AKE_SEQ_ERROR                   = 26,                              //身份验证顺序错误  SD_INVALID_VOLTRANGE               = 27,  SD_ADDR_OUT_OF_RANGE               = 28,  SD_SWITCH_ERROR                    = 29,  SD_SDIO_DISABLED                   = 30,  SD_SDIO_FUNCTION_BUSY              = 31,  SD_SDIO_FUNCTION_FAILED            = 32,  SD_SDIO_UNKNOWN_FUNCTION           = 33,  //标准错误定义  SD_INTERNAL_ERROR,   SD_NOT_CONFIGURED,  SD_REQUEST_PENDING,   SD_REQUEST_NOT_APPLICABLE,   SD_INVALID_PARAMETER,    SD_UNSUPPORTED_FEATURE,    SD_UNSUPPORTED_HW,    SD_ERROR,    SD_OK = 0 } SD_Error;      //SD卡CSD寄存器数据      typedef struct{  u8  CSDStruct;                                            //CSD结构  u8  SysSpecVersion;                                          //系统版本  u8  Reserved1;                                            //保留  u8  TAAC;                                              //数据读取访问时间1  u8  NSAC;                                              //在CLK期间的数据读取访问时间2  u8  MaxBusClkFrec;                                          //总线最高频率  u16 CardComdClasses;                                        //卡命令类  u8  RdBlockLen;                                            //最大读取数据块长度  u8  PartBlockRead;                                          //允许读取的部分块  u8  WrBlockMisalign;                                        //写入块未对准  u8  RdBlockMisalign;                                        //读取块未对准  u8  DSRImpl;                                            //DSR生效  u8  Reserved2;                                            //保留   u32 DeviceSize;                                            //驱动大小  u8  MaxRdCurrentVDDMin;                                        //最大读取流@ VDD最小  u8  MaxRdCurrentVDDMax;                                        //最大读取流@ VDD最大   u8  MaxWrCurrentVDDMin;                                        //最大写入流@ VDD最小   u8  MaxWrCurrentVDDMax;                                        //最大写入流@ VDD最大   u8  DeviceSizeMul;                                          //驱动大小  u8  EraseGrSize;                                          //擦除组大小  u8  EraseGrMul;                                            //擦除组大小乘数  u8  WrProtectGrSize;                                        //写保护组大小  u8  WrProtectGrEnable;                                        //写保护组使能  u8  ManDeflECC;                                            //制造商默认ECC  u8  WrSpeedFact;                                          //写入速度因子  u8  MaxWrBlockLen;                                          //最大写入数据长度  u8  WriteBlockPaPartial;                                      //允许写入的部分块  u8  Reserved3;                                            //保留  u8  ContentProtectAppli;                                      //内容保护程序  u8  FileFormatGrouop;                                        //文件格式组  u8  CopyFlag;                                            //复制标志OTP   u8  PermWrProtect;                                          //永久写保护  u8  TempWrProtect;                                          //临时写保护  u8  FileFormat;                                            //文件格式  u8  ECC;                                              //ECC 代码  u8  CSD_CRC;                                            //CSD CRC   u8  Reserved4;                                            //总是1} SD_CSD;   //SD卡CID寄存器数据typedef struct{  u8  ManufacturerID;                                          //制造商  u16 OEM_AppliID;                                          //OEM/应用程序ID  u32 ProdName1;                                            //名称部分1  u8  ProdName2;                                            //名称部分2  u8  ProdRev;                                            //版本  u32 ProdSN;                                              //序列号  u8  Reserved1;                                            //保留1  u16 ManufactDate;                                          //出厂日期  u8  CID_CRC;                                            //CID CRC  u8  Reserved2;                                            //总是1} SD_CID;   //SD卡状态typedef enum{  SD_CARD_READY                  = 0x00000001,  SD_CARD_IDENTIFICATION         = 0x00000002,  SD_CARD_STANDBY                = 0x00000003,  SD_CARD_TRANSFER               = 0x00000004,  SD_CARD_SENDING                = 0x00000005,  SD_CARD_RECEIVING              = 0x00000006,  SD_CARD_PROGRAMMING            = 0x00000007,  SD_CARD_DISCONNECTED           = 0x00000008,  SD_CARD_ERROR                  = 0x000000FF}SDCardState;//SD卡信息,包括CSD,CID等数据typedef struct{  SD_CSD SD_csd;  SD_CID SD_cid;  long long CardCapacity;                                        //SD卡容量,单位:字节,最大支持2^64字节大小的卡  u32 CardBlockSize;                                          //SD卡块大小    u16 RCA;                                                //卡相对地址  u8 CardType;                                              //卡类型} SD_CardInfo;extern SD_CardInfo SDCardInfo;                                      //SD卡信息//SDIO相关标志位,拷贝自:stm32f4xx_sdio.h#define SDIO_FLAG_CCRCFAIL                  0x00000001#define SDIO_FLAG_DCRCFAIL                  0x00000002#define SDIO_FLAG_CTIMEOUT                  0x00000004#define SDIO_FLAG_DTIMEOUT                  0x00000008#define SDIO_FLAG_TXUNDERR                  0x00000010#define SDIO_FLAG_RXOVERR                   0x00000020#define SDIO_FLAG_CMDREND                   0x00000040#define SDIO_FLAG_CMDSENT                   0x00000080#define SDIO_FLAG_DATAEND                   0x00000100#define SDIO_FLAG_STBITERR                  0x00000200#define SDIO_FLAG_DBCKEND                   0x00000400#define SDIO_FLAG_CMDACT                    0x00000800#define SDIO_FLAG_TXACT                     0x00001000#define SDIO_FLAG_RXACT                     0x00002000#define SDIO_FLAG_TXFIFOHE                  0x00004000#define SDIO_FLAG_RXFIFOHF                  0x00008000#define SDIO_FLAG_TXFIFOF                   0x00010000#define SDIO_FLAG_RXFIFOF                   0x00020000#define SDIO_FLAG_TXFIFOE                   0x00040000#define SDIO_FLAG_RXFIFOE                   0x00080000#define SDIO_FLAG_TXDAVL                    0x00100000#define SDIO_FLAG_RXDAVL                    0x00200000#define SDIO_FLAG_SDIOIT                    0x00400000#define SDIO_FLAG_CEATAEND                  0x00800000//SDIO 指令集#define SD_CMD_GO_IDLE_STATE                       0#define SD_CMD_SEND_OP_COND                        1#define SD_CMD_ALL_SEND_CID                        2#define SD_CMD_SET_REL_ADDR                        3                        //SD卡的SDIO_SEND_REL_ADDR#define SD_CMD_SET_DSR                             4#define SD_CMD_SDIO_SEN_OP_COND                    5#define SD_CMD_HS_SWITCH                           6#define SD_CMD_SEL_DESEL_CARD                      7#define SD_CMD_HS_SEND_EXT_CSD                     8#define SD_CMD_SEND_CSD                            9#define SD_CMD_SEND_CID                            10#define SD_CMD_READ_DAT_UNTIL_STOP                 11                        //SD卡不支持#define SD_CMD_STOP_TRANSMISSION                   12#define SD_CMD_SEND_STATUS                         13#define SD_CMD_HS_BUSTEST_READ                     14#define SD_CMD_GO_INACTIVE_STATE                   15#define SD_CMD_SET_BLOCKLEN                        16#define SD_CMD_READ_SINGLE_BLOCK                   17#define SD_CMD_READ_MULT_BLOCK                     18#define SD_CMD_HS_BUSTEST_WRITE                    19#define SD_CMD_WRITE_DAT_UNTIL_STOP                20 #define SD_CMD_SET_BLOCK_COUNT                     23 #define SD_CMD_WRITE_SINGLE_BLOCK                  24#define SD_CMD_WRITE_MULT_BLOCK                    25#define SD_CMD_PROG_CID                            26#define SD_CMD_PROG_CSD                            27#define SD_CMD_SET_WRITE_PROT                      28#define SD_CMD_CLR_WRITE_PROT                      29#define SD_CMD_SEND_WRITE_PROT                     30#define SD_CMD_SD_ERASE_GRP_START                  32                        //设置要擦除的第一个写块的地址SD卡独有#define SD_CMD_SD_ERASE_GRP_END                    33                        //设置要擦除的连续范围的最后一个写块的地址SD卡独有#define SD_CMD_ERASE_GRP_START                     35                        //设置要擦除的第一个写块的地址MMC card 3.31#define SD_CMD_ERASE_GRP_END                       36                        //设置要擦除的连续范围的最后一个写块的地址MMC card 3.31#define SD_CMD_ERASE                               38#define SD_CMD_FAST_IO                             39                        //SD卡不支持#define SD_CMD_GO_IRQ_STATE                        40                        //SD卡不支持#define SD_CMD_LOCK_UNLOCK                         42#define SD_CMD_APP_CMD                             55#define SD_CMD_GEN_CMD                             56#define SD_CMD_NO_CMD                              64#define SD_CMD_APP_SD_SET_BUSWIDTH                 6                        //SD卡独有#define SD_CMD_SD_APP_STAUS                        13                        //SD卡独有#define SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS        22                        //SD卡独有#define SD_CMD_SD_APP_OP_COND                      41                        //SD卡独有#define SD_CMD_SD_APP_SET_CLR_CARD_DETECT          42                        //SD卡独有#define SD_CMD_SD_APP_SEND_SCR                     51                        //SD卡独有#define SD_CMD_SDIO_RW_DIRECT                      52                        //SD卡IO独有#define SD_CMD_SDIO_RW_EXTENDED                    53                        //SD卡IO独有#define SD_CMD_SD_APP_GET_MKB                      43                        //SD卡独有#define SD_CMD_SD_APP_GET_MID                      44                        //SD卡独有#define SD_CMD_SD_APP_SET_CER_RN1                  45                        //SD卡独有#define SD_CMD_SD_APP_GET_CER_RN2                  46                        //SD卡独有#define SD_CMD_SD_APP_SET_CER_RES2                 47                        //SD卡独有#define SD_CMD_SD_APP_GET_CER_RES1                 48                        //SD卡独有#define SD_CMD_SD_APP_SECURE_READ_MULTIPLE_BLOCK   18                        //SD卡独有#define SD_CMD_SD_APP_SECURE_WRITE_MULTIPLE_BLOCK  25                        //SD卡独有#define SD_CMD_SD_APP_SECURE_ERASE                 38                        //SD卡独有#define SD_CMD_SD_APP_CHANGE_SECURE_AREA           49                        //SD卡独有#define SD_CMD_SD_APP_SECURE_WRITE_MKB             48                        //SD卡独有//支持的SD卡定义#define SDIO_STD_CAPACITY_SD_CARD_V1_1             0x00000000#define SDIO_STD_CAPACITY_SD_CARD_V2_0             0x00000001#define SDIO_HIGH_CAPACITY_SD_CARD                 0x00000002#define SDIO_MULTIMEDIA_CARD                       0x00000003#define SDIO_SECURE_DIGITAL_IO_CARD                0x00000004#define SDIO_HIGH_SPEED_MULTIMEDIA_CARD            0x00000005#define SDIO_SECURE_DIGITAL_IO_COMBO_CARD          0x00000006#define SDIO_HIGH_CAPACITY_MMC_CARD                0x00000007//SDIO相关参数定义#define NULL 0#define SDIO_STATIC_FLAGS               0x000005FF#define SDIO_CMD0TIMEOUT                0x00010000    #define SDIO_DATATIMEOUT                0xFFFFFFFF    #define SDIO_FIFO_Address               0x40018080//Mask for errors Card Status R1 OCR Register  #define SD_OCR_ADDR_OUT_OF_RANGE        0x80000000#define SD_OCR_ADDR_MISALIGNED          0x40000000#define SD_OCR_BLOCK_LEN_ERR            0x20000000#define SD_OCR_ERASE_SEQ_ERR            0x10000000#define SD_OCR_BAD_ERASE_PARAM          0x08000000#define SD_OCR_WRITE_PROT_VIOLATION     0x04000000#define SD_OCR_LOCK_UNLOCK_FAILED       0x01000000#define SD_OCR_COM_CRC_FAILED           0x00800000#define SD_OCR_ILLEGAL_CMD              0x00400000#define SD_OCR_CARD_ECC_FAILED          0x00200000#define SD_OCR_CC_ERROR                 0x00100000#define SD_OCR_GENERAL_UNKNOWN_ERROR    0x00080000#define SD_OCR_STREAM_READ_UNDERRUN     0x00040000#define SD_OCR_STREAM_WRITE_OVERRUN     0x00020000#define SD_OCR_CID_CSD_OVERWRIETE       0x00010000#define SD_OCR_WP_ERASE_SKIP            0x00008000#define SD_OCR_CARD_ECC_DISABLED        0x00004000#define SD_OCR_ERASE_RESET              0x00002000#define SD_OCR_AKE_SEQ_ERROR            0x00000008#define SD_OCR_ERRORBITS                0xFDFFE008//Masks for R6 Response #define SD_R6_GENERAL_UNKNOWN_ERROR     0x00002000#define SD_R6_ILLEGAL_CMD               0x00004000#define SD_R6_COM_CRC_FAILED            0x00008000#define SD_VOLTAGE_WINDOW_SD            0x80100000#define SD_HIGH_CAPACITY                0x40000000#define SD_STD_CAPACITY                 0x00000000#define SD_CHECK_PATTERN                0x000001AA#define SD_VOLTAGE_WINDOW_MMC           0x80FF8000#define SD_MAX_VOLT_TRIAL               0x0000FFFF#define SD_ALLZERO                      0x00000000#define SD_WIDE_BUS_SUPPORT             0x00040000#define SD_SINGLE_BUS_SUPPORT           0x00010000#define SD_CARD_LOCKED                  0x02000000#define SD_CARD_PROGRAMMING             0x00000007#define SD_CARD_RECEIVING               0x00000006#define SD_DATATIMEOUT                  0xFFFFFFFF#define SD_0TO7BITS                     0x000000FF#define SD_8TO15BITS                    0x0000FF00#define SD_16TO23BITS                   0x00FF0000#define SD_24TO31BITS                   0xFF000000#define SD_MAX_DATA_LENGTH              0x01FFFFFF#define SD_HALFFIFO                     0x00000008#define SD_HALFFIFOBYTES                0x00000020//Command Class Supported  #define SD_CCCC_LOCK_UNLOCK             0x00000080#define SD_CCCC_WRITE_PROT              0x00000040#define SD_CCCC_ERASE                   0x00000020                                 //CMD8指令#define SDIO_SEND_IF_COND               0x00000008/*********************************************************************************************************                  函    数    列    表*********************************************************************************************************/SD_Error SD_Init( void ) ;                                        //初始化SD卡u8 SD_ReadDisk( u8*buf, u32 sector, u8 cnt ) ;                              //读SD卡,fatfs/usb调用u8 SD_WriteDisk( u8*buf, u32 sector, u8 cnt ) ;                              //写SD卡,fatfs/usb调用#endif

(2)创建sdio_sdcard.c文件,并输入以下代码。

#include "sdio_sdcard.h"#include "string.h"SD_CardInfo SDCardInfo ;                                        //SD卡信息u8 CardType=SDIO_STD_CAPACITY_SD_CARD_V1_1 ;                              //SD卡类型/***************************************************Name    :SDIO_Clock_SetFunction  :SDIO发送命令函数Paramater  :      cmdindex:命令索引,低六位有效      waitrsp:期待的相应        00/10:无响应        01:短响应        11:长响应      arg:参数Return    :错误代码***************************************************/void SDIO_Send_Cmd( u8 cmdindex, u8 waitrsp, u32 arg ){        u32 tmpreg ;  SDIO->ARG = arg ;  tmpreg = SDIO->CMD ;  tmpreg &= 0xFFFFF800 ;                                        //清除index和waitrsp  tmpreg |= cmdindex&0X3F ;                                      //设置新的index  tmpreg |= waitrsp<<6 ;                                        //设置新的wait rsp  tmpreg |= 0<<8 ;                                          //无等待  tmpreg |= 1<<10 ;                                          //命令通道状态机使能  SDIO->CMD = tmpreg ;}/***************************************************Name    :SDIO_Send_Data_CfgFunction  :SDIO发送数据配置函数Paramater  :      datatimeout:超时时间设置      datalen:传输数据长度,低25位有效,必须为块大小的整数倍      blksize:块大小.实际大小为:2^blksize字节      dir:数据传输方向        0:控制器到卡        1:卡到控制器Return    :错误代码***************************************************/void SDIO_Send_Data_Cfg( u32 datatimeout, u32 datalen, u8 blksize, u8 dir ){  u32 tmpreg;  SDIO->DTIMER = datatimeout ;  SDIO->DLEN = datalen&0x1FFFFFF ;                                  //低25位有效  tmpreg = SDIO->DCTRL ;   tmpreg &= 0xFFFFFF08 ;                                        //清除之前的设置  tmpreg |= blksize<<4 ;                                        //设置块大小  tmpreg |= 0<<2 ;                                          //块数据传输  tmpreg |= ( dir&0x01 )<<1 ;                                      //方向控制  tmpreg |= 1<<0 ;                                          //数据传输使能,DPSM状态机  SDIO->DCTRL = tmpreg ;}/***************************************************Name    :SDIO_Clock_SetFunction  :SDIO时钟初始化设置Paramater  :      clkdiv:时钟分频系数Return    :错误代码***************************************************/void SDIO_Clock_Set( u8 clkdiv ){  u32 tmpreg = SDIO->CLKCR ;  tmpreg &= 0xFFFFFF00 ;  tmpreg |= clkdiv;  SDIO->CLKCR = tmpreg ;}/***************************************************Name    :CmdErrorFunction  :检查CMD0的执行状态Paramater  :NoneReturn    :错误代码***************************************************/SD_Error CmdError(){  SD_Error errorstatus = SD_OK ;  u32 timeout=SDIO_CMD0TIMEOUT ;  while( timeout-- )  {    //命令已发送(无需响应)    if( SDIO->STA&( 1<<7 ) )      break ;  }  if( timeout==0 )    return SD_CMD_RSP_TIMEOUT ;  SDIO->ICR = 0x5FF ;                                          //清除标记  return errorstatus ;}/***************************************************Name    :CmdResp7ErrorFunction  :检查R7响应的错误状态Paramater  :NoneReturn    :错误代码***************************************************/SD_Error CmdResp7Error(){  u32 status ;  u32 timeout = 0x00010000 ;   while( timeout-- )  {    status = SDIO->STA ;    if( ( status&0x45 )!=0 )                                    //等待接收到应答      break ;  }  //响应超时   if( ( timeout==0 )||( ( status&0x04 )==0x04 ) )  {    //当前卡不是2.0兼容卡,或者不支持设定的电压范围    SDIO->ICR |= 1<<2 ;                                        //清除命令响应超时标志    return SD_CMD_RSP_TIMEOUT ;  }  //成功接收到响应  if( ( status&0x40 )==0x40 )    SDIO->ICR |= 1<<6 ;                                        //清除响应标志  return SD_OK ;}/***************************************************Name    :CmdResp1ErrorFunction  :检查R1响应的错误状态Paramater  :      cmd:当前命令Return    :错误代码***************************************************/SD_Error CmdResp1Error( u8 cmd ){         u32 status ;  while( 1 )  {    status = SDIO->STA ;    if( ( status&0x45 )!=0 )                                    //等待接收到应答      break ;  }  //响应超时  if( ( status&0x04 )==0x04 )  {     SDIO->ICR |= 1<<2 ;                                        //清除命令响应超时标志    return SD_CMD_RSP_TIMEOUT ;  }  //CRC错误   if( ( status&0x01 )==0x01 )  {     SDIO->ICR |= 1<<0;                                        //清除标志    return SD_CMD_CRC_FAIL;  }  if( SDIO->RESPCMD!=cmd )    return SD_ILLEGAL_CMD ;                                      //命令不匹配    SDIO->ICR = 0x5FF ;                                          //清除标记  return ( SD_Error )( SDIO->RESP1&0xFDFFE008 ) ;                            //返回卡响应}/***************************************************Name    :CmdResp3ErrorFunction  :检查R3响应的错误状态Paramater  :NoneReturn    :错误代码***************************************************/SD_Error CmdResp3Error(){  u32 status ;                while( 1 )  {    status = SDIO->STA ;    if( ( status&0x45 )!=0 )                                     //等待接收到应答      break ;  }  //响应超时   if( ( status&0x04 )==0x04 )  {    SDIO->ICR |= 1<<2 ;                                        //清除命令响应超时标志    return SD_CMD_RSP_TIMEOUT ;  }     SDIO->ICR = 0x5FF ;                                          //清除标记   return SD_OK ;}/***************************************************Name    :CmdResp2ErrorFunction  :检查R2响应的错误状态Paramater  :NoneReturn    :错误代码***************************************************/SD_Error CmdResp2Error(){  u32 status ;  u32 timeout = 0x00010000 ;   while( timeout-- )  {    status = SDIO->STA ;    if( ( status&0x45 )!=0 )                                    //接收到R2响应      break ;  }  //响应超时    if( ( timeout==0 )||( ( status&0x04 )==0x04 ) )  {    SDIO->ICR |= 1<<2 ;                                        //清除命令响应超时标志    return SD_CMD_RSP_TIMEOUT ;  }  //CRC错误  if( ( status&0x01 )==0x01 )  {    SDIO->ICR |= 1<<0 ;                                        //清除响应标志    return SD_CMD_CRC_FAIL ;   }  SDIO->ICR = 0x5FF ;                                          //清除标记   return SD_OK ;}/***************************************************Name    :CmdResp6ErrorFunction  :检查R6响应的错误状态Paramater  :      cmd:之前发送的命令      prca:卡返回的RCA地址Return    :错误代码***************************************************/SD_Error CmdResp6Error( u8 cmd, u16 *prca ){  SD_Error errorstatus=SD_OK ;  u32 rspr1, status;   while(1)  {    status = SDIO->STA ;    //CRC错误/命令响应超时/已经收到响应(CRC校验成功)    if( status&( (1<<0)|(1<<2)|(1<<6) ) )      break ;  }  //响应超时  if( status&( 1<<2 ) )  {     SDIO->ICR |= 1<<2 ;                                        //清除命令响应超时标志    return SD_CMD_RSP_TIMEOUT ;  }  //CRC错误  if( status&1<<0 )  {    SDIO->ICR |= 1<<0 ;                                        //清除响应标志     return SD_CMD_CRC_FAIL ;  }  //判断是否响应cmd命令  if( SDIO->RESPCMD!=cmd )     return SD_ILLEGAL_CMD ;  SDIO->ICR = 0x5FF ;                                          //清除所有标记  rspr1 = SDIO->RESP1 ;                                        //得到响应  if( SD_ALLZERO==( rspr1&( SD_R6_GENERAL_UNKNOWN_ERROR|SD_R6_ILLEGAL_CMD|SD_R6_COM_CRC_FAILED ) ) )  {    *prca = ( u16 )( rspr1>>16 ) ;                                  //右移16位得到,rca    return errorstatus ;  }     if( rspr1&SD_R6_GENERAL_UNKNOWN_ERROR )    return SD_GENERAL_UNKNOWN_ERROR ;     if( rspr1&SD_R6_ILLEGAL_CMD )    return SD_ILLEGAL_CMD ;     if( rspr1&SD_R6_COM_CRC_FAILED )    return SD_COM_CRC_FAILED ;  return errorstatus ;}/***************************************************Name    :SDIO_IRQHandlerFunction  :SDIO中断服务函数Paramater  :NoneReturn    :错误代码***************************************************/void SDIO_IRQHandler(){   //接收完成中断  if( SDIO->STA&( 1<<8 ) )  {    SDIO_Send_Cmd( SD_CMD_STOP_TRANSMISSION, 1, 0 ) ;                        //发送CMD12,结束传输     SDIO->ICR |= 1<<8 ;                                        //清除完成中断标记    SDIO->MASK &= ~( ( 1<<1 )|( 1<<3 )|( 1<<8 )|( 1<<14 )|( 1<<15 )|( 1<<4 )|( 1<<5 )|( 1<<9 ) ) ;  //关闭相关中断  }  //数据CRC错误   if( SDIO->STA&( 1<<1 ) )  {    SDIO->ICR |= 1<<1 ;                                        //清除中断标记    SDIO->MASK &= ~( ( 1<<1 )|( 1<<3 )|( 1<<8 )|( 1<<14 )|( 1<<15 )|( 1<<4 )|( 1<<5 )|( 1<<9 ) ) ;  //关闭相关中断  }  //数据超时错误   if( SDIO->STA&( 1<<3 ) )  {    SDIO->ICR |= 1<<3 ;                                        //清除中断标记    SDIO->MASK &= ~( ( 1<<1 )|( 1<<3 )|( 1<<8 )|( 1<<14 )|( 1<<15 )|( 1<<4 )|( 1<<5 )|( 1<<9 ) ) ;  //关闭相关中断  }  //FIFO上溢错误    if( SDIO->STA&( 1<<5 ) )  {    SDIO->ICR |= 1<<5 ;                                        //清除中断标记    SDIO->MASK &= ~( ( 1<<1 )|( 1<<3 )|( 1<<8 )|( 1<<14 )|( 1<<15 )|( 1<<4 )|( 1<<5 )|( 1<<9 ) ) ;  //关闭相关中断  }  //FIFO下溢错误     if( SDIO->STA&( 1<<4 ) )  {    SDIO->ICR |= 1<<4 ;                                        //清除中断标记    SDIO->MASK &= ~( ( 1<<1 )|( 1<<3 )|( 1<<8 )|( 1<<14 )|( 1<<15 )|( 1<<4 )|( 1<<5 )|( 1<<9 ) ) ;  //关闭相关中断  }  //起始位错误  if( SDIO->STA&( 1<<9 ) )  {    SDIO->ICR |= 1<<9 ;                                        //清除中断标记    SDIO->MASK &= ~( ( 1<<1 )|( 1<<3 )|( 1<<8 )|( 1<<14 )|( 1<<15 )|( 1<<4 )|( 1<<5 )|( 1<<9 ) ) ;  //关闭相关中断  }}/***************************************************Name    :SD_PowerONFunction  :卡上电Paramater  :NoneReturn    :错误代码***************************************************/SD_Error SD_PowerON(){  u8 i=0 ;  SD_Error errorstatus=SD_OK ;  u32 response=0, count=0, validvoltage=0 ;  u32 SDType=SD_STD_CAPACITY ;  //配置CLKCR寄存器  SDIO->CLKCR = 0 ;                                          //清空CLKCR之前的设置  SDIO->CLKCR |= 0<<9 ;                                        //非省电模式  SDIO->CLKCR |= 0<<10 ;                                        //关闭旁路,CK根据分频设置输出  SDIO->CLKCR |= 0<<11 ;                                        //1位数据宽度  SDIO->CLKCR |= 0<<13 ;                                        //SDIOCLK上升沿产生SDIOCK  SDIO->CLKCR |= 0<<14 ;                                        //关闭硬件流控制  SDIO_Clock_Set( SDIO_INIT_CLK_DIV ) ;                                //设置时钟频率(初始化的时候,不能超过400Khz)  SDIO->POWER = 0x03 ;                                        //上电状态,开启卡时钟  SDIO->CLKCR |= 1<<8 ;                                        //SDIOCK使能  for( i=0; i<74; i++ )  {    SDIO_Send_Cmd( SD_CMD_GO_IDLE_STATE, 0, 0 ) ;                          //发送CMD0进入IDLE STAGE模式命令    errorstatus = CmdError() ;    if( errorstatus==SD_OK )      break ;  }  //返回错误状态  if( errorstatus )    return errorstatus ;  SDIO_Send_Cmd( SDIO_SEND_IF_COND, 1, SD_CHECK_PATTERN ) ;                      //发送CMD8,短响应,检查SD卡接口特性  errorstatus = CmdResp7Error() ;                                    //等待R7响应  //R7响应正常  if( errorstatus==SD_OK )  {    CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0 ;                            //SD 2.0卡    SDType = SD_HIGH_CAPACITY ;                                    //高容量卡  }  SDIO_Send_Cmd( SD_CMD_APP_CMD, 1, 0 ) ;                                //发送CMD55,短响应  errorstatus = CmdResp1Error( SD_CMD_APP_CMD ) ;                            //等待R1响应  //SD2.0/SD 1.1,否则为MMC卡  if( errorstatus==SD_OK )  {    //SD卡,发送ACMD41 SD_APP_OP_COND,参数为:0x80100000    while( ( !validvoltage )&&( count    {      SDIO_Send_Cmd( SD_CMD_APP_CMD, 1, 0 ) ;                            //发送CMD55,短响应      errorstatus = CmdResp1Error( SD_CMD_APP_CMD ) ;                        //等待R1响应      //响应错误      if( errorstatus!=SD_OK )      return errorstatus ;      SDIO_Send_Cmd( SD_CMD_SD_APP_OP_COND, 1, SD_VOLTAGE_WINDOW_SD|SDType );            //发送ACMD41,短响应      errorstatus = CmdResp3Error() ;                                //等待R3响应      //响应错误      if( errorstatus!=SD_OK )      return errorstatus ;      response = SDIO->RESP1 ;                                  //得到响应      validvoltage = ( ( ( response>>31 )==1 )?1:0 ) ;                      //判断SD卡上电是否完成      count ++ ;    }    if( count>=SD_MAX_VOLT_TRIAL )    {      errorstatus = SD_INVALID_VOLTRANGE ;      return errorstatus ;    }    if( response&=SD_HIGH_CAPACITY )      CardType = SDIO_HIGH_CAPACITY_SD_CARD ;  }  return errorstatus ;}/***************************************************Name    :SD_InitializeCardsFunction  :初始化所有的卡Paramater  :NoneReturn    :错误代码***************************************************/u32 CSD_Tab[ 4 ], CID_Tab[ 4 ], RCA=0 ;                                  //SD卡CSD,CID以及相对地址(RCA)数据SD_Error SD_InitializeCards(){   SD_Error errorstatus=SD_OK ;  u16 rca = 0x01 ;  //检查电源状态,确保为上电状态   if( ( SDIO->POWER&0x03 )==0 )    return SD_REQUEST_NOT_APPLICABLE ;  //非SECURE_DIGITAL_IO_CARD   if( SDIO_SECURE_DIGITAL_IO_CARD!=CardType )  {    SDIO_Send_Cmd( SD_CMD_ALL_SEND_CID, 3, 0 ) ;                          //发送CMD2,取得CID,长响应    errorstatus = CmdResp2Error() ;                                  //等待R2响应    //响应错误    if( errorstatus!=SD_OK )      return errorstatus;     CID_Tab[ 0 ] = SDIO->RESP1 ;    CID_Tab[ 1 ] = SDIO->RESP2 ;    CID_Tab[ 2 ] = SDIO->RESP3 ;    CID_Tab[ 3 ] = SDIO->RESP4 ;  }  //判断卡类型  if( ( SDIO_STD_CAPACITY_SD_CARD_V1_1==CardType )||( SDIO_STD_CAPACITY_SD_CARD_V2_0==CardType )||( SDIO_SECURE_DIGITAL_IO_COMBO_CARD==CardType )||( SDIO_HIGH_CAPACITY_SD_CARD==CardType ) )  {    SDIO_Send_Cmd( SD_CMD_SET_REL_ADDR, 1, 0 ) ;                          //发送CMD3,短响应    errorstatus = CmdResp6Error( SD_CMD_SET_REL_ADDR, &rca ) ;                    //等待R6响应    //响应错误    if( errorstatus!=SD_OK )      return errorstatus ;  }    if( SDIO_MULTIMEDIA_CARD==CardType )    {     SDIO_Send_Cmd( SD_CMD_SET_REL_ADDR, 1, ( u32 )( rca<<16 ) ) ;                  //发送CMD3,短响应    errorstatus = CmdResp2Error() ;                                  //等待R2响应    //响应错误    if( errorstatus!=SD_OK )      return errorstatus ;    }  //非SECURE_DIGITAL_IO_CARD  if( SDIO_SECURE_DIGITAL_IO_CARD!=CardType )  {    RCA = rca ;    SDIO_Send_Cmd( SD_CMD_SEND_CSD, 3, ( u32 )( rca<<16 ) ) ;                    //发送CMD9+卡RCA,取得CSD,长响应    errorstatus = CmdResp2Error() ;                                  //等待R2响应    //响应错误    if( errorstatus!=SD_OK )      return errorstatus ;      CSD_Tab[ 0 ] = SDIO->RESP1 ;    CSD_Tab[ 1 ] = SDIO->RESP2 ;    CSD_Tab[ 2 ] = SDIO->RESP3 ;    CSD_Tab[ 3 ] = SDIO->RESP4 ;  }  return SD_OK ;                                            //卡初始化成功}/***************************************************Name    :SD_GetCardInfoFunction  :得到卡信息Paramater  :      cardinfo:卡信息存储区Return    :错误代码***************************************************/SD_Error SD_GetCardInfo( SD_CardInfo *cardinfo ){   SD_Error errorstatus = SD_OK ;  u8 tmp = 0 ;       cardinfo->CardType = ( u8 )CardType ;                                //卡类型  cardinfo->RCA = ( u16 )RCA ;                                    //卡RCA值  tmp = ( u8 )( ( CSD_Tab[ 0 ]&0xFF000000 )>>24 ) ;  cardinfo->SD_csd.CSDStruct = ( tmp&0xC0 )>>6 ;                            //CSD结构  cardinfo->SD_csd.SysSpecVersion = ( tmp&0x3C )>>2 ;                          //2.0协议还没定义这部分(为保留),应该是后续协议定义的  cardinfo->SD_csd.Reserved1 = tmp&0x03 ;                                //2个保留位    tmp = ( u8 )( ( CSD_Tab[ 0 ]&0x00FF0000 )>>16 ) ;                          //第1个字节  cardinfo->SD_csd.TAAC = tmp ;                                    //数据读时间1  tmp = ( u8 )( ( CSD_Tab[ 0 ]&0x0000FF00 )>>8 ) ;                          //第2个字节  cardinfo->SD_csd.NSAC = tmp ;                                    //数据读时间2  tmp = ( u8 )( CSD_Tab[ 0 ]&0x000000FF ) ;                              //第3个字节  cardinfo->SD_csd.MaxBusClkFrec = tmp ;                                //传输速度       tmp = ( u8 )( ( CSD_Tab[ 1 ]&0xFF000000 )>>24 ) ;                          //第4个字节  cardinfo->SD_csd.CardComdClasses = tmp<<4 ;                              //卡指令类高四位  tmp = ( u8 )( ( CSD_Tab[ 1 ]&0x00FF0000 )>>16 ) ;                          //第5个字节  cardinfo->SD_csd.CardComdClasses |= ( tmp&0xF0 )>>4 ;                        //卡指令类低四位  cardinfo->SD_csd.RdBlockLen = tmp&0x0F ;                              //最大读取数据长度  tmp = ( u8 )( ( CSD_Tab[ 1 ]&0x0000FF00 )>>8 ) ;                          //第6个字节  cardinfo->SD_csd.PartBlockRead = ( tmp&0x80 )>>7 ;                          //允许分块读  cardinfo->SD_csd.WrBlockMisalign = ( tmp&0x40 )>>6 ;                        //写块错位  cardinfo->SD_csd.RdBlockMisalign = ( tmp&0x20 )>>5 ;                        //读块错位  cardinfo->SD_csd.DSRImpl = ( tmp&0x10 )>>4 ;  cardinfo->SD_csd.Reserved2 = 0 ;                                  //保留  //标准1.1/2.0卡/MMC卡   if( ( CardType==SDIO_STD_CAPACITY_SD_CARD_V1_1 )||( CardType==SDIO_STD_CAPACITY_SD_CARD_V2_0 )||( SDIO_MULTIMEDIA_CARD==CardType ) )  {    cardinfo->SD_csd.DeviceSize = ( tmp&0x03 )<<10 ;                        //C_SIZE(12位)     tmp = ( u8 )( CSD_Tab[ 1 ]&0x000000FF ) ;                            //第7个字节    cardinfo->SD_csd.DeviceSize |= tmp<<2 ;     tmp = ( u8 )( ( CSD_Tab[ 2 ]&0xFF000000 )>>24 );                        //第8个字节    cardinfo->SD_csd.DeviceSize |= ( tmp&0xC0 )>>6 ;     cardinfo->SD_csd.MaxRdCurrentVDDMin = ( tmp&0x38 )>>3 ;    cardinfo->SD_csd.MaxRdCurrentVDDMax = ( tmp&0x07 ) ;     tmp = ( u8 )( ( CSD_Tab[ 2 ]&0x00FF0000 )>>16 ) ;                        //第9个字节    cardinfo->SD_csd.MaxWrCurrentVDDMin = ( tmp&0xE0 )>>5 ;    cardinfo->SD_csd.MaxWrCurrentVDDMax = ( tmp&0x1C )>>2 ;    cardinfo->SD_csd.DeviceSizeMul = ( tmp&0x03 )<<1 ;                        //C_SIZE_MULT     tmp = ( u8 )( ( CSD_Tab[ 2 ]&0x0000FF00 )>>8 ) ;                        //第10个字节    cardinfo->SD_csd.DeviceSizeMul |= ( tmp&0x80 )>>7 ;     cardinfo->CardCapacity = ( cardinfo->SD_csd.DeviceSize+1 ) ;                  //计算卡容量    cardinfo->CardCapacity *= ( 1<SD_csd.DeviceSizeMul+2 ) ) ;    cardinfo->CardBlockSize = 1<SD_csd.RdBlockLen ) ;                  //块大小    cardinfo->CardCapacity *= cardinfo->CardBlockSize ;  }  //高容量卡  else if( CardType==SDIO_HIGH_CAPACITY_SD_CARD )  {     tmp = ( u8 )( CSD_Tab[ 1 ]&0x000000FF  );                            //第7个字节      cardinfo->SD_csd.DeviceSize = ( tmp&0x3F )<<16 ;                        //C_SIZE     tmp = ( u8 )( ( CSD_Tab[ 2 ]&0xFF000000 )>>24 ) ;                        //第8个字节       cardinfo->SD_csd.DeviceSize |= ( tmp<<8 ) ;     tmp = ( u8 )( ( CSD_Tab[ 2 ]&0x00FF0000 )>>16 ) ;                        //第9个字节       cardinfo->SD_csd.DeviceSize |= tmp ;     tmp = ( u8 )( ( CSD_Tab[ 2 ]&0x0000FF00 )>>8 ) ;                        //第10个字节       cardinfo->CardCapacity = ( long long )( cardinfo->SD_csd.DeviceSize+1 )*512*1024 ;        //计算卡容量    cardinfo->CardBlockSize = 512 ;                                  //块大小固定为512字节  }  cardinfo->SD_csd.EraseGrSize = ( tmp&0x40 )>>6 ;  cardinfo->SD_csd.EraseGrMul = ( tmp&0x3F )<<1 ;       tmp = ( u8 )( CSD_Tab[ 2 ]&0x000000FF ) ;                              //第11个字节  cardinfo->SD_csd.EraseGrMul |= ( tmp&0x80 )>>7 ;  cardinfo->SD_csd.WrProtectGrSize=( tmp&0x7F ) ;   tmp = ( u8 )( ( CSD_Tab[ 3 ]&0xFF000000 )>>24 ) ;                          //第12个字节  cardinfo->SD_csd.WrProtectGrEnable = ( tmp&0x80 )>>7 ;  cardinfo->SD_csd.ManDeflECC = ( tmp&0x60 )>>5 ;  cardinfo->SD_csd.WrSpeedFact = ( tmp&0x1C )>>2 ;  cardinfo->SD_csd.MaxWrBlockLen=( tmp&0x03 )<<2 ;  tmp = ( u8 )( ( CSD_Tab[ 3 ]&0x00FF0000 )>>16 ) ;                          //第13个字节  cardinfo->SD_csd.MaxWrBlockLen |= ( tmp&0xC0 )>>6 ;  cardinfo->SD_csd.WriteBlockPaPartial = ( tmp&0x20 )>>5 ;  cardinfo->SD_csd.Reserved3 = 0 ;  cardinfo->SD_csd.ContentProtectAppli=(tmp&0x01);  tmp = ( u8 )( ( CSD_Tab[ 3 ]&0x0000FF00 )>>8 ) ;                          //第14个字节  cardinfo->SD_csd.FileFormatGrouop = ( tmp&0x80 )>>7 ;  cardinfo->SD_csd.CopyFlag = ( tmp&0x40 )>>6 ;  cardinfo->SD_csd.PermWrProtect = ( tmp&0x20 )>>5 ;  cardinfo->SD_csd.TempWrProtect = ( tmp&0x10 )>>4 ;  cardinfo->SD_csd.FileFormat = ( tmp&0x0C )>>2 ;  cardinfo->SD_csd.ECC = ( tmp&0x03 ) ;  tmp = ( u8 )( CSD_Tab[ 3 ]&0x000000FF ) ;                              //第15个字节  cardinfo->SD_csd.CSD_CRC = ( tmp&0xFE )>>1 ;  cardinfo->SD_csd.Reserved4 = 1 ;  tmp = ( u8 )( ( CID_Tab[ 0 ]&0xFF000000 )>>24 ) ;                          //第0个字节  cardinfo->SD_cid.ManufacturerID = tmp ;  tmp = ( u8 )( ( CID_Tab[ 0 ]&0x00FF0000 )>>16 ) ;                          //第1个字节  cardinfo->SD_cid.OEM_AppliID=tmp<<8;  tmp = ( u8 )( ( CID_Tab[ 0 ]&0x000000FF00 )>>8 ) ;                          //第2个字节  cardinfo->SD_cid.OEM_AppliID |= tmp ;  tmp = ( u8 )( CID_Tab[ 0 ]&0x000000FF ) ;                              //第3个字节    cardinfo->SD_cid.ProdName1 = tmp<<24 ;  tmp = ( u8 )( ( CID_Tab[ 1 ]&0xFF000000 )>>24 ) ;                           //第4个字节  cardinfo->SD_cid.ProdName1 |= tmp<<16 ;  tmp = ( u8 )( ( CID_Tab[ 1 ]&0x00FF0000 )>>16 ) ;                             //第5个字节  cardinfo->SD_cid.ProdName1 |= tmp<<8 ;  tmp = ( u8 )( ( CID_Tab[ 1 ]&0x0000FF00 )>>8 ) ;                          //第6个字节  cardinfo->SD_cid.ProdName1 |= tmp ;  tmp = ( u8 )( CID_Tab[ 1 ]&0x000000FF ) ;                              //第7个字节  cardinfo->SD_cid.ProdName2 = tmp ;  tmp = ( u8 )( ( CID_Tab[ 2 ]&0xFF000000 )>>24 ) ;                          //第8个字节  cardinfo->SD_cid.ProdRev = tmp ;  tmp = ( u8 )( ( CID_Tab[ 2 ]&0x00FF0000 )>>16 ) ;                          //第9个字节  cardinfo->SD_cid.ProdSN = tmp<<24 ;  tmp = ( u8 )( ( CID_Tab[ 2 ]&0x0000FF00 )>>8 ) ;                          //第10个字节  cardinfo->SD_cid.ProdSN |= tmp<<16 ;  tmp = ( u8 )( CID_Tab[ 2 ]&0x000000FF );                              //第11个字节  cardinfo->SD_cid.ProdSN |= tmp<<8 ;  tmp = ( u8 )( ( CID_Tab[ 3 ]&0xFF000000 )>>24 ) ;                          //第12个字节  cardinfo->SD_cid.ProdSN |= tmp ;  tmp = ( u8 )( ( CID_Tab[ 3 ]&0x00FF0000 )>>16 ) ;                          //第13个字节  cardinfo->SD_cid.Reserved1 |= ( tmp&0xF0 )>>4 ;  cardinfo->SD_cid.ManufactDate = ( tmp&0x0F )<<8 ;  tmp = ( u8 )( ( CID_Tab[ 3 ]&0x0000FF00 )>>8 ) ;                          //第14个字节  cardinfo->SD_cid.ManufactDate |= tmp ;  tmp = ( u8 )( CID_Tab[ 3 ]&0x000000FF ) ;                              //第15个字节  cardinfo->SD_cid.CID_CRC = ( tmp&0xFE )>>1 ;  cardinfo->SD_cid.Reserved2 = 1 ;  return errorstatus ;}/***************************************************Name    :FindSCRFunction  :查找SD卡的SCR寄存器值Paramater  :      rca:卡相对地址      pscr:数据缓存区(存储SCR内容)Return    :错误代码***************************************************/     SD_Error FindSCR( u16 rca, u32 *pscr ){   u32 index = 0 ;   SD_Error errorstatus = SD_OK ;  u32 tempscr[ 2 ] = { 0, 0 } ;   SDIO_Send_Cmd( SD_CMD_SET_BLOCKLEN, 1, 8 ) ;                            //发送CMD16,短响应,设置Block Size为8字节   errorstatus = CmdResp1Error( SD_CMD_SET_BLOCKLEN ) ;   if( errorstatus!=SD_OK )    return errorstatus ;    SDIO_Send_Cmd( SD_CMD_APP_CMD, 1, ( u32 )rca<<16 ) ;                        //发送CMD55,短响应   errorstatus = CmdResp1Error( SD_CMD_APP_CMD ) ;   if( errorstatus!=SD_OK )    return errorstatus ;  SDIO_Send_Data_Cfg( SD_DATATIMEOUT, 8, 3, 1 ) ;                            //8个字节长度,block为8字节,SD卡到SDIO     SDIO_Send_Cmd( SD_CMD_SD_APP_SEND_SCR, 1, 0 ) ;                            //发送ACMD51,短响应,参数为0   errorstatus = CmdResp1Error( SD_CMD_SD_APP_SEND_SCR ) ;   if( errorstatus!=SD_OK )    return errorstatus ;   while( !( SDIO->STA&( SDIO_FLAG_RXOVERR|SDIO_FLAG_DCRCFAIL|SDIO_FLAG_DTIMEOUT|SDIO_FLAG_DBCKEND|SDIO_FLAG_STBITERR ) ) )  {    //接收FIFO数据可用    if( SDIO->STA&( 1<<21 ) )    {      *( tempscr+index ) = SDIO->FIFO ;                              //读取FIFO内容      index ++ ;      if( index>=2 )        break ;    }  }  //接收数据超时   if( SDIO->STA&( 1<<3 ) )  {     SDIO->ICR |= 1<<3 ;                                        //清除标记    return SD_DATA_TIMEOUT ;  }  //已发送/接收的数据块CRC校验错误  else if( SDIO->STA&( 1<<1 ) )  {     SDIO->ICR |= 1<<1 ;                                        //清除标记    return SD_DATA_CRC_FAIL ;  }  //接收FIFO溢出  else if( SDIO->STA&( 1<<5 ) )  {     SDIO->ICR |= 1<<5 ;                                        //清除标记    return SD_RX_OVERRUN ;  }  //起始位检测错误  else if( SDIO->STA&( 1<<9 ) )  {     SDIO->ICR |= 1<<9 ;                                        //清除标记    return SD_START_BIT_ERR ;      }     SDIO->ICR = 0X5FF ;                                          //清除标记     //把数据顺序按8位为单位倒过来.  *( pscr+1 ) = ( ( tempscr[ 0 ]&SD_0TO7BITS )<<24 )|( ( tempscr[ 0 ]&SD_8TO15BITS )<<8 )|( ( tempscr[ 0 ]&SD_16TO23BITS )>>8 )|( ( tempscr[ 0 ]&SD_24TO31BITS )>>24 ) ;  *( pscr )   = ( ( tempscr[ 1 ]&SD_0TO7BITS )<<24 )|( ( tempscr[ 1 ]&SD_8TO15BITS )<<8 )|( ( tempscr[ 1 ]&SD_16TO23BITS )>>8 )|( ( tempscr[ 1 ]&SD_24TO31BITS )>>24 ) ;   return errorstatus ;}/***************************************************Name    :SDEnWideBusFunction  :SDIO使能宽总线模式Paramater  :      enx:使能开关        0:不使能        1:使能Return    :错误代码***************************************************/SD_Error SDEnWideBus( u8 enx ){  SD_Error errorstatus = SD_OK ;   u32 scr[ 2 ] = { 0, 0 } ;  u8 arg = 0x00 ;  if( enx )    arg = 0x02 ;  else    arg = 0x00 ;  //SD卡处于LOCKED状态   if( SDIO->RESP1&SD_CARD_LOCKED )    return SD_LOCK_UNLOCK_FAILED ;   errorstatus = FindSCR( RCA, scr );                                  //得到SCR寄存器数据   if( errorstatus!=SD_OK )    return errorstatus ;  //支持宽总线  if( ( scr[ 1 ]&SD_WIDE_BUS_SUPPORT )!=SD_ALLZERO )  {     SDIO_Send_Cmd( SD_CMD_APP_CMD, 1, ( u32 )RCA<<16 );                        //发送CMD55+RCA,短响应     errorstatus = CmdResp1Error( SD_CMD_APP_CMD ) ;     if( errorstatus!=SD_OK )      return errorstatus ;     SDIO_Send_Cmd( SD_CMD_APP_SD_SET_BUSWIDTH, 1, arg ) ;                      //发送ACMD6,短响应,参数:10,4位;00,1位    errorstatus = CmdResp1Error( SD_CMD_APP_SD_SET_BUSWIDTH ) ;    return errorstatus ;  }  else    return SD_REQUEST_NOT_APPLICABLE ;                                //不支持宽总线设置}/***************************************************Name    :SD_EnableWideBusOperationFunction  :设置SDIO总线宽度Paramater  :      wmode:位宽模式        0->1位数据宽度        1->4位数据宽度        2->8位数据宽度Return    :错误代码***************************************************/SD_Error SD_EnableWideBusOperation( u32 wmode ){    SD_Error errorstatus = SD_OK ;   if( SDIO_MULTIMEDIA_CARD==CardType )    return SD_UNSUPPORTED_FEATURE ;                                  //MMC卡不支持   else if( ( SDIO_STD_CAPACITY_SD_CARD_V1_1==CardType )||( SDIO_STD_CAPACITY_SD_CARD_V2_0==CardType )||( SDIO_HIGH_CAPACITY_SD_CARD==CardType ) )  {    if( wmode>=2 )      return SD_UNSUPPORTED_FEATURE ;                                //不支持8位模式     else       {      errorstatus = SDEnWideBus( wmode ) ;       if( SD_OK==errorstatus )      {        SDIO->CLKCR &= ~( 3<<11 ) ;                                //清除之前的位宽设置            SDIO->CLKCR |= ( u16 )wmode<<11 ;                            //1位/4位总线宽度         SDIO->CLKCR |= 0<<14 ;                                  //不开启硬件流控制      }    }    }  return errorstatus ;}/***************************************************Name    :SD_InitFunction  :初始化SD卡Paramater  :NoneReturn    :错误代码***************************************************/SD_Error SD_Init(){  u8 clkdiv=0 ;  SD_Error errorstatus=SD_OK ;  //SDIO IO口初始化  RCC->APB2ENR |= 1<<4 ;                                        //使能PC时钟  RCC->APB2ENR |= 1<<5 ;                                        //使能PD时钟  RCC->AHBENR |= 1<<10 ;                                        //使能SDIO时钟  RCC->AHBENR |= 1<<1 ;                                        //使能DMA2时钟  GPIOC->CRH &= 0xFFF00000 ;  GPIOC->CRH |= 0x000BBBBB ;                                      //PC.8~12 复用输出  GPIOD->CRL &= 0xFFFFF0FF ;  GPIOD->CRL |= 0x00000B00 ;                                      //PD2复用输出  //SDIO外设寄存器设置为默认值  SDIO->POWER = 0x00000000 ;  SDIO->CLKCR = 0x00000000 ;  SDIO->ARG = 0x00000000 ;  SDIO->CMD = 0x00000000 ;  SDIO->DTIMER = 0x00000000 ;  SDIO->DLEN = 0x00000000 ;  SDIO->DCTRL = 0x00000000 ;  SDIO->ICR = 0x00C007FF ;  SDIO->MASK = 0x00000000 ;  NVIC_Init( 0, 0, SDIO_IRQn, 2 ) ;                                  //SDIO中断配置     errorstatus = SD_PowerON() ;                                    //SD卡上电   if( errorstatus==SD_OK )    errorstatus=SD_InitializeCards() ;                                //初始化SD卡                                  if( errorstatus==SD_OK )    errorstatus=SD_GetCardInfo( &SDCardInfo ) ;                            //获取卡信息   if( errorstatus==SD_OK )  {    SDIO_Send_Cmd( SD_CMD_SEL_DESEL_CARD, 1, SDCardInfo.RCA<<16 ) ;                  //发送CMD7,选择卡,短响应            errorstatus = CmdResp1Error( SD_CMD_SEL_DESEL_CARD ) ;  }     if( errorstatus==SD_OK )    errorstatus=SD_EnableWideBusOperation( 1 ) ;                          //4位宽度,如果是MMC卡,则不能用4位模式     if( ( errorstatus==SD_OK )||( SDIO_MULTIMEDIA_CARD==CardType ) )  {    if( ( SDCardInfo.CardType==SDIO_STD_CAPACITY_SD_CARD_V1_1 )||( SDCardInfo.CardType==SDIO_STD_CAPACITY_SD_CARD_V2_0 ) )      clkdiv = SDIO_TRANSFER_CLK_DIV+6 ;                              //V1.1/V2.0卡,设置最高72/12=6Mhz    else      clkdiv = SDIO_TRANSFER_CLK_DIV ;                              //SDHC等其他卡,设置最高72/6=12Mhz    SDIO_Clock_Set( clkdiv );                                    //设置时钟频率   }  return errorstatus ;}/***************************************************Name    :convert_from_bytes_to_power_of_twoFunction  :得到NumberOfBytes以2为底的指数Paramater  :      NumberOfBytes:字节数Return    :以2为底的指数值***************************************************/u8 convert_from_bytes_to_power_of_two( u16 NumberOfBytes ){  u8 count=0 ;  while( NumberOfBytes!=1 )  {    NumberOfBytes >>= 1 ;    count ++ ;  }  return count ;}/***************************************************Name    :SD_ReadBlockFunction  :读取一个块Paramater  :      buf:读数据缓存区(必须4字节对齐)      addr:读取地址      blksize:块大小Return    :错误代码***************************************************/SD_Error SD_ReadBlock( u8 *buf, long long addr, u16 blksize ){      SD_Error errorstatus = SD_OK ;  u8 power ;     u32 count=0, *tempbuff=( u32* )buf ;                                //转换为u32指针  u32 timeout = SDIO_DATATIMEOUT ;     if( NULL==buf )    return SD_INVALID_PARAMETER ;     SDIO->DCTRL = 0x0 ;                                          //数据控制寄存器清零(关DMA)  //大容量卡  if( CardType==SDIO_HIGH_CAPACITY_SD_CARD )  {    blksize = 512 ;    addr >>= 9 ;  }       SDIO_Send_Data_Cfg( SD_DATATIMEOUT, 0, 0, 0 ) ;                            //清除DPSM状态机配置  //卡锁了  if( SDIO->RESP1&SD_CARD_LOCKED )    return SD_LOCK_UNLOCK_FAILED ;  if( ( blksize>0 )&&( blksize<=2048 )&&( ( blksize&( blksize-1 ) )==0 ) )  {    power = convert_from_bytes_to_power_of_two( blksize ) ;    SDIO_Send_Cmd( SD_CMD_SET_BLOCKLEN, 1, blksize ) ;                        //发送CMD16+设置数据长度为blksize,短响应    errorstatus = CmdResp1Error( SD_CMD_SET_BLOCKLEN ) ;                      //等待R1响应    //响应错误    if( errorstatus!=SD_OK )      return errorstatus ;  }  else    return SD_INVALID_PARAMETER ;                                  SDIO_Send_Data_Cfg( SD_DATATIMEOUT, blksize, power, 1 ) ;                      //blksize,卡到控制器     SDIO_Send_Cmd( SD_CMD_READ_SINGLE_BLOCK, 1, addr ) ;                        //发送CMD17+从addr地址出读取数据,短响应  errorstatus = CmdResp1Error( SD_CMD_READ_SINGLE_BLOCK ) ;                      //等待R1响应  //响应错误  if( errorstatus!=SD_OK )    return errorstatus ;  __asm volatile( "cpsid i" ) ;                                    //关闭总中断(POLLING模式,严禁中断打断SDIO读写操作!!!)  //无上溢/CRC/超时/完成(标志)/起始位错误  while( !( SDIO->STA&( ( 1<<5 )|( 1<<1 )|( 1<<3 )|( 1<<10 )|( 1<<9 ) ) ) )  {    //接收区半满,表示至少存了8个字    if( SDIO->STA&( 1<<15 ) )    {      for( count=0; count<8; count++ )                              //循环读取数据        *( tempbuff+count ) = SDIO->FIFO ;      tempbuff += 8 ;         timeout = 0x7FFFFF ;                                    //读数据溢出时间    }    //处理超时    else    {      if( timeout==0 )        return SD_DATA_TIMEOUT ;      timeout -- ;    }  }  //数据超时错误  if( SDIO->STA&( 1<<3 ) )  {    SDIO->ICR |= 1<<3 ;                                        //清错误标志    return SD_DATA_TIMEOUT ;  }  //数据块CRC错误  else if( SDIO->STA&( 1<<1 ) )  {    SDIO->ICR |= 1<<1 ;                                        //清错误标志    return SD_DATA_CRC_FAIL ;  }  //接收FIFO上溢错误  else if( SDIO->STA&( 1<<5 ) )  {    SDIO->ICR |= 1<<5 ;                                        //清错误标志    return SD_RX_OVERRUN ;  }  //接收起始位错误  else if( SDIO->STA&( 1<<9 ) )  {    SDIO->ICR |= 1<<9 ;                                        //清错误标志    return SD_START_BIT_ERR ;  }  //FIFO里面,还存在可用数据  while( SDIO->STA&( 1<<21 ) )  {    *tempbuff = SDIO->FIFO ;                                    //循环读取数据    tempbuff ++ ;  }  __asm volatile( "cpsie i" ) ;                                    //开启总中断  SDIO->ICR = 0x5FF ;                                          //清除所有标记   return errorstatus ;}/***************************************************Name    :SD_ReadMultiBlocksFunction  :读取多个块Paramater  :      buf:读数据缓存区(必须4字节对齐)      addr:读取地址      blksize:块大小      nblks:要读取的块数Return    :错误代码***************************************************/__align(4) u32 *tempbuff ;SD_Error SD_ReadMultiBlocks( u8 *buf, long long addr, u16 blksize, u32 nblks ){    SD_Error errorstatus = SD_OK ;  u8 power ;     u32 count = 0 ;  u32 timeout = SDIO_DATATIMEOUT ;  tempbuff = ( u32* )buf ;                                      //转换为u32指针    SDIO->DCTRL = 0x0 ;                                          //数据控制寄存器清零(关DMA)  //大容量卡  if( CardType==SDIO_HIGH_CAPACITY_SD_CARD )  {    blksize = 512 ;    addr >>= 9 ;  }     SDIO_Send_Data_Cfg( SD_DATATIMEOUT, 0, 0, 0 ) ;                            //清除DPSM状态机配置  //卡锁了  if( SDIO->RESP1&SD_CARD_LOCKED )    return SD_LOCK_UNLOCK_FAILED ;  if( ( blksize>0 )&&( blksize<=2048 )&&( ( blksize&( blksize-1 ) )==0 ) )  {    power = convert_from_bytes_to_power_of_two( blksize ) ;    SDIO_Send_Cmd( SD_CMD_SET_BLOCKLEN, 1, blksize ) ;                        //发送CMD16+设置数据长度为blksize,短响应    errorstatus = CmdResp1Error( SD_CMD_SET_BLOCKLEN ) ;                      //等待R1响应    //响应错误    if( errorstatus!=SD_OK )      return errorstatus ;  }  else    return SD_INVALID_PARAMETER ;  //多块读  if( nblks>1 )  {    //判断是否超过最大接收长度       if( nblks*blksize>SD_MAX_DATA_LENGTH )      return SD_INVALID_PARAMETER ;    SDIO_Send_Data_Cfg( SD_DATATIMEOUT, nblks*blksize, power, 1 ) ;                  //nblks*blksize,512块大小,卡到控制器      SDIO_Send_Cmd( SD_CMD_READ_MULT_BLOCK, 1, addr ) ;                        //发送CMD18+从addr地址出读取数据,短响应    errorstatus = CmdResp1Error( SD_CMD_READ_MULT_BLOCK ) ;                      //等待R1响应    //响应错误    if( errorstatus!=SD_OK )      return errorstatus ;    __asm volatile( "cpsid i" ) ;                                  //关闭总中断(POLLING模式,严禁中断打断SDIO读写操作!!!)    //无上溢/CRC/超时/完成(标志)/起始位错误    while( !( SDIO->STA&( ( 1<<5 )|( 1<<1 )|( 1<<3 )|( 1<<8 )|( 1<<9 ) ) ) )    {      //接收区半满,表示至少存了8个字      if( SDIO->STA&( 1<<15 ) )      {        //循环读取数据        for( count=0; count<8; count++ )          *( tempbuff+count ) = SDIO->FIFO ;        tempbuff += 8 ;        timeout = 0X7FFFFF ;                                  //读数据溢出时间      }      //处理超时      else      {        if( timeout==0 )          return SD_DATA_TIMEOUT ;        timeout -- ;      }    }    //数据超时错误    if( SDIO->STA&( 1<<3 ) )    {      SDIO->ICR |= 1<<3 ;                                      //清错误标志      return SD_DATA_TIMEOUT;    }    //数据块CRC错误    else if( SDIO->STA&( 1<<1 ) )    {      SDIO->ICR |= 1<<1 ;                                      //清错误标志      return SD_DATA_CRC_FAIL ;    }    //接收fifo上溢错误    else if( SDIO->STA&( 1<<5 ) )    {      SDIO->ICR |= 1<<5 ;                                      //清错误标志      return SD_RX_OVERRUN;    }    //接收起始位错误    else if( SDIO->STA&( 1<<9 ) )    {      SDIO->ICR |= 1<<9 ;                                      //清错误标志      return SD_START_BIT_ERR ;    }    //FIFO里面,还存在可用数据    while( SDIO->STA&( 1<<21 ) )    {      *tempbuff = SDIO->FIFO ;                                  //循环读取数据      tempbuff ++ ;    }    //接收结束    if( SDIO->STA&( 1<<8 ) )    {      if( ( SDIO_STD_CAPACITY_SD_CARD_V1_1==CardType )||( SDIO_STD_CAPACITY_SD_CARD_V2_0==CardType )||( SDIO_HIGH_CAPACITY_SD_CARD==CardType ) )      {        SDIO_Send_Cmd( SD_CMD_STOP_TRANSMISSION, 1, 0 ) ;                    //发送CMD12+结束传输        errorstatus = CmdResp1Error( SD_CMD_STOP_TRANSMISSION ) ;                //等待R1响应        if( errorstatus!=SD_OK )          return errorstatus ;      }    }    __asm volatile( "cpsie i" ) ;                                  //开启总中断    SDIO->ICR = 0x5FF ;                                        //清除所有标记     }  return errorstatus ;}/***************************************************Name    :IsCardProgrammingFunction  :检查卡是否正在执行写操作Paramater  :      pstatus:当前状态Return    :错误代码***************************************************/SD_Error IsCardProgramming( u8 *pstatus ){   volatile u32 respR1=0, status=0 ;    SDIO_Send_Cmd( SD_CMD_SEND_STATUS, 1, ( u32 )RCA<<16 ) ;                      //发送CMD13    status = SDIO->STA ;  while( !( status&( ( 1<<0 )|( 1<<6 )|( 1<<2 ) ) ) )    status = SDIO->STA ;                                      //等待操作完成  //CRC检测失败     if( status&( 1<<0 ) )  {    SDIO->ICR |= 1<<0 ;                                        //清除错误标记    return SD_CMD_CRC_FAIL ;  }  //命令超时     if( status&( 1<<2 ) )  {    SDIO->ICR |= 1<<2 ;                                        //清除错误标记    return SD_CMD_RSP_TIMEOUT ;  }   if( SDIO->RESPCMD!=SD_CMD_SEND_STATUS )    return SD_ILLEGAL_CMD ;  SDIO->ICR = 0X5FF ;                                          //清除所有标记  respR1 = SDIO->RESP1 ;  *pstatus = ( u8 )( ( respR1>>9 )&0x0000000F ) ;  return SD_OK ;}/***************************************************Name    :SD_WriteBlockFunction  :写1个块Paramater  :      buf:数据缓存区      addr:写地址      blksize:块大小Return    :错误代码***************************************************/SD_Error SD_WriteBlock( u8 *buf, long long addr, u16 blksize ){  SD_Error errorstatus = SD_OK ;  u8  power=0, cardstate=0 ;  u32 timeout=0, bytestransferred=0 ;  u32 cardstatus=0, count=0, restwords=0 ;  u32  tlen = blksize ;                                        //总长度(字节)  u32*tempbuff = ( u32* )buf ;  //参数错误   if( buf==NULL )    return SD_INVALID_PARAMETER ;    SDIO->DCTRL = 0x0 ;                                          //数据控制寄存器清零(关DMA)    SDIO_Send_Data_Cfg( SD_DATATIMEOUT, 0, 0, 0 ) ;                            //清除DPSM状态机配置  //卡锁了  if( SDIO->RESP1&SD_CARD_LOCKED )    return SD_LOCK_UNLOCK_FAILED ;  //大容量卡   if( CardType==SDIO_HIGH_CAPACITY_SD_CARD )  {    blksize = 512 ;    addr >>= 9 ;  }  if( ( blksize>0 )&&( blksize<=2048 )&&( ( blksize&( blksize-1 ) )==0 ) )  {    power = convert_from_bytes_to_power_of_two( blksize ) ;    SDIO_Send_Cmd( SD_CMD_SET_BLOCKLEN, 1, blksize ) ;                        //发送CMD16+设置数据长度为blksize,短响应    errorstatus = CmdResp1Error( SD_CMD_SET_BLOCKLEN ) ;                      //等待R1响应    //响应错误    if( errorstatus!=SD_OK )      return errorstatus ;  }  else    return SD_INVALID_PARAMETER ;     SDIO_Send_Cmd( SD_CMD_SEND_STATUS, 1, ( u32 )RCA<<16 ) ;                      //发送CMD13,查询卡的状态,短响应  errorstatus = CmdResp1Error( SD_CMD_SEND_STATUS ) ;                          //等待R1响应  if( errorstatus!=SD_OK )    return errorstatus ;  cardstatus = SDIO->RESP1 ;  timeout = SD_DATATIMEOUT ;  //检查READY_FOR_DATA位是否置位     while( ( ( cardstatus&0x00000100 )==0 )&&( timeout>0 ) )  {    timeout -- ;       SDIO_Send_Cmd( SD_CMD_SEND_STATUS, 1, ( u32 )RCA<<16 ) ;                    //发送CMD13,查询卡的状态,短响应    errorstatus = CmdResp1Error( SD_CMD_SEND_STATUS ) ;                        //等待R1响应    if( errorstatus!=SD_OK )      return errorstatus ;    cardstatus = SDIO->RESP1 ;  }  if( timeout==0 )    return SD_ERROR ;     SDIO_Send_Cmd( SD_CMD_WRITE_SINGLE_BLOCK, 1, addr ) ;                        //发送CMD24,写单块指令,短响应  errorstatus = CmdResp1Error( SD_CMD_WRITE_SINGLE_BLOCK ) ;                      //等待R1响应  if( errorstatus!=SD_OK )    return errorstatus ;   SDIO_Send_Data_Cfg( SD_DATATIMEOUT, blksize, power, 0 ) ;                      //blksize, 控制器到卡  timeout = SDIO_DATATIMEOUT ;  __asm volatile( "cpsid i" ) ;                                    //关闭总中断(POLLING模式,严禁中断打断SDIO读写操作!!!)  //数据块发送成功/下溢/CRC/超时/起始位错误  while( !( SDIO->STA&( ( 1<<10 )|( 1<<4 )|( 1<<1 )|( 1<<3 )|( 1<<9 ) ) ) )  {    //发送区半空,表示至少存了8个字    if( SDIO->STA&( 1<<14 ) )    {      //不够32字节了      if( ( tlen-bytestransferred )      {        restwords=( ( tlen-bytestransferred )%4==0 )?( ( tlen-bytestransferred )/4 ):( ( tlen-bytestransferred )/4+1 ) ;        for( count=0; count4 )          SDIO->FIFO = *tempbuff ;      }      else      {        for( count=0; count<8; count++ )          SDIO->FIFO = *( tempbuff+count ) ;        tempbuff += 8 ;        bytestransferred += 32 ;      }      timeout = 0x3FFFFFFF ;                                    //写数据溢出时间    }    else    {      if( timeout==0 )        return SD_DATA_TIMEOUT ;      timeout -- ;    }  }  //数据超时错误  if( SDIO->STA&( 1<<3 ) )  {    SDIO->ICR |= 1<<3 ;                                        //清错误标志    return SD_DATA_TIMEOUT ;  }  //数据块CRC错误  else if( SDIO->STA&( 1<<1 ) )  {    SDIO->ICR |= 1<<1 ;                                        //清错误标志    return SD_DATA_CRC_FAIL ;  }  //接收fifo下溢错误  else if( SDIO->STA&( 1<<4 ) )  {    SDIO->ICR |= 1<<4 ;                                        //清错误标志    return SD_TX_UNDERRUN ;  }  //接收起始位错误  else if( SDIO->STA&( 1<<9 ) )  {    SDIO->ICR |= 1<<9 ;                                        //清错误标志    return SD_START_BIT_ERR ;  }     __asm volatile( "cpsie i" ) ;                                    //开启总中断  SDIO->ICR = 0x5FF ;                                          //清除所有标记   SDIO->ICR = 0x5FF ;                                          //清除所有标记   errorstatus = IsCardProgramming( &cardstate ) ;   while( ( errorstatus==SD_OK )&&( ( cardstate==SD_CARD_PROGRAMMING )||( cardstate==SD_CARD_RECEIVING ) ) )    errorstatus = IsCardProgramming( &cardstate ) ;  return errorstatus ;}/***************************************************Name    :SD_WriteMultiBlocksFunction  :写多个块Paramater  :      buf:数据缓存区      addr:写地址      blksize:块大小      nblks:要写入的块数Return    :错误代码***************************************************/SD_Error SD_WriteMultiBlocks( u8 *buf, long long addr, u16 blksize, u32 nblks ){  SD_Error errorstatus = SD_OK ;  u8  power = 0, cardstate = 0 ;  u32 timeout=0, bytestransferred=0 ;  u32 count = 0, restwords = 0 ;  u32 tlen= nblks*blksize ;                                      //总长度(字节)  u32 *tempbuff = ( u32* )buf ;  //参数错误    if( buf==NULL )    return SD_INVALID_PARAMETER ;    SDIO->DCTRL = 0x0 ;                                          //数据控制寄存器清零(关DMA)       SDIO_Send_Data_Cfg( SD_DATATIMEOUT, 0, 0, 0 );                            //清除DPSM状态机配置  //卡锁了  if( SDIO->RESP1&SD_CARD_LOCKED )    return SD_LOCK_UNLOCK_FAILED ;  //大容量卡   if( CardType==SDIO_HIGH_CAPACITY_SD_CARD )  {    blksize = 512 ;    addr >>= 9 ;  }      if( ( blksize>0 )&&( blksize<=2048 )&&( ( blksize&( blksize-1 ) )==0 ) )  {    power = convert_from_bytes_to_power_of_two( blksize ) ;          SDIO_Send_Cmd( SD_CMD_SET_BLOCKLEN, 1, blksize ) ;                        //发送CMD16+设置数据长度为blksize,短响应    errorstatus = CmdResp1Error( SD_CMD_SET_BLOCKLEN ) ;                      //等待R1响应    //响应错误    if( errorstatus!=SD_OK )      return errorstatus ;  }  else    return SD_INVALID_PARAMETER ;  if( nblks>1 )  {                if( nblks*blksize>SD_MAX_DATA_LENGTH )      return SD_INVALID_PARAMETER ;       if( ( SDIO_STD_CAPACITY_SD_CARD_V1_1==CardType )||( SDIO_STD_CAPACITY_SD_CARD_V2_0==CardType )||( SDIO_HIGH_CAPACITY_SD_CARD==CardType ) )      {      //提高性能          SDIO_Send_Cmd( SD_CMD_APP_CMD, 1, ( u32 )RCA<<16 );                      //发送ACMD55,短响应      errorstatus = CmdResp1Error( SD_CMD_APP_CMD ) ;                        //等待R1响应      if( errorstatus!=SD_OK )        return errorstatus ;          SDIO_Send_Cmd( SD_CMD_SET_BLOCK_COUNT, 1, nblks ) ;                      //发送CMD23,设置块数量,短响应      errorstatus = CmdResp1Error( SD_CMD_SET_BLOCK_COUNT ) ;                    //等待R1响应      if( errorstatus!=SD_OK )        return errorstatus ;    }    SDIO_Send_Cmd( SD_CMD_WRITE_MULT_BLOCK, 1, addr ) ;                        //发送CMD25,多块写指令,短响应    errorstatus = CmdResp1Error( SD_CMD_WRITE_MULT_BLOCK ) ;                    //等待R1响应    if( errorstatus!=SD_OK )      return errorstatus ;      SDIO_Send_Data_Cfg( SD_DATATIMEOUT, nblks*blksize, power, 0 ) ;                  //blksize控制器到卡    timeout = SDIO_DATATIMEOUT ;    __asm volatile( "cpsid i" ) ;                                  //关闭总中断(POLLING模式,严禁中断打断SDIO读写操作!!!)    //下溢/CRC/数据结束/超时/起始位错误    while( !( SDIO->STA&( ( 1<<4 )|( 1<<1) |( 1<<8 )|( 1<<3 )|( 1<<9 ) ) ) )    {      //发送区半空,表示至少存了8字(32字节)      if( SDIO->STA&( 1<<14 ) )      {        //不够32字节了        if( ( tlen-bytestransferred )        {          restwords = ( ( tlen-bytestransferred )%4==0 )?( ( tlen-bytestransferred )/4 ):( ( tlen-bytestransferred )/4+1 );          for( count=0; count4 )            SDIO->FIFO = *tempbuff ;        }        //发送区半空,可以发送至少8字(32字节)数据        else        {          for( count=0; count            SDIO->FIFO = *( tempbuff+count ) ;          tempbuff += SD_HALFFIFO ;          bytestransferred += SD_HALFFIFOBYTES ;        }        timeout = 0x3FFFFFFF ;                                  //写数据溢出时间      }      else      {        if( timeout==0 )          return SD_DATA_TIMEOUT ;        timeout -- ;      }    }    //数据超时错误    if(SDIO->STA&(1<<3))    {      SDIO->ICR |= 1<<3 ;                                      //清错误标志      return SD_DATA_TIMEOUT ;    }    //数据块CRC错误    else if( SDIO->STA&( 1<<1 ) )    {      SDIO->ICR |= 1<<1 ;                                      //清错误标志      return SD_DATA_CRC_FAIL ;    }    //接收fifo下溢错误    else if( SDIO->STA&( 1<<4 ) )    {      SDIO->ICR |= 1<<4 ;                                      //清错误标志      return SD_TX_UNDERRUN ;    }    //接收起始位错误    else if( SDIO->STA&( 1<<9 ) )    {      SDIO->ICR |= 1<<9 ;                                      //清错误标志      return SD_START_BIT_ERR ;    }    //发送结束    if( SDIO->STA&( 1<<8 ) )    {      if( ( SDIO_STD_CAPACITY_SD_CARD_V1_1==CardType )||( SDIO_STD_CAPACITY_SD_CARD_V2_0==CardType )||( SDIO_HIGH_CAPACITY_SD_CARD==CardType ) )      {        SDIO_Send_Cmd( SD_CMD_STOP_TRANSMISSION, 1, 0 ) ;                    //发送CMD12+结束传输        errorstatus = CmdResp1Error( SD_CMD_STOP_TRANSMISSION ) ;                //等待R1响应        if( errorstatus!=SD_OK )          return errorstatus ;         }    }    __asm volatile( "cpsie i" ) ;                                  //开启总中断    SDIO->ICR=0x5FF ;                                        //清除所有标记    }   SDIO->ICR = 0x5FF ;                                          //清除所有标记   errorstatus = IsCardProgramming( &cardstate ) ;   while( ( errorstatus==SD_OK )&&( ( cardstate==SD_CARD_PROGRAMMING )||( cardstate==SD_CARD_RECEIVING ) ) )    errorstatus = IsCardProgramming( &cardstate ) ;  return errorstatus ;     }/***************************************************Name    :SD_ReadDiskFunction  :读SD卡Paramater  :      buf:数据缓存区      sector:扇区地址      cnt:扇区个数Return    :错误代码***************************************************/__align(4) u8 SDIO_DATA_BUFFER[ 512 ] ;u8 SD_ReadDisk( u8*buf, u32 sector, u8 cnt ){  u8 sta = SD_OK ;  long long lsector = sector ;  u8 n ;  if( CardType!=SDIO_STD_CAPACITY_SD_CARD_V1_1 )    lsector <<= 9 ;  if( ( ( u32 )buf%4 )!=0 )  {     for( n=0; n    {       sta = SD_ReadBlock( SDIO_DATA_BUFFER, lsector+512*n, 512 ) ;                //单个sector的读操作      memcpy( buf , SDIO_DATA_BUFFER , 512 ) ;      buf += 512 ;    }  }  else  {    if( cnt==1 )      sta = SD_ReadBlock( buf, lsector, 512 ) ;                          //单个sector的读操作    else      sta = SD_ReadMultiBlocks( buf, lsector, 512, cnt ) ;                    //多个sector  }  return sta ;}/***************************************************Name    :SD_WriteDiskFunction  :写SD卡Paramater  :      buf:数据缓存区      sector:扇区地址      cnt:扇区个数Return    :错误代码***************************************************/u8 SD_WriteDisk( u8*buf, u32 sector, u8 cnt ){  u8 sta = SD_OK ;  u8 n ;  long long lsector = sector ;  if( CardType!=SDIO_STD_CAPACITY_SD_CARD_V1_1 )    lsector <<= 9 ;  if( ( ( u32 )buf%4 )!=0 )  {     for( n=0; n    {      memcpy( SDIO_DATA_BUFFER, buf, 512 ) ;       sta = SD_WriteBlock( SDIO_DATA_BUFFER, lsector+512*n, 512 ) ;                //单个sector的写操作      buf += 512 ;    }  }  else  {    if( cnt==1 )      sta = SD_WriteBlock( buf, lsector, 512 ) ;                          //单个sector的写操作    else      sta = SD_WriteMultiBlocks( buf, lsector, 512, cnt ) ;                    //多个sector    }  return sta ;}

(3)创建1.c文件,并输入以下代码。

#include "sys.h"#include "delay.h"#include "usart1.h"#include "lcd.h"#include "sdio_sdcard.h"int main(){  u8 Str[ 30 ] ;  u16 temp ;   STM32_Clock_Init( 9 ) ;                                        //系统时钟设置  SysTick_Init( 72 ) ;                                        //延时初始化  USART1_Init( 72, 115200 ) ;                                      //串口初始化为115200  LCD_Init() ;                                            //初始化LCD  while( SD_Init() ) ;                                        //初始化SD卡  temp = SDCardInfo.CardCapacity>>20 ;                                //单位换算  sprintf( ( char * )Str, "SD Size: %4d MB", temp ) ;  LCD_ShowString( 30, 170, Str ) ;                                  //显示SD卡容量   while(1)  {      }}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值