⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmc.c

📁 实现了avr下对sd卡的读写,支持文件存取,删除的功能
💻 C
字号:
//-------------------------------------------------------------------------
#include	<avr/io.h>

#include	"mmc.h"
#include	"spi.h"
//-------------------------------------------------------------------------
#define	CS			PB4
#define	CSH			PORTB|=_BV(CS)
#define	CSL			PORTB&=~_BV(CS)

//-------------------------------------------------------------------------
void mmcInit(void){	
	spiInit();					// initialize SPI interface	
	DDRB|=_BV(PB4);				// release chip select,low power selcet
	CSH;
}
//-------------------------------------------------------------------------
uint8_t mmcReset_1(void){
	uint8_t i,retry,r1;

	retry=0;
	do{
		for(i=0;i<10;i++) spiTransferByte(0xFF);	//send dummy at CS high(dummy argument又叫哑元变量 )	
		r1=mmcSendCommand(MMC_GO_IDLE_STATE, 0);	// resetting card
		retry++;
		if(retry>10) return -1;
	} while(r1 != MMC_R1_IDLE_STATE);

	retry=0;
	do{			
		r1=mmcSendCommand(MMC_SEND_OP_COND, 0);	// initializing card
		retry++;
		if(retry>100) return -1;
	} while(r1!=0);

	mmcSendCommand(MMC_CRC_ON_OFF, 0);			// turn off CRC checking
	mmcSendCommand(MMC_SET_BLOCKLEN, 512);		// set block len 512 bytes

	return 0;
}
//-------------------------------------------------------------------------
uint8_t mmcReset(void){
	uint8_t i;
	for(i=0;i<50;i++)if(mmcReset_1()==0)return 0;
	return -1;
}
//-------------------------------------------------------------------------
uint8_t mmcSendCommand(uint8_t cmd, uint32_t arg){
	uint8_t r1;

	CSL;											// assert chip select	
	r1 = mmcCommand(cmd, arg);						// issue the command
	CSH;											// release chip select
	return r1;
}
//-------------------------------------------------------------------------
uint8_t mmcRead(uint32_t sector, uint8_t* buffer ){
	uint8_t r1;
	uint16_t i;

	CSL;											// assert chip select	
	r1 = mmcCommand(MMC_READ_SINGLE_BLOCK, sector<<9);	// issue command,argument is the data address,the sector contains 512Byte,so leftshift 9bits,so the sector is just the serial number
	if(r1 != 0)return r1;	
	while(spiTransferByte(0xFF)!=MMC_STARTBLOCK_READ);// wait for block start
	
	for(i=0; i<0x200; i++){//0x200即读了512个,2的9次
		*buffer++ = spiTransferByte(0xFF);			// read in data
	}
	
	spiTransferByte(0xFF);							// read 16-bit CRC
	spiTransferByte(0xFF);							//ba crc du wan cai neng pai gan jing
	CSH;											// release chip select,you fen zhu le 
	return 0;
}
//-------------------------------------------------------------------------
uint8_t mmcWrite(uint32_t sector, uint8_t* buffer){
	uint8_t r1;
	uint16_t i;

	CSL;											// assert chip select	
	r1 = mmcCommand(MMC_WRITE_BLOCK,sector<<9);	// issue command ????????
	if(r1 != 0)return r1;	//return r1 for further judgement in subfunctions
	spiTransferByte(0xFF);							// send dummy	
	spiTransferByte(MMC_STARTBLOCK_WRITE);			// send data start token,indicate data will follow,arouse the slaver
	
	for(i=0; i<512; i++){
		spiTransferByte(*buffer++);				// write data
	}
	
	spiTransferByte(0xFF);							// write 16-bit CRC (dummy values)
	spiTransferByte(0xFF);
	
	r1 = spiTransferByte(0xFF);						// read data response token
	if((r1&MMC_DR_MASK)!=MMC_DR_ACCEPT)return r1;	//the mask get the lower five bits(Higher bits are all ones),compared with 0x05(MMC_DR_ACCEPT)
	while(!spiTransferByte(0xFF));					// wait until card not busy(wait for the high level)
	CSH;											// release chip select
	return 0;
}
//-------------------------------------------------------------------------
uint8_t mmcCommand(uint8_t cmd, uint32_t arg){
	uint8_t r1,retry=0;
	spiTransferByte(cmd|0x40);						// send command
	spiTransferByte(arg>>24);
	spiTransferByte(arg>>16);
	spiTransferByte(arg>>8);
	spiTransferByte(arg);
	spiTransferByte(0x95);	// crc valid only for MMC_GO_IDLE_STATE
	// end command
	// wait for response
	// if more than 8 retries, card has timed-out
	// return the received 0xFF
	while((r1=spiTransferByte(0xFF))==0xFF)if(retry++>8)break;
	// return response
	return r1;
}
//-------------------------------------------------------------------------
//Routine for reading CID Registers from MMC/SD-Card (16Bytes) 
//Return 0 if no Error.
uint8_t Read_CID_MMC(uint8_t *buffer){
	uint8_t r1,i;

	CSL;											// assert chip select
	r1 = mmcCommand(MMC_SEND_CID,0);				// reading CID Registers
	if(r1 != 0)return r1;
	while(spiTransferByte(0xFF)!=MMC_STARTBLOCK_READ);// wait for block start
	for(i=0; i<16; i++){
		*buffer++=spiTransferByte(0xFF);			// read in data  16Byte
	}
	spiTransferByte(0xFF);							// read 16-bit CRC
	spiTransferByte(0xFF);
	CSH;											// release chip select
	
	return(0);
}
//-------------------------------------------------------------------------
//Routine for reading CSD Registers from MMC/SD-Card (16Bytes)
//Return 0 if no Error.
uint8_t Read_CSD_MMC(uint8_t *buffer){
	uint8_t r1,i;
		
	CSL;											// assert chip select
	r1 = mmcCommand(MMC_SEND_CSD,0);				// reading CSD Registers
	if(r1 != 0)return r1;
	while(spiTransferByte(0xFF)!=MMC_STARTBLOCK_READ);// wait for block start
	for(i=0; i<16; i++){
		*buffer++=spiTransferByte(0xFF);			// read in data
	}
	spiTransferByte(0xFF);							// read 16-bit CRC
	spiTransferByte(0xFF);
	CSH;
	
	return(0);
}
//-------------------------------------------------------------------------
//returns the :
// 	size of the card in MB ( ret * 1024^2) == bytes
// 	sector count and multiplier MB are in u08 == C_SIZE / (2^(9-C_SIZE_MULT))
// 	name of the media 
void MMC_get_volume_info(void){
	uint8_t i,buffer[16];
    struct MMC_VOLUME_INFO vinf;
    
	for(i=0;i<16;i++)buffer[i]=0;
	Read_CSD_MMC(buffer);
	
	vinf.sector_count=buffer[6]&0x03;
	vinf.sector_count<<=8;
	vinf.sector_count+=buffer[7];
	vinf.sector_count<<=2;
	vinf.sector_count+=(buffer[8]&0xc0)>>6;
		
	vinf.sector_multiply=buffer[9]&0x03;
	vinf.sector_multiply<<=1;
	vinf.sector_multiply+=(buffer[10]&0x80)>>7;
	//SD的容量
	vinf.size_MB=vinf.sector_count>>(9-vinf.sector_multiply);

	for(i=0;i<16;i++)buffer[i]=0;
	Read_CID_MMC(buffer);
	//SD的名称
	vinf.name[0]=buffer[3];
	vinf.name[1]=buffer[4];
	vinf.name[2]=buffer[5];
	vinf.name[3]=buffer[6];
	vinf.name[4]=buffer[7];
	vinf.name[5]=0x00; //end flag
}
//-------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -