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

📄 mmc_lib.c

📁 SD和mmc卡的读写程序
💻 C
字号:
#include <avr/io.h>
#include "mmc_lib.h"

static unsigned char cmd[6];

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

static unsigned char send_cmd(void)
{
	unsigned short i;
	
	spi_send_byte(0xFF); //Dummy delay 8 clocks
	MMC_PORT &= ~(1<<MMC_CS);	//MMC Chip Select -> Low (activate)

	for (i=0; i<6; i++)
	{//Send 6 Bytes
		spi_send_byte(cmd[i]);
	}

	unsigned char result;
	
	for(i=0; i<128; i++)
	{//waiting for response (!0xff)
		spi_send_byte(0xFF);
		
		result = SPDR;
		
		if ((result & 0x80) == 0)
			break;
	}
	
	return(result); // TimeOut !
}

unsigned char mmc_init(void)
{
	MMC_DDR &= ~(1<<SPI_MISO);	//MMC Data Out -> Input
	MMC_DDR |= 1<<SPI_CLK | 1<<SPI_MOSI | 1<<MMC_CS;	//MMC Chip Select -> Output
		
	SPCR = 1<<SPE | 1<<MSTR | SPI_INIT_CLOCK; //SPI Enable, SPI Master Mode
	SPSR = SPI_DOUBLE_SPEED << SPI2X;
	
	unsigned char i;
	
	for (i=0; i<10; i++) { //Pulse 80+ clocks to reset MMC
		spi_send_byte(0xFF);
	}
	
	unsigned char res;

	cmd[0] = 0x40 + MMC_GO_IDLE_STATE;
	cmd[1] = 0x00; cmd[2] = 0x00; cmd[3] = 0x00; cmd[4] = 0x00; cmd[5] = 0x95;
	
	for (i=0; i<10; i++)
	{
		res=send_cmd(); //store result of reset command, should be 0x01
		MMC_PORT |= 1<<MMC_CS; //MMC Chip Select -> High (deactivate);
		spi_send_byte(0xFF);
		if (res == 0x01)
			break;
	}
	
	if (res != 0x01) //Response R1 from MMC (0x01: IDLE, The card is in idle state and running the initializing process.)
		return(MMC_INIT);
	
	cmd[0]=0x40 + MMC_SEND_OP_COND;
		
	i=0;
	
	while((send_cmd() != 0) && (i < 0xFF)) {
		MMC_PORT |= 1<<MMC_CS; //MMC Chip Select -> High (deactivate);
		spi_send_byte(0xFF);
		i++;
	}
	MMC_PORT |= 1<<MMC_CS; //MMC Chip Select -> High (deactivate);
	
	if (i < 0xFF)
		return(MMC_OK);

	return(MMC_TIMEOUT);
}

static unsigned char wait_start_byte(void)
{
	unsigned char i=0;
	
	do
	{
		spi_send_byte(0xFF);
		i++;
	} while ((SPDR != 0xFE) && (i<255));
	
	if (i<255)
		return MMC_OK;
	else
		return MMC_NOSTARTBYTE;
}

unsigned char mmc_start_read_block(unsigned long adr, unsigned char adrshift)
{
	adr = adr << adrshift;
	
	cmd[0] = 0x40 + MMC_READ_SINGLE_BLOCK;
	cmd[1] = (adr & 0xFF000000) >> 0x18;
	cmd[2] = (adr & 0x00FF0000) >> 0x10;
	cmd[3] = (adr & 0x0000FF00) >> 0x08;
	cmd[4] = (adr & 0x000000FF);
	cmd[5] = 0x95;
	
	SPCR = 1<<SPE | 1<<MSTR | SPI_READ_CLOCK; //SPI Enable, SPI Master Mode
	
	if (send_cmd() != 0x00) {
		MMC_PORT |= 1<<MMC_CS; //MMC Chip Select -> High (deactivate);
		return(MMC_CMDERROR); //wrong response!
	}
	
	if (wait_start_byte())
	{
		MMC_PORT |= 1<<MMC_CS; //MMC Chip Select -> High (deactivate);
		return MMC_NOSTARTBYTE;
	}
	
	return(MMC_OK);
}

void mmc_read_buffer(unsigned char *buf, unsigned short len)
{
	while (len--)
	{
		spi_send_byte(0xFF);
		*(buf++) = SPDR;
	}
}

void mmc_stop_read_block(void)
{
	//read 2 bytes CRC (not used);
	spi_send_byte(0xFF);
	spi_send_byte(0xFF);
	MMC_PORT |= 1<<MMC_CS; //MMC Chip Select -> High (deactivate);
}

void mmc_set_blocklen(unsigned short blocklen)
{
	cmd[0] = 0x40 + MMC_SET_BLOCKLEN;
	cmd[1] = 0x00;
	cmd[2] = 0x00;
	cmd[3] = blocklen >> 8;
	cmd[4] = blocklen;
	cmd[5] = 0x95;
	send_cmd();
}
	
unsigned char mmc_start_write_block(unsigned long adr, unsigned char adrshift)
{
	adr = adr << adrshift;
	
	cmd[0] = 0x40 + MMC_WRITE_BLOCK;
	cmd[1] = (adr & 0xFF000000) >> 0x18;
	cmd[2] = (adr & 0x00FF0000) >> 0x10;
	cmd[3] = (adr & 0x0000FF00) >> 0x08;
	cmd[4] = (adr & 0x000000FF);
	cmd[5] = 0x95;
	
	SPCR = 1<<SPE | 1<<MSTR | SPI_WRITE_CLOCK; //SPI Enable, SPI Master Mode
	
	if (send_cmd() != 0x00) {
		MMC_PORT |= 1<<MMC_CS; //MMC Chip Select -> High (deactivate);
		return(MMC_CMDERROR); //cmd24 wrong response!
	}

	unsigned char i=0;
	
	for (i=0;i<255;i++) { //delay before sending datablock to MMC
		spi_send_byte(0xFF);
	}
	spi_send_byte(0xFE); //send startbyte
	return (MMC_OK);
}

void mmc_write_buffer(unsigned char *buf, unsigned short len)
{
	while (len--)
	{//send datablock to MMC
		spi_send_byte(*buf++);
	}
}

void mmc_stop_write_block(void)
{
	//write 2 dummy bytes to MMC (CRC);
	spi_send_byte(0xFF);
	spi_send_byte(0xFF);
	
	do
	{
		spi_send_byte(0xFF);
	} while (SPDR != 0xFF);
	
	MMC_PORT |= 1<<MMC_CS; //MMC Chip Select -> High (deactivate);
}	

unsigned char mmc_read_csd(char *buffer)
{
	cmd[0]=0x40 + MMC_SEND_CSD;
	send_cmd();
	
	if (wait_start_byte())
	{
		MMC_PORT |= 1<<MMC_CS; //MMC Chip Select -> High (deactivate);
		return MMC_NOSTARTBYTE;
	}
	
	mmc_read_buffer(buffer, 16);
	mmc_stop_read_block();
	return(MMC_OK);
}

unsigned char mmc_read_cid(char *buffer)
{
	cmd[0]=0x40 + MMC_SEND_CID;
	send_cmd();
	
	if (wait_start_byte())
	{
		MMC_PORT |= 1<<MMC_CS; //MMC Chip Select -> High (deactivate);
		return MMC_NOSTARTBYTE;
	}
	
	mmc_read_buffer(buffer, 16);
	mmc_stop_read_block();
	return(MMC_OK);
}

⌨️ 快捷键说明

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