本人想对SD卡进行简单读写操作,就对一个扇区写入数据,然后读出来。可是却碰到一个奇怪的问题,本人以SPI方式读写SD卡,在复位,初始化等过程都正常,但在对一个扇区写入数据时,在写入扇区写命令并得到SD卡正确的0回应后,随后写入的数据都发生变化,所有数据都左移一位,相当于所有数据都乘2。读数据倒正常。为了验正本人的SPI读写函数正确,特地在SD卡读写前先进行对SPI存储芯片25AA010A的读写测试,证明可以对25AA010A芯片正常写入16字节数据,也能正常读出数据。但对SD卡却出现奇怪现象,请高手指点问题出在哪。
这是本人的原理图:
这是终端显示情况:
SPI存储芯片写入内存图:
SPI终端监视图:
以下是程序:
- #include<reg52.h>
- sbit SD_SCL=P3^5;
- sbit SD_SI=P3^6;
- sbit SD_SO=P3^7;
- sbit SD_CS=P3^4;
- #define DELAY_TIME 100
- #define TryNum 127
- #define INIT_CMD0_ERROR 0x01
- #define INIT_CMD1_ERROR 0x02
- #define WRITE_BLOCK_ERROR 0x03
- #define READ_BLOCK_ERROR 0x04
- unsigned char waitnum;
- #define uint unsigned int
- #define uchar unsigned char
- void delay(int i)
- {int x;
- for(x=0;x<i;x++);
- }
- //==============================================================
- unsigned char bdata _dat;
- sbit _dat7=_dat^7;
- sbit _dat6=_dat^6;
- sbit _dat5=_dat^5;
- sbit _dat4=_dat^4;
- sbit _dat3=_dat^3;
- sbit _dat2=_dat^2;
- sbit _dat1=_dat^1;
- sbit _dat0=_dat^0;
- void SD_spi_write(unsigned char x)
- {_dat=x;
- SD_SI=_dat7;
- SD_SCL=0;
- delay(waitnum);
- SD_SCL=1;
- delay(waitnum);
- SD_SI=_dat6;
- SD_SCL=0;
- delay(waitnum);
- SD_SCL=1;
- delay(waitnum);
- SD_SI=_dat5;
- SD_SCL=0;
- delay(waitnum);
- SD_SCL=1;
- delay(waitnum);
- SD_SI=_dat4;
- SD_SCL=0;
- delay(waitnum);
- SD_SCL=1;
- delay(waitnum);
- SD_SI=_dat3;
- SD_SCL=0;
- delay(waitnum);
- SD_SCL=1;
- delay(waitnum);
- SD_SI=_dat2;
- SD_SCL=0;
- delay(waitnum);
- SD_SCL=1;
- delay(waitnum);
- SD_SI=_dat1;
- SD_SCL=0;
- delay(waitnum);
- SD_SCL=1;
- delay(waitnum);
- SD_SI=_dat0;
- SD_SCL=0;
- delay(waitnum);
- SD_SCL=1;
- delay(waitnum);
- }
- unsigned char SD_spi_read()
- {SD_SO=1;
- SD_SCL=1;
- delay(waitnum);
- SD_SCL=0;
- delay(waitnum);
- _dat7=SD_SO;
- SD_SCL=1;
- delay(waitnum);
- SD_SCL=0;
- delay(waitnum);
- _dat6=SD_SO;
- SD_SCL=1;
- delay(waitnum);
- SD_SCL=0;
- delay(waitnum);
- _dat5=SD_SO;
- SD_SCL=1;
- delay(waitnum);
- SD_SCL=0;
- delay(waitnum);
- _dat4=SD_SO;
- SD_SCL=1;
- delay(waitnum);
- SD_SCL=0;
- delay(waitnum);
- _dat3=SD_SO;
- SD_SCL=1;
- delay(waitnum);
- SD_SCL=0;
- delay(waitnum);
- _dat2=SD_SO;
- SD_SCL=1;
- delay(waitnum);
- SD_SCL=0;
- delay(waitnum);
- _dat1=SD_SO;
- SD_SCL=1;
- delay(waitnum);
- SD_SCL=0;
- delay(waitnum);
- _dat0=SD_SO;
- return _dat;
- }
- //##########################################################
- char Rec_C;
- void SerInit()
- {SCON=0x50;
- TMOD=0x22;
- TH1=0xfd;
- TL1=0xfd;
- EA=1;
- ES=1;
- ET1=0;
- TR1=1;
- }
- void Serp()interrupt 4
- {if(RI==1)
- {Rec_C=SBUF;
- RI=0;
- }
- }
- void SendC(uchar ci)
- {SBUF=ci;
- while(TI==0);
- TI==0;
- }
- void Sendstr(uchar *cp)
- {int i=0;
- while(cp[ i]!=0)[ i]
- {delay(50);
- SendC(cp[ i]);[ i]
- delay(50);
- i++;
- }
- }
- //##########################################################
- void SPI_Write_Addstr(int add,int num,char *cp)
- {int i;
- SD_CS=0;
- SD_spi_write(6);
- SD_CS=1;delay(8);
- SD_CS=0;
- SD_spi_write(2);
- SD_spi_write(add);
- for(i=0;i<num;i++)
- {SD_spi_write(cp[ i]);[ i]
- SendC(cp[ i]);[ i]
- }
- SD_CS=1;
- }
- //-----------------------------------------------------------
- void SPI_Read_Addstr(int add,int len)
- {int i;
- SD_CS=0;
- SD_spi_write(3);
- SD_spi_write(add);
- for(i=0;i<len;i++)
- SendC(SD_spi_read());
- SD_CS=1;
- }
- //###########################################################
- unsigned char SD_Write_Cmd(unsigned char *pcmd)
- {unsigned char temp,time=0;
- SD_CS=1;
- SD_spi_write(0xff);
- SD_CS=0;
- SD_spi_write(pcmd[0]);
- SD_spi_write(pcmd[1]);
- SD_spi_write(pcmd[2]);
- SD_spi_write(pcmd[3]);
- SD_spi_write(pcmd[4]);
- SD_spi_write(pcmd[5]);
- do{temp=SD_spi_read();
- time++;
- }while((temp==0xff)&&(time<TryNum));
- return temp;
- }
- //================================================================
- unsigned char SD_Reset()
- {unsigned char i,time,temp;
- unsigned char pcmd[]={0x40,0,0,0,0,0x95};
- SD_CS=1;
- for(i=0;i<0x0f;i++)
- {SD_spi_write(0xff);
- }
- SD_CS=0;
- time=0;
- do{temp=SD_Write_Cmd(pcmd);
- time++;
- if(time==TryNum){SD_CS=1;return(INIT_CMD0_ERROR);}
- }while(temp!=0x01);
- SD_CS=1;
- SD_spi_write(0xff);
- return 0;
- }
- //==================================================================
- unsigned char SD_Init()
- {unsigned char time,temp;
- unsigned char pcmd[]={0x41,0,0,0x02,0,0xff};
- SD_CS=0;
- time=0;
- do{temp=SD_Write_Cmd(pcmd);
- time++;
- if(time==TryNum){SD_CS=1;return(INIT_CMD1_ERROR);}
- }while(temp!=0);
- SD_CS=1;
- SD_spi_write(0xff);
- return 0;
- }
- //==================================================================
- unsigned char SD_Write_Sector(unsigned long addr)
- {unsigned char temp,time;
- unsigned int i;
- unsigned char pcmd[]={0x58,0,0,0,0,0xff};
- waitnum=1;
- addr<<=9;
- pcmd[1]=((addr&0xff000000)>>24);
- pcmd[2]=((addr&0x00ff0000)>>16);
- pcmd[3]=((addr&0x0000ff00)>>8);
- SD_CS=0;
- time=0;
- do{temp=SD_Write_Cmd(pcmd);
- time++;
- if(time==TryNum){SD_CS=1;return temp;}
- }while(temp!=0);//偿试写入命令并获取反应不超过127次
- for(i=0;i<100;i++)SD_spi_read();
- SD_spi_write(0xff);//此句本来应写入标志字0xfe;因写入数据会左移一位,所以写入0xff,左移1位后正好是0xfe;勉强完成写入扇区操作。
- for(i=0;i<512;i++)//写入512个#
- {SD_spi_write(0x23);
- if(i%32==0)Sendstr("\r");
- SendC(0x23);
- }
- SD_spi_write(0xff);
- SD_spi_write(0xff);
- temp=SD_spi_read();
- if((temp&0x1f)!=0x05){SD_CS=1;return WRITE_BLOCK_ERROR;}
- while(SD_spi_read()!=0xff);
- SD_CS=1;
- SD_spi_write(0xff);
- return 0;
- }
- //===================================================================
- unsigned char SD_Read_Sector(unsigned long addr)
- {unsigned char temp,time;
- unsigned int j;
- unsigned char pcmd[]={0x51,0,0,0,0,0xff};
- addr<<=9;
- pcmd[1]=((addr&0xff000000)>>24);
- pcmd[2]=((addr&0x00ff0000)>>16);
- pcmd[3]=((addr&0x0000ff00)>>8);
- SD_CS=0;
- time=0;
- do{temp=SD_Write_Cmd(pcmd);
- time++;
- if(time==TryNum){return READ_BLOCK_ERROR;}
- }while(temp!=0);//偿试写入命令并获取反应不超过127次
- while(SD_spi_read()!=0xfe);//读到标志字0xfe为止
- for(j=0;j<512;j++)//读出512个字节
- {temp=SD_spi_read();
- if(j%32==0)Sendstr("\r");
- SendC(temp);
- }
- SD_spi_read();
- SD_spi_read();
- SD_CS=1;
- SD_spi_write(0xff);
- return 0;
- }
- //################################################################
- main()
- {uchar i,j;
- SerInit();
- Sendstr("SPI RW Test\r");
- SPI_Write_Addstr(0x40,16,"123456789abcdef");
- delay(1000);
- SendC('\r');
- SPI_Read_Addstr(0x40,16);
- Sendstr("\rSD RW Test...\r");
- waitnum=100;
- i=SD_Reset();
- Sendstr("\rreset=");
- SendC(i+0x30);
- i=SD_Init();
- Sendstr("\rinit=");
- SendC(i+0x30);
- waitnum=2;
- i=SD_Write_Sector(0x5);
- Sendstr("\rwrite sec=");
- SendC(i+0x30);
- i=SD_Read_Sector(0x6);
- Sendstr("\rread sec=");
- SendC(i+0x30);
- while(1);
- }
复制代码
|