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

📄 mmc.c

📁 C51单片机SPI方式读写SD卡
💻 C
字号:

#include <c8051f350.h> // SFR declarations

// MMC commands
#define MMC_GO_IDLE_STATE 0
#define MMC_SEND_OP_COND 1
#define MMC_SEND_CSD 9
#define MMC_SEND_CID 10
#define MMC_SEND_STATUS 13
#define MMC_SET_BLOCKLEN 16
#define MMC_READ_SINGLE_BLOCK 17
#define MMC_WRITE_BLOCK 24
#define MMC_PROGRAM_CSD 27
#define MMC_SET_WRITE_PROT 28
#define MMC_CLR_WRITE_PROT 29
#define MMC_SEND_WRITE_PROT 30
#define MMC_TAG_SECTOR_START 32
#define MMC_TAG_SECTOR_END 33
#define MMC_UNTAG_SECTOR 34
#define MMC_TAG_ERASE_GROUP_START 35
#define MMC_TAG_ERARE_GROUP_END 36
#define MMC_UNTAG_ERASE_GROUP 37
#define MMC_ERASE 38
#define MMC_CRC_ON_OFF 59

#define R1_BUSY 128
#define R1_PARAMETER 64
#define R1_ADDRESS 32
#define R1_ERASE_SEQ 16
#define R1_COM_CRC 8
#define R1_ILLEGAL_COM 4
#define R1_ERASE_RESET 2
#define R1_IDLE_STATE 1

sbit led1 = P0^7;
sbit led2 = P0^6;

sbit mmc_sck = P1^0;
sbit mmc_miso = P1^1;
sbit mmc_mosi = P1^2;
sbit mmc_cs = P1^3;

#define SYSmmc_sck 24500000 / 8 // SYSmmc_sck frequency in Hz

unsigned char xdata ram_data[512];

void PORT_Init (void);
unsigned char SPI_tx_rx(unsigned char spi_data);
unsigned char MMC_sendCmd(unsigned char cmd,unsigned char A31_24,unsigned char A23_16,unsigned char A15_8,unsigned char A7_0);
void MMC_finish(void);
void MMC_flush(unsigned char flush_num);
void MMC_reset(void);
unsigned char MMC_check(void);
unsigned long MMC_capactity(void);
void MMC_name(void);

//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main (void)
{
  	// disable watchdog timer
   	PCA0MD &= ~0x40;                   	// 禁止看门狗
   	SP = 0x7F;							// 设置堆栈
   	PORT_Init ();                       // Initialize crossbar and GPIO
	OSCICN = 0xC0;                      // configure internal oscillator for
	                                    // its lowest frequency
	RSTSRC = 0x04;                      // enable missing clock detector

	MMC_reset();
	while (MMC_check())
	{
	}
	MMC_name();
	while (1)
	{
	}
}

/********************端口初始化******************/
void PORT_Init (void)
{
   XBR0		= 0x03;                       // 设置交叉开关
   XBR1		= 0x40;                       // 
   P0MDOUT	= 0xFD;                       // 
   P1MDOUT	= 0xFD;
   mmc_cs = 1;
   mmc_mosi = 1;
   mmc_sck = 1;
   led1 = 0;
   led2 = 0;
}

/***********SPI读取/写入****基础SPI传送命令******/
unsigned char SPI_tx_rx(unsigned char spi_data) 
{
	char i;
	for (i=0;i<8;i++)
	{
		mmc_sck = 0;
		if (spi_data >= 128) mmc_mosi = 1;
			else mmc_mosi = 0;
		mmc_sck = 1;
		spi_data = ((spi_data << 1) & 0xFE) | mmc_miso;
	}
	return spi_data;
}

//------------------------------------------------------------------------------------
/***********MMC_sendCmd();*****基础传送命令*******/
//------------------------------------------------------------------------------------
uchar MMC_sendCmd(uchar cmd,uchar A31_24,uchar A23_16,uchar A15_8,uchar A7_0)
{
	signed char temp;
	mmc_cs = 0;
	
	SPI_tx_rx(cmd|0x40); //cmd"01xxxxxx"
	SPI_tx_rx(A31_24);
	SPI_tx_rx(A23_16);
	SPI_tx_rx(A15_8);
	SPI_tx_rx(A7_0);
	SPI_tx_rx(0x95); //crc for cmd0
	
	SPI_tx_rx(0xff); //one empty cycle
	
	temp=SPI_tx_rx(0xff); //0=busy 
	if ((temp-0x80)>=0) //0b1xxxxxxx=err
	{
		temp=0xff;
		while (SPI_tx_rx(0xff)==0); 
		led1 = 1; //test point
	}
	else if (cmd==MMC_SEND_STATUS) //如果是读状态命令
	{
		temp=SPI_tx_rx(0xff); //read STATUS
		while (SPI_tx_rx(0xff)==0); 
		led1 = 1;
	}
	else //是其他命令
	{
		while (SPI_tx_rx(0xff)==0); 
		led1 = 1;
	}
	return temp; 
} 

//------------------------------------------------------------------------------------
/***********MMC_finish();***停止卡片******/
//------------------------------------------------------------------------------------
void MMC_finish(void)
{
	mmc_cs = 1;
	SPI_tx_rx(0xff);
}

//------------------------------------------------------------------------------------
/***********MMC_flush();*****丢弃几个字节*******/
//------------------------------------------------------------------------------------
void MMC_flush(uchar flush_num)
{
	uchar counter;
	for (counter=0;counter<flush_num;counter++) SPI_tx_rx(0xff); //丢弃几个字节
	MMC_finish(); 
}

//------------------------------------------------------------------------------------
/***********MMC_reset();***将MMC卡转到SPI模式****/
//------------------------------------------------------------------------------------
void MMC_reset(void)
{
	uchar counter,mmc_response,lcd_add;
	for (counter=0;counter<11;counter++) SPI_tx_rx(0xff);//80个时钟开始总线
	
	mmc_response=MMC_sendCmd(MMC_GO_IDLE_STATE,0,0,0,0); //send cmd0
	MMC_finish();
	
	for (counter=0;counter<80;counter++) //失败尝试次数
	{
		
		mmc_response=MMC_sendCmd(MMC_SEND_OP_COND,0,0,0,0);
		MMC_finish();
		
		if (mmc_response==0) //切换到SPI成功
		{
			led2 = 1;
			counter=81; //跳出失败尝试次数
		}
		else led1 = 1; //切换到SPI失败
		
	} 
	
}

//------------------------------------------------------------------------------------
/***********MMC_check();******测试卡是否正常为0***********/
//------------------------------------------------------------------------------------
uchar MMC_check(void)
{
	uchar mmc_response;
	mmc_response=MMC_sendCmd(MMC_SEND_STATUS,0,0,0,0); //send cmd
	MMC_finish();
	return (mmc_response&0x93);
} 


//------------------------------------------------------------------------------------
/***********MMC_name();**获得卡的名字*****/
//------------------------------------------------------------------------------------
void MMC_name(void)
{
	uchar counter,lcd_add,mmc_response=1;
	mmc_response=MMC_sendCmd(MMC_SEND_CID,0,0,0,0);
	while (mmc_response) //读到数据为0表示正常,就跳出
	{
		MMC_finish();
		mmc_response=MMC_sendCmd(MMC_SEND_CID,0,0,0,0);
		led1 = 1; //test point
		// prog_flag=1; //错误标记
	}
	led1 = 0; //test point
	for (counter=0;counter<26;counter++)
	{
		ram_data[counter]=SPI_tx_rx(0xff);
	} 
	MMC_flush(8); 
} 

//------------------------------------------------------------------------------------
/***********MMC_capactity();******************/
//------------------------------------------------------------------------------------
unsigned long MMC_capactity(void)
{
	uchar counter,lcd_add,mmc_response=1;
	mmc_response=MMC_sendCmd(MMC_SEND_CSD,0,0,0,0);
	while (mmc_response) //读到数据为0表示正常,就跳出
	{
		MMC_finish();
		mmc_response=MMC_sendCmd(MMC_SEND_CID,0,0,0,0);
		//LCD_write(mmc_response,1); //test point
		led1 = 1; //test point
		// prog_flag=1; //错误标记
	}
	led1 = 0; //test point
	for (counter=0;counter<26;counter++)
	{
		ram_data[counter]=SPI_tx_rx(0xff);
		//LCD_write(ram_data[counter],1); //test point
	} 
	MMC_flush(8); 
	
} 

⌨️ 快捷键说明

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