|
楼主 |
发表于 2006-7-20 09:59:29
|
显示全部楼层
好东西就要给大家分享!
//ICC-AVR application builder : 2005-11-12 17:11:59
// Target : M16
// Crystal: 8.0000Mhz
// copyright:endylu
#include <iom16v.h>
#include <macros.h>
#include "main.h"
//=======================================================================
uint8 Read_Byte_SD(void)
{
//char Byte;
SPDR=0xff;
while(!(SPSR&(1<<SPIF)));
//Byte=SPDR;
return(SPDR);
}
//=======================================================================
void Write_Byte_SD(uint8 Byte)
{
SPDR=Byte;
while(!(SPSR&(1<<SPIF)));
}
//=======================================================================
uint8 Write_Command_SD1(uint8*CMD)
{
uint8 a;
uint8 tmp=0xff;
uint8 Timeout=0;
// Raise chip select
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 10here
return(tmp);
}
//=======================================================================
uint8 Write_Command_SD(uint8 CMD,uint32 address)
{
uint8 tmp;
uint8 Timeout=0;
// Lower chip select
SD_Enable();
//Send the 6 byte command
Write_Byte_SD(CMD);
Write_Byte_SD(address>>24);
Write_Byte_SD(address>>16);
Write_Byte_SD(address>>8);
Write_Byte_SD(address);
Write_Byte_SD(0xff);
//Wait for the response
tmp=Read_Byte_SD();
while((tmp==0xff)&(Timeout++<8))
{
tmp=Read_Byte_SD();
}
return(tmp);
}
//=======================================================================
uint8 SDInit(void)
{
uint8 a,b,retry;
uint8 CMD[]={0x40,0x00,0x00,0x00,0x00,0x95};
asm("cli"); //clear all interrupt.
// Set certain pins to inputs and others to outputs
// Only SPI_DI (data in) is an input
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_Write|=(1<<SD_Chip_Select);
//We need to wait for the SD_Direction_REG to be ready
for(a=0;a<200;a++)
{
nop();
};
//Enable SPI in Master Mode with IDLE low and clock at 8M/128
SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);
SPSR&=~(1<<SPI2X);
// We need to give the card about a Hundred cycles to load
for (b=0;b<0x0f;++b)
{
Write_Byte_SD(0xff);
}
//Send the initialization commands to the card
retry=0;
while(Write_Command_SD1(CMD)!=0X01)
{
Delay_ms(10); //很重要,要不然就要REST才可以
//fail and return
if(retry++>50)
{
return 1;
}
}
//Send the 2nd command
retry=0;
CMD[0]=0x41;
CMD[5]=0xFF;
while(Write_Command_SD1(CMD)!=0)
{
Delay_ms(10);
if (retry++>50)
{
return 2;
}
}
//Set the SPI bus to full speed 8M/2
SPCR&=~((1<<SPR0)|(1<<SPR1));
SPSR|=(1<<SPI2X);
//Raise Chip Select
SD_Disable();
asm("sei");
return 0;
}
//=======================================================================
uint8 SD_set_length(uint16 length)
{uint8 retry;
//Command to set the block length;
while(Write_Command_SD(0x50,length)!=0)
{
if (retry++>10)
{
return 1;
}
}
SD_Disable();
return 0;
}
//=======================================================================
uint8 SD_read_sector(uint32 addr,uint8*Buffer)
{
uint16 a;
uint8 retry=0;
// Send the read command
while(Write_Command_SD(0x51,addr<<9)!=0)
{
if (retry++>10)
{
return 1;
}
}
//receive the start byte
while(Read_Byte_SD()!=0xfe);
//Read off all the bytes in the block
for(a=0;a<512;a++)
{
*Buffer++=Read_Byte_SD();
}
//Read CRC byte
Read_Byte_SD();
Read_Byte_SD();
// Set SD_Chip_Select to high
SD_Disable();
return 0;
}
//=======================================================================
uint8 SD_start_read(uint32 addr)
{
uint8 retry;
// Send the read command
while(Write_Command_SD(0x51,addr<<9)!=0)
{
if (retry++>10)
{
return 1;
}
}
//Send the start byte
while(Read_Byte_SD()!=0xfe);
SD_Disable();
return 0; //open successfully!
}
//=======================================================================
void SD_get_date(uint8 *Buffer,uint16 Number)
{
uint16 a;
SD_Enable();
for(a=0;a<Number;a++)
{
*Buffer++=Read_Byte_SD();
}
SD_Disable(); // Set SD_Chip_Select to high
}
//=======================================================================
uint8 SD_read_sector2(uint32 addr,uint8*Buffer,uint16 Bytes)
{
uint16 a;
uint8 retry=0;
// Send the read command
while(Write_Command_SD(0x51,addr)!=0)
{
if (retry++>10)
{
return 1;
}
}
//receive the start byte
while(Read_Byte_SD()!=0xfe);
//Read off all the bytes in the block
for(a=0;a<Bytes;a++)
{
*Buffer++=Read_Byte_SD();
}
//Read CRC byte
Read_Byte_SD();
Read_Byte_SD();
// Set SD_Chip_Select to high
SD_Disable();
return 0;
}
//=======================================================================
//Routine for writing a Block(512Byte) to MMC/SD-Card
//Return 0 if sector writing is completed.
unsigned char SD_write_sector(unsigned long addr,unsigned char *Buffer)
{
unsigned char tmp,retry;
unsigned int i;
#asm("cli"); //clear all interrupt.
//Command 24 is a writing blocks command for MMC/SD-Card.
while(Write_Command_SD(0x58,addr)!=0)
{
if (retry++>10)
{
return 1;
}
}
//Before writing,send 100 clock to MMC/SD-Card
for (i=0;i<100;i++)
{
Read_Byte_SD();
}
//Send Start Byte to MMC/SD-Card
Write_Byte_SD(0xFE);
//Now send real data Bolck (512Bytes) to MMC/SD-Card
for (i=0;i<512;i++)
{
Write_Byte_SD(*Buffer++); //send 512 bytes to Card
}
//CRC-Byte
Write_Byte_SD(0xFF); //Dummy CRC
Write_Byte_SD(0xFF); //CRC Code
tmp=Read_Byte_SD(); // read response
if((tmp & 0x1F)!=0x05) // data block accepted ?
{
SD_Disable();
return 1; //Error!
}
//Wait till MMC/SD-Card is not busy
while (Read_Byte_SD()!=0xff){};
//set MMC_Chip_Select to high (MMC/SD-Card Invalid)
SD_Disable();
return 0;
} |
|