上源程序:
#include
#include
typedef unsigned int uint;
typedef unsigned char uchar;
uchar CMD0[6]={0x40,0x00,0x00,0x00,0x00,0x95};//命令0
uchar CMD1[6]={0x41,0x00,0x00,0x00,0x00,0xff};//命令1
uchar CMD24[6];
uchar CMD17[6];
uchar a[512];
void delay(uint i)
{
while(i--);
}
void spi_init(void)
{
DDRB|=BIT(4);//CS片选
DDRB|=BIT(5);//MOSI
DDRB&=~(1<<6);//MISO
DDRB|=BIT(7);//SCK
SPCR=0x12;//设置SPI
SPSR=0x00;
PORTB=0xff;
SPCR|=(1<<6);//使能SPI
}
uchar send(uchar dat)//发送数据
{
uchar dat1=0;
SPDR=dat;
while(!(SPSR&(1<<7)));//等待数据发送完成
dat1=SPDR;
return dat1;
}
void SPI_HIGH(void)
{
SPCR|=(0<
SPSR|=(1<
}
uchar send_cmd(uchar *CMD)//发送命令
{
uchar i,dat;
PORTB|=(1<<4);//CS=0;
send(0xff);//一定要有这一步,否则可能初始化不能成功
PORTB&=~(1<<4);
send(CMD[0]);
send(CMD[1]);
send(CMD[2]);
send(CMD[3]);
send(CMD[4]);
send(CMD[5]);
do
{
dat=send(0xff);//读回命令的响应
i++;
}while((i<200)&&(dat==0xff));
return dat;
}
uchar MMC_init(void)//MMC卡的初始化
{
uchar n=0xff,j=0xff;//MMC卡的初始化可能要多次发送命令才会初始化成功
uint m;
PORTB&=~(1<<4);
for(m=0;m<0x0f;m++)
{
send(0xff);
}//上电发送大于74个时钟 16*8
do
{
n=send_cmd(CMD0);//发送CMD0复位,响应R1=0x01
m++;
}while((m<200)&&(n!=0x01));
m=0;
do
{
j=send_cmd(CMD1);//发送CMD1激活卡,响应R1=0x00
m++;
}while((m<2000)&&(j!=0x00));
PORTB|=(1<<4);
return n;//初始化成功
}
uchar write_byte(void)//
{
uint i;
uchar dat;
CMD24[0]=0x58;
CMD24[1]=0x00;
CMD24[2]=0x00;
CMD24[3]=0x00;
CMD24[4]=0x00;
CMD24[5]=0xff;
send_cmd(CMD24);//命令只要发送一次就可了当初始化成功的时候
send(0xff);//填充时钟
send(0xfe);//发送起始令牌
for(i=0;i<512;i++)
{
send(0x02);
}
send(0xff);
send(0xff);//两个字节的校检字节
dat=send(0xff);//接受到0x05表示成功
return dat;
}
void read_byte(void)//读数据块命令成功
{
uint i;
CMD17[0]=0x40+17;
CMD17[1]=0x00;
CMD17[2]=0x00;
CMD17[3]=0x00;
CMD17[4]=0x00;
CMD17[5]=0xff;
send_cmd(CMD17);//发送读数据命令的时候,只要发一次,不能多发否则会出现各种问题
while(send(0xff)!=0xfe);//等待第一个数据令牌
for(i=0;i<512;i++)
{
a[i]=send(0xff);
}
send(0xff);
send(0xff);//两个字节的校检字节
}
void main(void)
{
DDRD=0xff;
DDRC=0xff;
PORTD=0xff;
DDRA=0xff;
PORTA=0xff;
spi_init();
PORTD=MMC_init();
PORTC=write_byte();
read_byte();
PORTD=a[510];
while(1);
}
已经测试过正确