机电专业技术网

您现在的位置:| 机电专业技术网>电子电气>单片机> 正文 在线投稿

SD卡读写子程序

来源:  作者:  时间:2008-06-22  阅读:

硬件平台:atmega8L最小系统
                    硬spi(sd卡的初始化采用了io口模拟时序,因为在实验中发现要使用较低的速率才能稳定的初始化)
软件开发平台:ICC-AVR     version 6.31a
硬件配置:atmega8L    内部8m时钟
                    sandisk 128m sd卡
 
几个基本的子程序及其介绍:
 
1.io口模拟spi,实现数据发送,在初始化时使用
void iodatatransfer(unsigned char iodata)
 {
 unsigned char num,b;
 num=0x80;
 for (b=0;b<0x08;b++) 
     { 
    WDR();//feed the dog
  //SD_Write|=(1<<SPI_Clock);//sck=1
       SD_Write&=~(1<<SPI_Clock);//sck=0   
    if(iodata&num)
    SD_Write|=(1<<SPI_DO);//do=1
    else
    SD_Write&=~(1<<SPI_DO);//do=0
    delay_4ms();//4ms
    WDR();//feed the dog
    //SD_Write&=~(1<<SPI_Clock);//sck=0   
    SD_Write|=(1<<SPI_Clock);//sck=1
    delay_4ms();//4ms
    if(num>0x01)
    num=num>>1;
     } 
 } 
 
2.io口模拟spi,实现数据读取,在初始化时使用
 unsigned char iodataread(void)
 {
   unsigned char data,temp,b;
   data=0;
   temp=0;
   for (b=0;b<0x08;b++)
   {
    WDR();//feed the dog  
    SD_Write&=~(1<<SPI_Clock);//sck=0 
 delay_4ms();//4ms
    WDR();//feed the dog
 
    SD_Write|=(1<<SPI_Clock);//sck=1
 temp=SD_READ;
 temp&=0x10;//to maintain the pb.4 bit(data_in)
  WDR();//feed the dog
 if(temp)
  {
  data|=0x01; 
     }
 if(b<7)
  {
  data=data<<1;//
     }
 delay_4ms();//4ms
  WDR();//feed the dog
   }  
   return data;
 }

3.io口模拟spi,实现指令发送及读响应,在初始化时使用 
  unsigned char iocmd(unsigned char *cmd)
 {
 unsigned temp,a,timeout;
 temp=0xff;
 timeout=0;
 // Raise chip select  -----/ss=1
 SD_Disable(); 
 WDR();//feed the dog
 
 // Send an 8 bit pulse 
 iodatatransfer(0xff);
 WDR();//feed the dog
 // Lower chip select 
 SD_Enable();
  for(a=0;a<6;a++)
  {
  iodatatransfer(*cmd++);
  WDR();
  //transfer cmd in io_mode
  }
  while(temp==0xff)//
      { 
    WDR();//feed the dog
       temp=iodataread(); 
       if(timeout++>100) 
         { 
          break; 
         } 
      } 
  WDR();//feed the dog
 return(temp);//the respone of the byte_write_operation     
 }
 
4.硬spi读数据
 unsigned char Read_Byte_SD(void) 

 char Byte;
   //SD_Enable();
 SPDR=0xff; 
 while(!(SPSR&(1<<SPIF)));// 
 Byte=SPDR;
 return(Byte); 
}
 
5.硬spi写数据
void Write_Byte_SD(char Byte) 

//SD_Enable();
 SPDR=Byte; 
 while(!(SPSR&(1<<SPIF))); 
 
6.硬spi写指令及读响应
unsigned char Write_Command_SD(char *CMD) 

 unsigned char a; 
 unsigned char tmp=0xff; 
 unsigned char Timeout=0; 
 // Raise chip select  -----/ss=1
 SD_Disable(); 
 // Send an 8 bit pulse 
 Write_Byte_SD(0xFF); 
 
 // Lower chip select 
 SD_Enable(); 
 //Send the 6 byte command 
 for(a=0;a<0x06;a++) 
    { 
     Write_Byte_SD(*CMD++); 
    } 
 //Wait for the response 
 while(tmp==0xff)//
      { 
       tmp=Read_Byte_SD(); 
       if(Timeout++>100) 
         { 
          break; 
         } 
      } 
 //for some reason we need to delay here 
//delay_1ms();
 return(tmp);//the respone of the byte_write_operation 
}
 
7.初始化
unsigned char SDInit(void) 

 unsigned char a,b,retry,erroetoken; 
 unsigned char CMD[]={0x40,0x00,0x00,0x00,0x00,0x95};//cmd0
 // Set certain pins to inputs and others to outputs 
 // Only SPI_DI (data in) is an input 
 //SD_Direction_REG==ddrb
 SD_Direction_REG&=~(1<<SPI_DI); 
 SD_Direction_REG|=(1<<SPI_Clock); 
 SD_Direction_REG|=(1<<SPI_DO); 
 SD_Direction_REG|=(1<<SD_Chip_Select); 
 //SD_Direction_REG|=(1<<SPI_SS); 
 SD_Disable();
 //We need to wait for the SD_Direction_REG to be ready 
 for(a=0;a<200;a++) 
    { 
  WDR();//feed the dog
     nop();
  nop();
    }; 
 delay_1ms();
 
 SD_Disable();//  
 iodatatransfer(0xff);
 WDR();//feed the dog
 //return 0;///////////
 
 retry=0;
 SD_Enable();
 while((erroetoken=iocmd(CMD))!=0x01)//
 {
 WDR();
 //serial(erroetoken);
 if(retry++>200) 
 { //fail and return
 return 1; 
 } 
 } 
  //return 0;///////////
 
//Send the 2nd command 
 retry=0; 
 CMD[0]=0x41; 
 CMD[5]=0xFF; 
while(erroetoken=iocmd(CMD)!=0x00) 
      { 
    WDR();
       if (retry++>200) 
          {
          return 2; 
          } 
       }     
    
 //Set the SPI bus to full speed 
 SPCR=0x50; 
  SPSR|=0x01;
 //Raise Chip Select 
 SD_Disable(); 
 return 0; 
 
8.设置每次读的字节数
char SD_set_length(unsigned int length)
{
 unsigned char retry;
 //Command to set the block length;
 char CMD[]={0x50,0x00,0x00,0x00,0x00,0xFF}; //cmd16
 
 CMD[3]=((length&0xFF00)>>;//
 CMD[4]= (length&0x00FF); 
 while(Write_Command_SD(CMD)!=0)// 
      { 
    WDR();
       if (retry++>200) 
          { 
          return 1; 
          } 
       }
 SD_Disable();
 return 0;
}

9.write 512 bytes to a given sector from a  Byte_byte_long  Buffer
unsigned char SD_write_sector(unsigned long addr,unsigned char *Buffer,unsigned int Bytes)
{
 unsigned int a;
 unsigned char retry,temp;
 //Command to read a block;
 char CMD[]={0x58,0x00,0x00,0x00,0x00,0xFF};//cmd24
 CMD[1]=((addr&0xFF000000)>>24); 
 CMD[2]=((addr&0x00FF0000)>>16); 
 CMD[3]=((addr&0x0000FF00)>>;
 CMD[4]=(addr&0x000000FF);
  //Send the write command 
  
 while(Write_Command_SD(CMD)!=0) 
      { 
       if (retry++>50) 
          { 
          return 1; 
          } 
       } 
 //Send the start byte 
 Write_Byte_SD(0xfe);                                                                          
 //Read off all the bytes in the block 
 for(a=0;a<Bytes;++a) 
 { 
 Write_Byte_SD(*Buffer++);
 }  
 while((temp=Read_Byte_SD())&0x10);
 //serial(temp);//according to p101 of datasheet
 if((temp&0x0f)!=0x05)
 return 2;
 //Read CRC byte 
 while(SD_READ&0x10);//detect if data_in pb.4 is still busy(high)
  
 // Set SD_Chip_Select to high 
 SD_Disable(); 
 //SEI(); //re-enable interrupts 
 return 0; 
 
}

unsigned char SD_read_sector(unsigned long addr,unsigned char *Buffer,unsigned int Bytes) 

 
 unsigned int a;
 unsigned char retry;
 //Command to read a block;
 char CMD[]={0x51,0x00,0x00,0x00,0x00,0xFF};//cmd17
 //CLI(); //disable all interrupts
 //addr = addr << 9; //addr = addr * 512 
 CMD[1]=((addr&0xFF000000)>>24); 
 CMD[2]=((addr&0x00FF0000)>>16); 
 CMD[3]=((addr&0x0000FF00)>>;
 CMD[4]=(addr&0x000000FF);
  //Send the read command 
  
 while(Write_Command_SD(CMD)!=0) 
      { 
    WDR();//feed the dog
       if (retry++>200) 
          { 
          return 1; 
          } 
       } 
 //Send the start byte 
  while(Read_Byte_SD()!=0xfe) 
  {
  WDR();//feed the dog
  }                                                                            
 //Read off all the bytes in the block 
 for(a=0;a<Bytes;++a) 
 { 
  WDR();//feed the dog
 *Buffer=Read_Byte_SD(); 
 //serial(*Buffer);
 Buffer++;
 }  
 //Read CRC byte 
 Read_Byte_SD(); 
 Read_Byte_SD(); 
  
 // Set SD_Chip_Select to high 
 SD_Disable(); 
 //SEI(); //re-enable interrupts 
 return 0; 
/*
//read xx bytes no matter of misalignment!!
*/
unsigned char read_antimisaliment(unsigned long addr_temp,unsigned char *p_buffer, unsigned int length)
{
  unsigned int _length=0x0000;
  SD_Enable();
  while(SD_read_sector(addr_temp,p_buffer,length))
  {
  SD_Enable();//
  length-=0x0001;//to find a suuitable length to avoid misalignment
  _length+=0x0001;// _length+length==xx
  SD_set_length(length);
  } 
  ///
  if(_length==0x0000)
  {
  return 0;
  }
  ///
  addr_temp+=length;
  SD_Enable();//
  SD_set_length(_length);
  SD_Enable();//
  while(SD_read_sector(addr_temp,p_buffer,_length))
  {
  SD_Enable();
  }
  SD_Enable();//
  SD_set_length(length+_length);//to read the rest bytes of the xx bytes
  return 0;
  /////////////////
 }

将SD卡读写子程序

最新评论:共有 0 位网友发表了评论 查看所有评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
匿名

赞助商链接