
(圖一)

(圖二)
/********************************************************************************************************************
函數名:unsigned char mmc_command(unsigned char *comm,unsigned char retuen_dat)
功能:向sd卡寫命令
返回: 1- >操作失敗 0->成功
********************************************************************************************************************/
unsigned char mmc_command(unsigned char *comm,unsigned char retuen_dat)
{
unsigned char n,temp,count,n_count;
count = 0;
do
{
SSEL_D(0);
for(n=0;n<6;n++)
SPI_Send_Dat(*comm++);
for(n_count=0;n_count<5;n_count++)
{
temp = SPI_Receiver_Dat();
if(temp == retuen_dat)break;
}
SSEL_D(1);
SPI_Send_Dat(0xff);
if(count>100) return 1;
}while(temp!=retuen_dat);
return 0;
}
/*******************************************************************************************************
函數名:void mmc_init(void)
功能:初始化sd卡
返回: 無
*******************************************************************************************************/
void mmc_init(void)
{
unsigned char command_dat[6];
unsigned char n;
for(n=0;n<6;n++) command_dat[n] = 0;
SPI_Init();
for(n=0;n<16;n++)
SPI_Send_Dat(0xff);//圖一 同步用至少74個周期
command_dat[0] = 0x40;
command_dat[5] = 0x95;
mmc_command(command_dat,0x01);//圖二
command_dat[0] = 0x41;
command_dat[5] = 0xff;
mmc_command(command_dat,0x00);//圖二
}


/*******************************************************************************************************
函數名:void write_mmc_dat(unsigned char *comm,unsigned char *dat,unsigned int len)
功能:向sd寫數據(底層)
返回: 無
*******************************************************************************************************/
void write_mmc_dat(unsigned char *comm,unsigned char *dat,unsigned int len)
{
unsigned char n,temp,n_count;//,count;
unsigned int count;
count = 0;
for(count=0;count<5;count++)
{
SSEL_D(1);
SPI_Send_Dat(0xff);
SSEL_D(0);
for(n=0;n<6;n++)
SPI_Send_Dat(*comm++);
for(n_count=0;n_count<5;n_count++)
{
temp = SPI_Receiver_Dat();
if(temp == 0)break;
}
if(temp == 0)break;
}
SPI_Send_Dat(0xff);
SPI_Send_Dat(0xff);
SPI_Send_Dat(0xfE);//開始寫
for(count=0;count<len;count++)
{
SPI_Send_Dat(*dat);
dat++;
}
SPI_Send_Dat(0xff);
SPI_Send_Dat(0xff);
temp = SPI_Receiver_Dat();
if( temp&0x1f!=0x05);//寫失敗
SSEL_D(1);
SPI_Send_Dat(0xff);
}
/*******************************************************************************************************
函數名:void write_mmc_dat(unsigned char *comm,unsigned char *dat,unsigned int len)
功能:向sd寫數據
返回: 無
*******************************************************************************************************/
void MMCWdBolckOne(unsigned long addr,unsigned char *buffer)
{
unsigned char command_dat[6];
command_dat[0] = 0x40 + 24; // READ SINGLE BLOCK
addr <<= 9; // addr*512,取512的整數倍
command_dat[1] = (addr >> 24);
command_dat[2] = (addr >> 16);
command_dat[3] = (addr >> 8);
command_dat[4] = (addr >> 0);
command_dat[5] = 0;
write_mmc_dat(command_dat,buffer,512);
}

/*******************************************************************************************************
函數名:void write_mmc_dat(unsigned char *comm,unsigned char *dat,unsigned int len)
功能:向sd讀數據(底層)
返回: 無
*******************************************************************************************************/
void read_mmc_dat(unsigned char *comm,unsigned char *dat,unsigned int len)
{
unsigned char n,temp,count,n_count;
count = 0;
for(count=0;count<5;count++)
{
SSEL_D(1);
SPI_Send_Dat(0xff);
SSEL_D(0);
for(n=0;n<6;n++)
SPI_Send_Dat(*comm++);
for(n_count=0;n_count<5;n_count++)
{
temp = SPI_Receiver_Dat();
if(temp == 0)break;
}
if(temp == 0)break;
}
for(n_count=0;n_count<50;n_count++)
{
temp = SPI_Receiver_Dat();
if(temp == 0xfe)break;
}
while(len--)
{
*dat = SPI_Receiver_Dat();
dat++;
}
SPI_Send_Dat(0xff);
SPI_Send_Dat(0xff);
SSEL_D(1);
SPI_Send_Dat(0xff);
}
/*******************************************************************************************************
函數名:void write_mmc_dat(unsigned char *comm,unsigned char *dat,unsigned int len)
功能:讀sd寫數據
返回: 無
*******************************************************************************************************/
void MMCRdBolckOne(unsigned long addr,unsigned char *buffer,unsigned int len)
{
unsigned char command_dat[6];
command_dat[0] = 0x40 + 17; // READ SINGLE BLOCK
addr <<= 9; // addr*512,取512的整數倍
command_dat[1] = (addr >> 24);
command_dat[2] = (addr >> 16);
command_dat[3] = (addr >> 8);
command_dat[4] = (addr >> 0);
command_dat[5] = 0;
read_mmc_dat(command_dat,buffer,len);
}
#define SCK_IO(x) (x?(P1=0X0f):(P1=0X0f))//1->輸出 0->輸入
#define MOSI_IO(x) (x?(P1=0X0f):(P1=0X0f))
#define MISO_IO(x) (x?(P1=0X0f):(P1=0X0f))
#define SSEL_IO(x) (x?(P1=0X0f):(P1=0X0f))
#define SCK_D(x) (x?(P1|=0X01):(P1&=0XFE))
#define MOSI_D(x) (x?(P1|=0X02):(P1&=0XFD))
#define SSEL_D(X) (X?(P1|=0X08):(P1&=0XF7))
#define MISO_I() (P1&0X04)
/**********************************************
模式零 spi 寫數據
***********************************************/
void SPI_Send_Dat(unsigned char dat)
{
unsigned char n;
for(n=0;n<8;n++)
{
SCK_D(0);
if(dat&0x80)MOSI_D(1);
else MOSI_D(0);
dat<<=1;
SCK_D(1);
}
SCK_D(0);
}
/*********************************************
模式零 spi 讀數據
*********************************************/
unsigned char SPI_Receiver_Dat(void)
{
unsigned char n ,dat,bit_t;
for(n=0;n<8;n++)
{
SCK_D(0);
dat<<=1;
if(MISO_I())dat|=0x01;
else dat&=0xfe;
SCK_D(1);
}
SCK_D(0);
return dat;
}
void SPI_Init(void)
{
SCK_IO(1) ;
MOSI_IO(1) ;
MISO_IO(0) ;
SSEL_IO(1) ;
SSEL_D(1);
MOSI_D(1);
SCK_D(0);
}

上行為寫 下行為讀
code unsigned char leab[512] = {0x55,0xaa,2,3,4,5,6,7,8,9};
unsigned char rmmc[16];
main()
{
unsigned char i;
Time_Count0_Init(0 ,1); //10ms時基
start_time0(); //開啟定時器0
Time_Count1_Init(0,2); //用于產生9600串口波特率
start_time1() ; //開啟定時器1
Uart_Config(1); //配置串口
interrupt_Open(); //打開中斷
mmc_init();
MMCWdBolckOne(0,leab);
for(i=0;i<16;i++)
Send_Data(leab[i]);
MMCRdBolckOne(0x00,rmmc,10);
for(i=0;i<16;i++)
Send_Data(rmmc[i]);
while (1);
}