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

📄 atmega8l sdcard.txt

📁 atmega8L最小系统读写SD卡的程序。
💻 TXT
字号:
硬件平台: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)>>8);// 
 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)>>8); 
 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)>>8); 
 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;
  /////////////////
 } 

⌨️ 快捷键说明

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