www.pudn.com > MMC_SD.rar > MMC_SD.c, change:2009-07-23,size:5578b


/*******************************************************************/ 
/*                          SD卡驱动程序                           */ 
/* 文件名: MCC_SD.c                                                */ 
/* 平台: MAPLAB + MCC18                                            */ 
 
 
#include"MMC_SD/MMC_SD.h" /*头文件*/ 
#include<spi.h> 
 
//#include<p18cxxx.h> 
//#include"LCM/md130.h" 
//#include"FAT/FAT.h" 
//#include"UART/UART.h" 
//#include<stdio.h> 
//#include<stdlib.h> 
//#include<timers.h> 
//#include "GUI/gui.h" 
//#include "delay.h" 
 
 
/* spi low speed, below 400KHz */ 
void SPI_Low(void) 
{ 
	OpenSPI1(SPI_FOSC_64, MODE_00, SMPMID); 
} 
 
/* spi high speed, not exceed 25MHz */ 
void SPI_High(void) 
{ 
	OpenSPI1(SPI_FOSC_16, MODE_00, SMPMID); 
} 
 
uint8 SPI_WriteByte(uint8 val) 
{ 
	SSP1BUF = val; 
	while( !SSP1STATbits.BF ); 
	return SSP1BUF; 
} 
 
uint8 SPI_ReadByte(void) 
{ 
	SSP1BUF = 0xff; 
	while( !SSP1STATbits.BF ); 
	return SSP1BUF; 
} 
 
/* sd send command */  
uint8 MMC_SD_SendCommand(uint8 cmd, uint32 arg) 
{ 
	uint8 r1; 
	uint8 retry=0; 
	 
	SPI_WriteByte(0xff); 
	SPI_CS_Assert; 
	 
	SPI_WriteByte(cmd | 0x40);	/* send command */ 
	SPI_WriteByte(arg>>24); 
	SPI_WriteByte(arg>>16); 
	SPI_WriteByte(arg>>8); 
	SPI_WriteByte(arg); 
	SPI_WriteByte(0x95); 
	 
	while((r1 = SPI_WriteByte(0xff)) == 0xff)	/* wait response */ 
		if(retry++ > 0xfe) break;				/* time out error */ 
 
	SPI_CS_Deassert; 
	SPI_WriteByte(0xff);				// extra 8 CLK 
 
	return r1;								/* return state */ 
} 
 
/* SD card initialization, include reset and configuration */ 
uint8 MMC_SD_Init(void) 
{ 
	uint8 i; 
	uint16 retry = 0; 
	uint8 r1 = 0; 
	 
	MMC_SD_PORT_INI;	/* Port Initialize */ 
	SPI_Low();			/* SPI intialize */ 
	 
	do 
	{ 
		for(i=0;i<100;i++) SPI_WriteByte(0xff); 
		r1 = MMC_SD_SendCommand(0, 0);//发idle命令	//send idle command 
		retry++; 
		if(retry>0xfffe) return 1;//超时退出		//time out 
	} while(r1 != 0x01);	 
 
 
	retry = 0; 
	do 
	{ 
		r1 = MMC_SD_SendCommand(1, 0);//发active命令	//send active command 
		retry++; 
		if(retry>0xfffe) return 1;//超时退出		//time out 
	} while(r1); 
	 
	SPI_High();		/* Use High Speed SPI*/ 
	 
	r1 = MMC_SD_SendCommand(59, 0);//关crc		//disable CRC 
 
	r1 = MMC_SD_SendCommand(16, 512);//设扇区大小512	//set sector size to 512 
	return 0;//正常返回		//normal return 
} 
 
//读一个扇区		//read one sector 
uint8 MMC_SD_ReadSingleBlock(uint32 sector, uint8* buffer) 
{ 
	uint8 r1; 
	uint16 i; 
	uint16 retry=0; 
 
	SPI_High();		/* Use High Speed SPI*/ 
 
	r1 = MMC_SD_SendCommand(17, sector<<9);//读命令	//read command 
	 
	if(r1 != 0x00) 
		return r1; 
 
	SPI_CS_Assert; 
	//等数据的开始	//wait to start recieve data 
	while(SPI_WriteByte(0xff) != 0xfe)if(retry++ > 0xfffe){SPI_CS_Deassert;return 1;} 
 
	for(i=0; i<512; i++)//读512个数据	//read 512 bytes 
	{ 
		*buffer++ = SPI_WriteByte(0xff); 
	} 
 
	SPI_WriteByte(0xff);//伪crc    //dummy crc 
	SPI_WriteByte(0xff); 
	 
	SPI_CS_Deassert; 
	SPI_WriteByte(0xff);// extra 8 CLK 
 
	return 0; 
} 
 
 
//写一个扇区		//wirite one sector //not used in this application 
uint8 MMC_SD_WriteSingleBlock(uint32 sector, uint8* buffer) 
{ 
	uint8 r1; 
	uint16 i; 
	uint16 retry=0; 
	 
	SPI_High();		/* Use High Speed SPI*/ 
 
	r1 = MMC_SD_SendCommand(24, sector<<9);//写命令	//send command 
	if(r1 != 0x00) 
		return r1; 
 
	SPI_CS_Assert; 
	 
	SPI_WriteByte(0xff); 
	SPI_WriteByte(0xff); 
	SPI_WriteByte(0xff); 
 
	SPI_WriteByte(0xfe);//发开始符			//send start byte "token" 
	 
	for(i=0; i<512; i++)//送512字节数据		//send 512 bytes data 
	{ 
		SPI_WriteByte(*buffer++); 
	} 
	 
	SPI_WriteByte(0xff);			//dummy crc 
	SPI_WriteByte(0xff); 
	 
	r1 = SPI_WriteByte(0xff); 
	 
	if( (r1&0x1f) != 0x05)//等待是否成功	//judge if it successful 
	{ 
		SPI_CS_Deassert; 
		return r1; 
	} 
	//等待操作完		//wait no busy 
	while(!SPI_WriteByte(0xff))if(retry++ > 0xfffe){SPI_CS_Deassert;return 1;} 
 
	SPI_CS_Deassert; 
	SPI_WriteByte(0xff);// extra 8 CLK 
 
	return 0; 
} 
 
 
 
uint32 MMC_SD_ReadCapacity() 
{ 
	uint8 r1; 
	uint16 i; 
	uint16 temp; 
	uint8 buffer[16]; 
	uint32 Capacity; 
	uint16 retry =0; 
	//uint8 retry=0; 
 
	SPI_High();		/* Use High Speed SPI*/ 
 
	r1 = MMC_SD_SendCommand(9, 0);//写命令	//send command  //READ CSD 
	if(r1 != 0x00) 
		return r1; 
 
	SPI_CS_Assert; 
	while(SPI_WriteByte(0xff) != 0xfe)if(retry++ > 0xfffe){SPI_CS_Deassert;return 1;} 
	 
	for(i=0;i<16;i++) 
	{ 
		buffer[i]=SPI_WriteByte(0xff); 
	}	 
 
	SPI_WriteByte(0xff); 
	SPI_WriteByte(0xff); 
	 
	SPI_WriteByte(0xff); 
	 
	SPI_CS_Deassert; 
 
	SPI_WriteByte(0xff);// extra 8 CLK 
 
/*********************************/ 
//	C_SIZE 
	i = buffer[6]&0x03; 
	i<<=8; 
	i += buffer[7]; 
	i<<=2; 
	i += ((buffer[8]&0xc0)>>6); 
 
/**********************************/ 
//  C_SIZE_MULT 
 
	r1 = buffer[9]&0x03; 
	r1<<=1; 
	r1 += ((buffer[10]&0x80)>>7); 
 
 
/**********************************/ 
// BLOCKNR 
 
	r1+=2; 
 
	temp = 1; 
	while(r1) 
	{ 
		temp*=2; 
		r1--; 
	} 
	 
	Capacity = ((uint32)(i+1))*((uint32)temp); 
 
///////////////////////// 
// READ_BL_LEN 
 
	i = buffer[5]&0x0f; 
 
/*************************/ 
//BLOCK_LEN 
 
	temp = 1; 
	while(i) 
	{ 
		temp*=2; 
		i--; 
	} 
/************************/ 
 
 
/************** formula of the capacity ******************/ 
// 
//  memory capacity = BLOCKNR * BLOCK_LEN 
//	 
//	BLOCKNR = (C_SIZE + 1)* MULT 
// 
//           C_SIZE_MULT+2 
//	MULT = 2 
// 
//               READ_BL_LEN 
//	BLOCK_LEN = 2 
/**********************************************/ 
 
//The final result 
 
	 
	Capacity *= (uint32)temp;	  
	return Capacity; 
}