DSP SD_FAT32

1 SD 卡介绍

SD 卡( Secure Digital Memory Card)中文翻译为安全数码卡,它是在 MMC 的基础上发展而来, 是一种基于半导体快闪记忆器的新一代记忆设备,它被广 泛地于便携式装置上使用,例如数码相机、个人数码助理(PDA)和多媒体播放器等。SD 卡由日本松下、东芝及美国 SanDisk 公司于 1999 年 8 月共同开发研制。大小犹如一张邮票的 SD 记忆卡,重量只有 2 克,但却拥有高记忆容量、快速数据传输率、极大的移动灵活性以及很好的安全性。 按容量分类,可以将 SD 卡分为 3 类: SD 卡、 SDHC 卡、 SDXC 卡。如下:

SD 卡和 SDHC 卡协议基本兼容,但是 SDXC 卡,同这两者区别就比较大了,本章我们讨论的主要是 SD/SDHC 卡(简称 SD 卡)。

SD 卡一般支持 2 种操作模式:

1,SD 卡模式(通过 SDIO 通信);

2,SPI 模式;

主机可以选择以上任意一种模式同 SD 卡通信,SD 卡模式允许 4 线的高速数据传输。SPI 模式允许简单的通过 SPI 接口来和 SD 卡通信,这种模式同 SD卡模式相比就是丧失了速度。

SD 卡的引脚排序如下(TF 卡的引脚顺序与 SD 卡不同,大家可以百度了解它们之间的管脚,但功能是一样的):

SD 卡引脚功能如下:

SD 卡只能使用 3.3V 的 IO 电平,所以, MCU 一定要能够支持 3.3V 的 IO端口输出。注意:在 SPI 模式下, CS/MOSI/MISO/CLK 都需要加 10~100K 左右的上拉电阻。

SD 卡有 5 个寄存器,如下:

SD 卡的命令格式,如下:

SD 卡的指令由 6 个字节组成,字节 1 的最高 2 位固定为 01,低 6 位为命令号(比如 CMD16,为 10000 即 16 进制的 0X10,完整的 CMD16,第一个字节为 01010000,即 0X10+0X40)。字节 2~5 为命令参数,有些命令是没有参数的。字节 6 的高七位为 CRC 值,最低位恒定为 1。

SD 卡的命令总共有 12 类,分为 Class0~Class11,这里我们仅介绍几个比较重要的命令,如下:

上图中,大部分的命令是初始化的时候用的。图中的 R1、R3 和 R7 等是 SD卡的回应, SD 卡和单片机的通信采用发送应答机制,如下:

每发送一个命令, SD 卡都会给出一个应答,以告知主机该命令的执行情况,或者返回主机需要获取的数据。SPI 模式下, SD 卡针对不同的命令,应答可以使 R1~R7, R1 的应答,各位描述如下:

R2~R7 的响应,我们就不介绍了,请的大家参考 SD 卡 2.0 协议。接下来,我们看看 SD 卡初始化过程。因为我们使用的是 SPI 模式,所以先得让 SD 卡进入 SPI 模式。方法如下: 在 SD 卡收到复位命令( CMD0)时, CS 为有效电平(低电平)则 SPI 模式被启用。不过在发送 CMD0 之前,要发送>74 个时钟,这是因为 SD 卡内部有个供电电压上升时间,大概为 64 个 CLK,剩下的 10个 CLK 用于 SD 卡同步,之后才能开始 CMD0 的操作,在卡初始化的时候, CLK时钟最大不能超过 400Khz。

2 SD 卡初始化流程

最后,我们来看看 SD 卡的初始化流程,要实现 SPI 驱动 SD 卡,最重要的步骤就是 SD 卡的初始化,只要 SD 卡初始化完成了,那么剩下的(读写操作) 就简单了,所以我们这里重点介绍 SD 卡的初始化。我们使用的是 2.0 协议,即只支持标准容量 SD 和高容量 SDHC 标准卡,不支持超大容量 SDXC 标准卡,所以可以支持的最高卡容量是 32GB。SD 卡初始化流程图如图:

从图中,我们看到,不管什么卡(这里我们将卡分为 4 类: SD2.0 高容量卡( SDHC,最大 32G), SD2.0 标准容量卡( SDSC,最大 2G), SD1.x 卡和 MMC 卡)。首先我们要执行的是卡上电(需要设置 SDIO_POWER[1:0]=11),上电后发送 CMD0,对卡进行软复位,之后发送 CMD8 命令,用于区分 SD 卡 2.0,只有 2.0 及以后的卡才支持 CMD8 命令, MMC 卡和 V1.x 的卡,是不支持该命令的。 CMD8 的格式如图所示:

这里,我们需要在发送 CMD8 的时候,通过其带的参数我们可以设置 VHS位,以告诉 SD 卡主机的供电情况,VHS 位定义如图所示:

这里我们使用参数 0X1AA,即告诉 SD 卡,主机供电为 2.7~3.6V 之间,如果 SD 卡支持 CMD8,且支持该电压范围,则会通过 CMD8 的响应( R7)将参数部分原本返回给主机,如果不支持 CMD8,或者不支持这个电压范围,则不响应。在发送 CMD8 后,发送 ACMD41(注意发送 ACMD41 之前要先发送 CMD55),来进一步确认卡的操作电压范围,并通过 HCS 位来告诉 SD 卡,主机是不是支持高容量卡( SDHC)。ACMD41 的命令格式如图所示:

ACMD41 得到的响应( R3)包含 SD 卡 OCR 寄存器内容,OCR 寄存器内容定义如图所示:

对于支持 CMD8 指令的卡,主机通过 ACMD41 的参数设置 HCS 位为 1,来告诉 SD 卡主机支 SDHC 卡,如果设置为 0,则表示主机不支持 SDHC 卡, SDHC卡如果接收到 HCS 为 0,则永远不会反回卡就绪状态。对于不支持 CMD8 的卡, HCS 位设置为 0 即可。

SD 卡在接收到 ACMD41 后,返回 OCR 寄存器内容,如果是 2.0 的卡,主机可以通过判断 OCR 的 CCS 位来判断是 SDHC 还是 SDSC;如果是 1.x 的卡,则忽略该位。 OCR 寄存器的最后一个位用于告诉主机 SD 卡是否上电完成,如果上电完成,该位将会被置 1。

对于 MMC 卡,则不支持 ACMD41,不响应 CMD55,对 MMC 卡,我们只需要在发送 CMD0 后,在发送 CMD1(作用同 ACMD41),检查 MMC 卡的 OCR 寄存器,实现 MMC 卡的初始化。

至此,我们便实现了对 SD 卡的类型区分,在 SD 卡初始化流程图中,最后发送了 CMD2 和 CMD3 命令,用于获得卡 CID 寄存器数据和卡相对地址( RCA)。

CMD2 用于获得 CID 寄存器的数据,CID 寄存器数据各位定义如图所示:

SD 卡在收到 CMD2 后,将返回 R2 长响应( 136 位),其中包含 128 位有效数据( CID 寄存器内容),存放在 SDIO_RESP1~4 等 4 个寄存器里面。通过读取这四个寄存器,就可以获得 SD 卡的 CID 信息。

CMD3 用于设置卡相对地址( RCA,必须为非 0),对于 SD 卡(非 MMC 卡), 在收到 CMD3 后,将返回一个新的 RCA 给主机,方便主机寻址。 RCA 的存在允许挂多个 SD 卡,通过 RCA 来区分主机要操作的是哪个卡。而对于 MMC 卡,则 不是由 SD 卡自动返回 RCA,而是主机主动设置 MMC 卡的 RCA,即通过 CMD3 带参数(高 16 位用于 RCA 设置),实现 RCA 设置。同样 MMC 卡也支持一个 SDIO接口挂多个 MMC 卡,不同于 SD 卡的是所有的 RCA 都是由主机主动设置的,而SD 卡的 RCA 则是 SD 卡发给主机的。

在获得卡 RCA 之后,我们便可以发送 CMD9(带 RCA 参数),获得 SD 卡的 CSD 寄存器内容,从 CSD 寄存器,我们可以得到 SD 卡的容量和扇区大小等十分重要的信息。 CSD 寄存器我们在这里就不详细介绍了,关于 CSD 寄存器的详细介绍,请大家参考《 SD 卡 2.0 协议.pdf》。

到这里我们的 SD 卡初始化基本就结束了,最后通过 CMD7 命令,选中我们要操作的 SD 卡,即可开始对 SD 卡的读写操作了,SD 卡的其他命令和参数,我们这里就不再介绍了,请大家参考《 SD 卡 2.0 协议.pdf》,里面有非常详细的介绍。SD 卡的操作是比较复杂的,要想彻底搞清 SD 卡的操作,短时间是不可能的,如果只是应用 SD 卡的话就非常简单,掌握几个 API 函数即可。

我们看下一个典型的 SD 卡初始化过程:

1、初始化与 SD 卡连接的硬件条件( MCU 的 SPI 配置, IO 口配置);

2、上电延时( >74 个 CLK);

3、复位卡( CMD0),进入 IDLE 状态;

4、发送 CMD8,检查是否支持 2.0 协议;

5、根据不同协议检查 SD 卡(命令包括: CMD55、 CMD41、 CMD58 和 CMD1等);

6、取消片选,发多 8 个 CLK,结束初始化

这样我们就完成了对 SD 卡的初始化,注意末尾发送的 8 个 CLK 是提供SD 卡额外的时钟,完成某些操作。通过 SD 卡初始化,我们可以知道 SD 卡的类型( V1、 V2、 V2HC 或者 MMC),在完成了初始化之后,就可以开始读写数据了。

SD 卡读取数据,这里通过 CMD17 来实现,具体过程如下:

1、发送 CMD17;

2、接收卡响应 R1;

3、接收数据起始令牌 0XFE;

4、接收数据;

5、接收 2 个字节的 CRC,如果不使用 CRC,这两个字节在读取后可以丢掉。

6、禁止片选之后,发多 8 个 CLK;

以上就是一个典型的读取 SD 卡数据过程, SD 卡的写与读数据差不多,写数据通过 CMD24 来实现,具体过程如下:

1、发送 CMD24;

2、接收卡响应 R1;

3、发送写数据起始令牌 0XFE;

4、发送数据;

5、发送 2 字节的伪 CRC;

6、禁止片选之后,发多 8 个 CLK;

以上就是一个典型的写 SD 卡过程。关于 SD 卡的介绍,我们就介绍到这里,更详细的介绍请参考( SD 卡 2.0 协议)。

3 硬件设计

本实验使用到硬件资源如下:

1)D1 指示灯

2)TF 卡

LED 指示灯模块电路在前面章节都介绍过,这里就不多说,下面我们看下 TF卡与 F28335 的连接电路图,如下图所示:

4 软件设计

extern	void play_Udisc();

/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void main()
{
	Uint16 i=0;


	InitSysCtrl();
	InitPieCtrl();
	IER = 0x0000;
	IFR = 0x0000;
	InitPieVectTable();

	LED_Init();
	TIM0_Init(150,200000);//200ms
	UARTa_Init(4800);

	InitXintf();
	InitSpiaGpio();

	spi_initialization();					//Initialize SPI

	sd_card_insertion();			//Check for card insertion
	sd_initialization();			//Initialize card

	sd_read_register(SEND_CSD);		//Read CSD register
	sd_read_register(READ_OCR);		//Read OCR register
	sd_read_register(SEND_CID);		//Read CID register

	play_Udisc();

	asm("     ESTOP0");  // test failed!! Stop!

	while(1)
	{

	}
}

void InitXintf(void)
{
    // This shows how to write to the XINTF registers.  The
    // values used here are the default state after reset.
    // Different hardware will require a different configuration.

    // For an example of an XINTF configuration used with the
    // F28335 eZdsp, refer to the examples/run_from_xintf project.

    // Any changes to XINTF timing should only be made by code
    // running outside of the XINTF.

    // All Zones---------------------------------
    // Timing for all zones based on XTIMCLK = 1/2 SYSCLKOUT
    EALLOW;
    XintfRegs.XINTCNF2.bit.XTIMCLK = 1;
    // No write buffering
    XintfRegs.XINTCNF2.bit.WRBUFF = 0;
    // XCLKOUT is enabled
    XintfRegs.XINTCNF2.bit.CLKOFF = 0;
    // XCLKOUT = XTIMCLK/2
    XintfRegs.XINTCNF2.bit.CLKMODE = 1;


    // Zone 0------------------------------------
    // When using ready, ACTIVE must be 1 or greater
    // Lead must always be 1 or greater
    // Zone write timing
    XintfRegs.XTIMING0.bit.XWRLEAD = 3;
    XintfRegs.XTIMING0.bit.XWRACTIVE = 7;
    XintfRegs.XTIMING0.bit.XWRTRAIL = 3;
    // Zone read timing
    XintfRegs.XTIMING0.bit.XRDLEAD = 3;
    XintfRegs.XTIMING0.bit.XRDACTIVE = 7;
    XintfRegs.XTIMING0.bit.XRDTRAIL = 3;

    // double all Zone read/write lead/active/trail timing
    XintfRegs.XTIMING0.bit.X2TIMING = 1;

    // Zone will sample XREADY signal
    XintfRegs.XTIMING0.bit.USEREADY = 1;
    XintfRegs.XTIMING0.bit.READYMODE = 1;  // sample asynchronous

    // Size must be either:
    // 0,1 = x32 or
    // 1,1 = x16 other values are reserved
    XintfRegs.XTIMING0.bit.XSIZE = 3;

    // Zone 6------------------------------------
    // When using ready, ACTIVE must be 1 or greater
    // Lead must always be 1 or greater
    // Zone write timing
    XintfRegs.XTIMING6.bit.XWRLEAD = 3;
    XintfRegs.XTIMING6.bit.XWRACTIVE = 7;
    XintfRegs.XTIMING6.bit.XWRTRAIL = 3;
    // Zone read timing
    XintfRegs.XTIMING6.bit.XRDLEAD = 3;
    XintfRegs.XTIMING6.bit.XRDACTIVE = 7;
    XintfRegs.XTIMING6.bit.XRDTRAIL = 3;

    // double all Zone read/write lead/active/trail timing
    XintfRegs.XTIMING6.bit.X2TIMING = 1;

    // Zone will sample XREADY signal
    XintfRegs.XTIMING6.bit.USEREADY = 1;
    XintfRegs.XTIMING6.bit.READYMODE = 1;  // sample asynchronous

    // Size must be either:
    // 0,1 = x32 or
    // 1,1 = x16 other values are reserved
    XintfRegs.XTIMING6.bit.XSIZE = 3;

    // Bank switching
    // Assume Zone 6 is slow, so add additional BCYC cycles
    // when ever switching from Zone 6 to another Zone.
    // This will help avoid bus contention.
    XintfRegs.XBANK.bit.BANK = 6;
    XintfRegs.XBANK.bit.BCYC = 6;

    // Zone 7------------------------------------
    // When using ready, ACTIVE must be 1 or greater
    // Lead must always be 1 or greater
    // Zone write timing
    XintfRegs.XTIMING7.bit.XWRLEAD = 3;
    XintfRegs.XTIMING7.bit.XWRACTIVE = 7;
    XintfRegs.XTIMING7.bit.XWRTRAIL = 3;
    // Zone read timing
    XintfRegs.XTIMING7.bit.XRDLEAD = 3;
    XintfRegs.XTIMING7.bit.XRDACTIVE = 7;
    XintfRegs.XTIMING7.bit.XRDTRAIL = 3;

    // double all Zone read/write lead/active/trail timing
    XintfRegs.XTIMING7.bit.X2TIMING = 1;

    // Zone will sample XREADY signal
    XintfRegs.XTIMING7.bit.USEREADY = 1;
    XintfRegs.XTIMING7.bit.READYMODE = 1;  // sample asynchronous

    // Size must be either:
    // 0,1 = x32 or
    // 1,1 = x16 other values are reserved
    XintfRegs.XTIMING7.bit.XSIZE = 3;

    // Bank switching
    // Assume Zone 7 is slow, so add additional BCYC cycles
    // when ever switching from Zone 6 to another Zone.
    // This will help avoid bus contention.
//    XintfRegs.XBANK.bit.BANK = 7;
//    XintfRegs.XBANK.bit.BCYC = 7;
    EDIS;
   //Force a pipeline flush to ensure that the write to
   //the last register configured occurs before returning.

   InitXintf16Gpio();
// InitXintf32Gpio();

   asm(" RPT #7 || NOP");

}
void InitSpiaGpio()
{

   EALLOW;
/* Enable internal pull-up for the selected pins */
// Pull-ups can be enabled or disabled by the user.  
// This will enable the pullups for the specified pins.
// Comment out other unwanted lines.

    GpioCtrlRegs.GPBPUD.bit.GPIO54 = 0;   // Enable pull-up on GPIO54 (SPISIMOA)
    GpioCtrlRegs.GPBPUD.bit.GPIO55 = 0;   // Enable pull-up on GPIO55 (SPISOMIA)
    GpioCtrlRegs.GPBPUD.bit.GPIO56 = 0;   // Enable pull-up on GPIO56 (SPICLKA)
    GpioCtrlRegs.GPBPUD.bit.GPIO57 = 0;   // Enable pull-up on GPIO57 (SPISTEA)


//    GpioCtrlRegs.GPBPUD.bit.GPIO54 = 0;   // Enable pull-up on GPIO54 (SPISIMOA)
//    GpioCtrlRegs.GPBPUD.bit.GPIO55 = 0;   // Enable pull-up on GPIO55 (SPISOMIA)
//    GpioCtrlRegs.GPBPUD.bit.GPIO56 = 0;   // Enable pull-up on GPIO56 (SPICLKA)
//    GpioCtrlRegs.GPBPUD.bit.GPIO57 = 0;   // Enable pull-up on GPIO57 (SPISTEA)

/* Set qualification for selected pins to asynch only */
// This will select asynch (no qualification) for the selected pins.
// Comment out other unwanted lines.

//    GpioCtrlRegs.GPAQSEL2.bit.GPIO16 = 3; // Asynch input GPIO16 (SPISIMOA)
//    GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 3; // Asynch input GPIO17 (SPISOMIA)
//    GpioCtrlRegs.GPAQSEL2.bit.GPIO18 = 3; // Asynch input GPIO18 (SPICLKA)
//    GpioCtrlRegs.GPAQSEL2.bit.GPIO19 = 3; // Asynch input GPIO19 (SPISTEA)

    GpioCtrlRegs.GPBQSEL2.bit.GPIO54 = 3; // Asynch input GPIO16 (SPISIMOA)
    GpioCtrlRegs.GPBQSEL2.bit.GPIO55 = 3; // Asynch input GPIO17 (SPISOMIA)
    GpioCtrlRegs.GPBQSEL2.bit.GPIO56 = 3; // Asynch input GPIO18 (SPICLKA)
    GpioCtrlRegs.GPBQSEL2.bit.GPIO57 = 3; // Asynch input GPIO19 (SPISTEA)

    
/* Configure SPI-A pins using GPIO regs*/
// This specifies which of the possible GPIO pins will be SPI functional pins.
// Comment out other unwanted lines.

//    GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1; // Configure GPIO16 as SPISIMOA
//    GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1; // Configure GPIO17 as SPISOMIA
//    GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1; // Configure GPIO18 as SPICLKA
//    GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1; // Configure GPIO19 as SPISTEA

    GpioCtrlRegs.GPBMUX2.bit.GPIO54 = 1; // Configure GPIO54 as SPISIMOA
    GpioCtrlRegs.GPBMUX2.bit.GPIO55 = 1; // Configure GPIO55 as SPISOMIA
    GpioCtrlRegs.GPBMUX2.bit.GPIO56 = 1; // Configure GPIO56 as SPICLKA
    GpioCtrlRegs.GPBMUX2.bit.GPIO57 = 1; // Configure GPIO57 as SPISTEA

    EDIS;
}
#define SPI_SEL_REG *(Uint16 *)0x4800
#define SPI_SD  0X02


//SD Standard Commands
#define GO_IDLE_STATE 				0x4000
#define SEND_OP_COND  				0x4100
#define SWITCH_FUNC					0x4600
#define SEND_IF_COND				0x4800
#define SEND_CSD	  				0x4900
#define SEND_CID	  				0x4A00
#define	STOP_TRANSMISSION			0x4C00
#define SEND_STATUS 				0x4D00
#define	SET_BLOCKLEN				0x5000
#define READ_SINGLE_BLOCK 			0x5100
#define READ_MULTIPLE_BLOCK			0x5200
#define WRITE_BLOCK 				0x5800
#define	WRITE_MULTIPLE_BLOCK		0x5900
#define PROGRAM_CSD					0x5B00
#define SET_WRITE_PROT				0x5C00
#define CLR_WRITE_PROT				0x5D00
#define SEND_WRITE_PROT				0x5E00
#define ERASE_WR_BLK_START_ADDR 	0x6000
#define ERASE_WR_BLK_END_ADDR 		0x6100
#define ERASE 						0x6600
#define	LOCK_UNLOCK					0x6A00
#define APP_CMD						0x7700
#define GEN_CMD						0x7800
#define READ_OCR	 				0x7A00
#define CRC_ON_OFF					0x7B00

//SD Application Specific Commands
#define	SD_STATUS					0x4D00
#define SEND_NUM_WR_BLOCKS			0x5600
#define SET_WR_BLK_ERASE_COUNT		0x5700
#define SD_SEND_OP_COND				0x6900
#define SET_CLR_CARD_DETECT			0x6A00
#define SEND_SCR					0x7300

//Data Tokens
#define INITIAL_CRC 				0x9500
#define DUMMY_CRC 					0xFF00
#define DUMMY_DATA 					0xFF00
#define START_BLOCK					0xFE00
#define MULTIPLE_START_BLOCK 		0xFC00
#define MULTIPLE_STOP_TRANSMISSION	0xFD00 
#define SECTOR_ZERO 		    	0x0000
#define STUFF_BITS 					0x0000
#define BUSY						0x0000
#define SINGLE_SECTOR				0x0001
#define MULTIPLE_WRITE				0x0001
#define CRC_ON						0x0001
#define CRC_OFF						0x0000
#define BLOCK_LENGTH				0x0200
//#define TRUE  						0x0001
//#define FALSE 						0x0000
#define CHECK_PATTERN				0xAA00
#define SUPPLY_VOLTAGE				0x0100
#define HIGH_CAPACITY				0x4000
#define SUPPORTED_VOLTAGE			0xFF00
#define INTERFACE_COND				426
#define VER2_OP_COND				1073741824

//Status and Error Codes
#define IN_IDLE_STATE 				0x0100
#define SUCCESS 					0x0000
#define DATA_ACCEPTED 				0x0500
#define CRC_ERROR 					0x0B00
#define WRITE_ERROR 				0x0D00
#define ERROR						0x0100
#define CC_ERROR					0x0200
#define CARD_ECC_FAILED				0x0400
#define OUT_OF_RANGE				0x0800  
#define ILLEGAL_COMMAND_IDLE_STATE  0x0500 

//Continuous Commands

#define RESET_RESPONSE response = 0xFF00;
#define EIGHT_CLOCK_CYCLE_DELAY spi_xmit_byte(DUMMY_DATA);

//Global Prototypes

//Functions located in SD_SPI_Erase.c
extern void sd_erase_block(Uint16 starting_sector, Uint16 total_sectors);

//Functions located in SD_SPI_Initialization.c
extern void spi_initialization();
extern void led_initialization();
extern void sd_card_insertion();
extern void sd_initialization();
extern void sd_version1_initialization();
extern void sd_version2_initialization();

//Functions located in SD_SPI_Read.c
extern void sd_read_block(Uint16 sector, Uint16 *pBuffer);
extern void sd_read_multiple_block(Uint16 sector, Uint16 *pBuffer, Uint16 total_sectors);
extern void sd_data_response(Uint16 *pBuffer, Uint16 total_sectors);

//Functions located in SD_SPI_Registers.c
extern void sd_read_register(Uint16 command);
extern void sd_ocr_response();
extern void sd_cid_csd_response(Uint16 command);
extern void sd_send_status();
extern void sd_switch_function(Uint16 *pBuffer);

//Functions located in SD_SPI_Transmission.c
extern Uint16 spi_xmit_byte(Uint16 byte);
extern void spi_xmit_command(Uint16 command, Uint32 data, Uint16 crc);
extern Uint16 sd_crc7(Uint16 full_command[6]);
extern void sd_command_response();
extern void sd_error();

//Functions located in SD_SPI_Write.c
extern void sd_write_block(Uint16 sector, Uint16 *pBuffer);
extern void sd_write_multiple_block(Uint16 sector, Uint16 *pBuffer, Uint16 total_sectors);
extern void sd_write_data(Uint16 *pBuffer, Uint16 total_sectors, Uint16 multiple_write);

//Global Variables
extern Uint16 response, ocr_contents[5], csd_contents[16], cid_contents[16];
extern Uint16 card_status[2], data_manipulation, high_capacity, crc_enabled;
extern void SPI_ENABLE();

/
extern void SPI_DISABLE();
//============================================================
void SPI_ENABLE()
{
	SPI_SEL_REG=SPI_SD;	//使能SPI_SD
}
/
void SPI_DISABLE()
{
	SPI_SEL_REG=0xFF;	//DISABLE SPI_SD
}

//Global Variables
Uint16 response, ocr_contents[5], csd_contents[16], cid_contents[16];
Uint16 card_status[2], data_manipulation = TRUE, high_capacity = FALSE, crc_enabled = FALSE;

//########################## SPI_INITIALIZATION ##############################
void spi_initialization()
{    
	SpiaRegs.SPICCR.all =0x0007;	    //Reset off, rising edge, 8-bit char bits  
	SpiaRegs.SPICTL.all =0x000E;        //Enable master mode, delayed phase,
                                        //enable talk, and SPI int disabled.
	SpiaRegs.SPIBRR =0x0063;									
    SpiaRegs.SPICCR.all =0x0087;		//Relinquish SPI from Reset 
    SpiaRegs.SPIPRI.bit.FREE = 1; 		//Transmission not affected by emulator
}
//########################## SPI_INITIALIZATION ##############################


//########################## LED_INITIALIZATION ##############################

//########################## LED_INITIALIZATION ##############################


//######################### CHECK_CARD_INSERTION #############################
void sd_card_insertion()
{
	Uint16 i;

//	while(GpioDataRegs.GPBDAT.bit.GPIO34 != 0){}; 	//Wait for Card A Insertion
  // 	GpioDataRegs.GPACLEAR.bit.GPIO28 = TRUE;		//Emit Card A Status LED, Optional					
//	GpioDataRegs.GPACLEAR.bit.GPIO20 = TRUE;		//Emit SDIO Mode LED, Optional

   	//After Card Detection, SD protocol states that card needs 74 clock 
   	//cycles with the DATA IN line high for chip to stabilize. CS does not 
   	//need to be active for this action.

   	SPI_DISABLE();							//Pull CS high
	for(i=0;i<10;i++)					//Transmit 0xFF for 80 clock cycles
   		spi_xmit_byte(DUMMY_DATA); 
}
//######################### CHECK_CARD_INSERTION #############################


//########################## SD_INITIALIZATION ###############################
void sd_initialization()
{
	SPI_ENABLE();								//Pull CS low
	data_manipulation = FALSE;				//Register manipulation function

	//Transmit GO IDLE STATE command to card with CS low to select SPI mode 
	//and put the card in IDLE mode.
   	spi_xmit_command(GO_IDLE_STATE, STUFF_BITS, INITIAL_CRC);	
   	
   	RESET_RESPONSE;							//Reset response	
	while(response != IN_IDLE_STATE)		//Wait until card responds with IDLE response
		sd_command_response();
		
  //	GpioDataRegs.GPASET.bit.GPIO20 = TRUE;  //Disable SDIO Mode LED, Optional	
//	GpioDataRegs.GPACLEAR.bit.GPIO5 = TRUE; //Emit SPI Mode LED, Optional
	
	RESET_RESPONSE;							//Reset response			
	//After receiving response clock must be active for 8 clock cycles
	EIGHT_CLOCK_CYCLE_DELAY;

	crc_enabled = TRUE;						//CRC is always enabled for SEND_IF_COND command
	spi_xmit_command(SEND_IF_COND, INTERFACE_COND, DUMMY_CRC);	//Transmit SEND_IF_COND command
	crc_enabled = FALSE;					//CRC is disabled for SPI mode

	//Wait until card responds with IDLE response
	while((response != IN_IDLE_STATE) && (response != ILLEGAL_COMMAND_IDLE_STATE))	
		response = spi_xmit_byte(DUMMY_DATA);

	//If SEND_IF_COND returned illegal command call sd_version1_initialization for
	//standard capacity card initialization. Otherwise call sd_version2_initialization 
	//for high capacity card initialization
	if(response == ILLEGAL_COMMAND_IDLE_STATE)
		sd_version1_initialization();	
	else if(response == IN_IDLE_STATE)
		sd_version2_initialization();

	SPI_DISABLE();								//Pull CS high
   	//After receiving response clock must be active for 8 clock cycles
	EIGHT_CLOCK_CYCLE_DELAY;

	SpiaRegs.SPIBRR = 0x0004;				//Adjust Clock to 10.0 MHz (10.0 Mbps)
}
//########################## SD_INITIALIZATION ###############################


//###################### SD_VERSION1_INITIALIZATION ##########################
void sd_version1_initialization()
{

	RESET_RESPONSE;						//Reset response
   	//After receiving response clock must be active for 8 clock cycles
	EIGHT_CLOCK_CYCLE_DELAY;

	spi_xmit_command(READ_OCR, STUFF_BITS, DUMMY_CRC);	//Transmit READ_OCR command
	//Wait until card responds with IN_IDLE_STATE response
	while(response != IN_IDLE_STATE)		
		sd_command_response();

	sd_ocr_response();					//Call OCR response function

	//If host voltage is not compatible with card voltage, do not communicate 
	//further with card
	if(ocr_contents[1] != SUPPORTED_VOLTAGE)		
		sd_error();

	RESET_RESPONSE;						//Reset response
 	//After receiving response clock must be active for 8 clock cycles
	EIGHT_CLOCK_CYCLE_DELAY;

	while(response != SUCCESS)
	{
		RESET_RESPONSE;					//Reset response
   		//After receiving response clock must be active for 8 clock cycles
		EIGHT_CLOCK_CYCLE_DELAY;
		
		//Before transmitting application specific commands, the APP_CMD
		//must be transmitted
		spi_xmit_command(APP_CMD, STUFF_BITS, DUMMY_CRC);
		//Wait until card responds with IN_IDLE_STATE response
		while(response != IN_IDLE_STATE)	 
			sd_command_response();

		RESET_RESPONSE;					//Reset response
   		//After receiving response clock must be active for 8 clock cycles
		EIGHT_CLOCK_CYCLE_DELAY;	
   		
   		//Transmit SEND OP COND command   								
 		spi_xmit_command(SD_SEND_OP_COND, STUFF_BITS, DUMMY_CRC);				  
		sd_command_response();			//Receive response
	}
	
	RESET_RESPONSE;						//Reset response
   	//After receiving response clock must be active for 8 clock cycles
	EIGHT_CLOCK_CYCLE_DELAY;			
}
//###################### SD_VERSION1_INITIALIZATION ##########################


//###################### SD_VERSION2_INITIALIZATION ##########################
void sd_version2_initialization()
{
	Uint16 i, send_if_cond_response[4], ccs_check;
	
	//Receive SEND_IF_COND response
	for(i=0;i<3;i++)
		send_if_cond_response[i] = spi_xmit_byte(DUMMY_DATA);

	//If voltage accepted or check pattern does not match, do not communicate further
	if((send_if_cond_response[2] != SUPPLY_VOLTAGE) || (send_if_cond_response[3] != CHECK_PATTERN))
		sd_error();

	RESET_RESPONSE;						//Reset response
 	//After receiving response clock must be active for 8 clock cycles
	EIGHT_CLOCK_CYCLE_DELAY;
	
	while(response != SUCCESS)
	{
		RESET_RESPONSE;					//Reset response
 	  	//After receiving response clock must be active for 8 clock cycles
		EIGHT_CLOCK_CYCLE_DELAY;

		//Before transmitting application specific commands, the APP_CMD
		//must be transmitted
		spi_xmit_command(APP_CMD, STUFF_BITS, DUMMY_CRC);
		while(response != IN_IDLE_STATE)//Wait until card responds with IN_IDLE_STATE response 
			sd_command_response();

		RESET_RESPONSE;					//Reset response
   		//After receiving response clock must be active for 8 clock cycles
		EIGHT_CLOCK_CYCLE_DELAY;
   		
   		//Transmit SEND_OP_COND command   								
 		spi_xmit_command(SD_SEND_OP_COND, VER2_OP_COND, DUMMY_CRC);				  
		sd_command_response();			//Receive response
	}
	
	RESET_RESPONSE;						//Reset response
   	//After receiving response clock must be active for 8 clock cycles
	EIGHT_CLOCK_CYCLE_DELAY;
		
	spi_xmit_command(READ_OCR, STUFF_BITS, DUMMY_CRC);	//Transmit READ_OCR command
	//Wait until card responds with SUCCESS response
	while(response != SUCCESS)		
		sd_command_response();

	sd_ocr_response();					//Call OCR response function
	
	ccs_check = ocr_contents[0] & HIGH_CAPACITY; //Mask ocr_contents to test for High Capacity

	if(ccs_check == HIGH_CAPACITY)		//Check if card is High Capacity
		high_capacity = TRUE;				 
	
	RESET_RESPONSE;						//Reset response
   	//After receiving response clock must be active for 8 clock cycles
	EIGHT_CLOCK_CYCLE_DELAY;			
}
//###################### SD_VERSION2_INITIALIZATION ##########################
FLAGS bFlags;
extern unsigned char DBUF[BUFFER_LENGTH];
unsigned char usector;
extern unsigned long  DirStartCluster32;		
extern unsigned long  DirStartCluster;
extern SYS_INFO_BLOCK   DeviceInfo;
unsigned char DataBuf[BUFFER_LENGTH];
extern	FILE_INFO   	 ThisFile;

/
void play_Udisc();

void play_Udisc()
{
    int temp,i;

 
    DirStartCluster=0;
	DirStartCluster32=0;

	for(temp=0;temp<512;temp++)
		DBUF[temp]=0;


	
	
		   		DirStartCluster=0;
				DirStartCluster32=0;
				ThisFile.FatSectorPointer=0;
				DeviceInfo.LastFreeCluster=0;

			if(InitFileSystem())
				{
				bFlags.bits.SLAVE_IS_ATTACHED = TRUE;				
			
				}
			else
				{				
				bFlags.bits.SLAVE_IS_ATTACHED = FALSE;				
				}		
				
			
		

		if(bFlags.bits.SLAVE_IS_ATTACHED)
			{
				CreateFile("demo123.txt",0x20);
				for (i=0;i<100;i++)
				{
		     		DataBuf[i*10+0]='U';
		     		DataBuf[i*10+1]=' ';
		     		DataBuf[i*10+2]='D';
		     		DataBuf[i*10+3]='I';
		     		DataBuf[i*10+4]='S';
		     		DataBuf[i*10+5]='K';
					DataBuf[i*10+6]=' ';
					DataBuf[i*10+7]='!';
					DataBuf[i*10+8]= 13;
					DataBuf[i*10+9]= 10; 
				}		     	     
				for(i=0;i<10;i++)
				{
					SetFilePointer(ThisFile.LengthInByte);
					WriteFile(1000,DataBuf);
				
				}
						   asm ("      ESTOP0");//ok	
			}		
		
		asm ("      ESTOP0");//error  
    	
}

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值