mmc_lib.c

来自「用ATMEL AVR CPU开发MMC CARD 的MMC库」· C语言 代码 · 共 189 行

C
189
字号
#include <avr/io.h>
#include "mmc_lib.h"

void mmc_send_byte(unsigned char data)
{
	SPDR=data;
	loop_until_bit_is_set(SPSR, SPIF); // wait for byte transmitted...
}

unsigned char mmc_write_cmd(char *cmd)
{
	unsigned char i;
	
	mmc_send_byte(0xFF); //Dummy delay 8 clocks
	cbi(MMC_PORT, MMC_CS);	//MMC Chip Select -> Low (activate)
	
	for (i=0; i<6; i++) {//Send 6 Bytes
		mmc_send_byte(*cmd++);
	}
	
	for(i=0; i<255; i++) {//waiting for response (!0xff)
		mmc_send_byte(0xFF);
		
		if (SPDR != 0xFF) {
			return(SPDR);
		}
	}
	
	return(SPDR); // TimeOut !
}

unsigned char mmc_init(void)
{
	cbi(MMC_DDR, SPI_MISO);	//MMC Data Out -> Input
	sbi(MMC_DDR, SPI_CLK);	//MMC Clock -> Output
	sbi(MMC_DDR, SPI_MOSI);	//MMC Data In -> Output
	sbi(MMC_DDR, MMC_CS);		//MMC Chip Select -> Output
	
	sbi(MMC_PORT, MMC_CS);	//MMC Chip Select -> High (deactivate)
	
	SPCR = 1<<SPE | 1<<MSTR | 1<<SPR0; //SPI Enable, SPI Master Mode
	
	unsigned char i;
	
	for (i=0; i<15; i++) { //Pulse 80+ clocks to reset MMC
		mmc_send_byte(0xFF);
	}
	
	unsigned char res;

	char cmd[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95}; //CMD0
	
	res=mmc_write_cmd(cmd); //store result of reset command, should be 0x01
	sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
	mmc_send_byte(0xFF);
		
	if (res != 0x01) {	//Response R1 from MMC (0x01: IDLE, The card is in idle state and running the initializing process.)
		return(1);
	}
	
	cmd[0]=0x41;
	cmd[5]=0xFF;
	
	i=0;
	
	while((mmc_write_cmd(cmd) != 0) && (i < 255)) {
		sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
		mmc_send_byte(0xFF);
		i++;
	}
	sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
	
	if (i < 255) {
		return(0);
	}
	
	return(2);
}

unsigned char mmc_read_block(char *cmd, char *buffer, unsigned long count)
{
	if (mmc_write_cmd(cmd) != 0x00) {
		sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
		return(1); //wrong response!
	}
	
	unsigned char res=0xff;
	unsigned long i=0;
	
	while((res != 0xFE) && (i < 255)) { //wait for startbyte (0xFE)
		mmc_send_byte(0xFF);
		res=SPDR;
		i++;
	}
	
	if (i >= 255) { //startbyte received ?
		sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
		return(2);
	}
	
	for (i=0;i<count;i++)
	{
		mmc_send_byte(0xFF);
		*buffer++ = SPDR;
	}
	
	//read 2 bytes CRC (not used);
	mmc_send_byte(0xFF);
	mmc_send_byte(0xFF);
	
	sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
	return(0);
}

unsigned char mmc_read_sector(unsigned long sector, char *buffer)
{
	char cmd[] = {0x51, 0x00, 0x00, 0x00, 0x00, 0xFF}; //CMD17
		
	sector = sector << 9;
	
	cmd[1] = (sector & 0xFF000000) >> 24;
	cmd[2] = (sector & 0x00FF0000) >> 16;
	cmd[3] = (sector & 0x0000FF00) >> 8;

	return(mmc_read_block(cmd, buffer, 512));
}


unsigned char mmc_write_sector(unsigned long sector, char *buffer)
{
	char cmd[] = {0x58, 0x00, 0x00, 0x00, 0x00, 0xFF}; //CMD24
		
	sector = sector << 9;
	
	cmd[1] = (sector & 0xFF000000) >> 24;
	cmd[2] = (sector & 0x00FF0000) >> 16;
	cmd[3] = (sector & 0x0000FF00) >> 8;

	if (mmc_write_cmd(cmd) != 0x00) {
		sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
		return(1); //cmd24 wrong response!
	}
	
	unsigned short i=0;
	
	for (i=0;i<255;i++) { //delay before sending datablock to MMC
		mmc_send_byte(0xFF);
	}
	mmc_send_byte(0xFE); //send startbyte
	
	for (i=0;i<512;i++) { //send datablock to MMC
		mmc_send_byte(*buffer++);
	}
	
	//write 2 dummy bytes to MMC (CRC);
	mmc_send_byte(0xFF);
	mmc_send_byte(0xFF);
	
	unsigned char res=0x00;
	
	i=0;
	
	while((res != 0xFF) && (i < 255)) { //wait while MMC is busy!
		mmc_send_byte(0xFF);
		res=SPDR;
		i++;
	}
	
	sbi(MMC_PORT, MMC_CS); //MMC Chip Select -> High (deactivate);
	if (i<255) {
		return(0);
	}
	else {
		return(2);
	}
}

unsigned char mmc_read_csd(char *buffer)
{
	char cmd[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
	return(mmc_read_block(cmd, buffer, 16));
}

unsigned char mmc_read_cid(char *buffer)
{
	char cmd[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
	return(mmc_read_block(cmd, buffer, 16));
}

⌨️ 快捷键说明

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