************************************************************/
#ifndef _SD_INCLUDED_
#define _SD_INCLUDED_
#include <util/delay.h>
//正点原子@scut 08/09/11
//很多部分参考网友(波仔)的
#include "myspi.h"
#define SD_CS_H SET_BIT(PORTB,0)
#define SD_CS_L CLR_BIT(PORTB,0)
unsigned char BUFFER[512]; //扇区缓冲区
unsigned char reading=0; //标记读写,1:读
void spi_init(void); //初始化spi
unsigned char SD_Write_Command(unsigned char cmd,unsigned long arg);//写命令到sd卡
void sd_port_init(void);//初始化sd卡的io
unsigned char SD_Init(void); //sd卡初始化
unsigned char SD_Read_Block(unsigned long address); //读取一个块数据
#define sd_port_init() {SD_CS_H;}
//****************************************************************************
//Send a Command to MMC/SD-Card
//Return: the second byte of response register of MMC/SD-Card
//****************************************************************************
unsigned char SD_Write_Command(unsigned char cmd,unsigned long arg)
{
unsigned char tmp;
unsigned char retry=0;
SD_CS_H; //SD卡关闭
//send 8 Clock Impulse
Write_Byte_SPI(0xFF);
SD_CS_L; //SD卡使能
Write_Byte_SPI(cmd|0x40); //送头命令
Write_Byte_SPI(arg>>24);
Write_Byte_SPI(arg>>16); //send 6 Byte Command to MMC/SD-Card
Write_Byte_SPI(arg>>8);
Write_Byte_SPI(arg&0xff);
Write_Byte_SPI(0x95); //仅仅对RESET有效的CRC效验码
//get 8 bit response
do //Read_Byte_MMC(); //read the first byte,ignore it.
{
tmp = Read_Byte_SPI(); //Only last 8 bit is used here.Read it out.
retry++;
}
while((tmp==0xff)&&(retry<100)); //当没有收到有效的命令的时候
if(reading==0)SD_CS_H;//MMC_CS_PIN=1;
else SD_CS_L; //MMC_CS_PIN=0;
return(tmp);
}
//****************************************************************************
//SD卡初始化(SPI-MODE)
//****************************************************************************
unsigned char SD_Init(void)
{
unsigned char retry,temp;
unsigned char i;
SD_CS_L; //SD卡使能
_delay_us(250); //Wait MMC/SD ready...等待MMC/SD卡准备就绪
for (i=0;i<0x0f;i++)
{
Write_Byte_SPI(0xff); //send 74 clock at least!!!
}
retry=0;
do//Send Command CMD0 to MMC/SD Card
{
temp=SD_Write_Command(0,0);//retry 200 times to send CMD0 command
retry++;
if(retry==100)return 0xff;//CMD0 Error!
}
while(temp!=1);
retry=0;
do//Send Command CMD1 to MMC/SD-Card
{
temp=SD_Write_Command(1,0);//retry 100 times to send CMD1 command
retry++;
if(retry==100);
}while(temp!=0);
retry=0;
SD_Write_Command(16,512); //设置一次读写BLOCK的长度为512个字节
SD_CS_H; //MMC_CS_PIN=1; //set MMC_Chip_Select to high 设置到高位
return(0); //All commands have been taken.
}
//****************************************************************************
//从SD卡读一个扇区 Return 0 if no Error.
//address:所在的物理扇区编号
//返回值:!0xff
//****************************************************************************
unsigned char SD_Read_Block(unsigned long address)
{
unsigned char temp=0;
unsigned int i=0;
reading=1;
temp=SD_Write_Command(17,address); //读出RESPONSE
while(Read_Byte_SPI()!= 0xfe)SET_BIT(PORTA,1);//直到读取到了数据的开始头0XFE,才继续
CLR_BIT(PORTA,1);
for(i=0; i<512; i++)
{
BUFFER[i]=Read_Byte_SPI();
}
Read_Byte_SPI();//CRC - Byte
Read_Byte_SPI();//CRC - Byte
reading=0;
SD_CS_H;; //关闭SD卡
return(temp);
}
//****************************************************************************
//从SD卡读一个扇区 Return 0 if no Error.
//****************************************************************************
unsigned char SD_Read_Block2(unsigned long address,unsigned char *buf)
{
unsigned char temp=0;unsigned int i=0;
reading=1;
temp=SD_Write_Command(17,address); //读出RESPONSE
while (Read_Byte_SPI()!= 0xfe);//直到读取到了数据的开始头0XFE,才继续
for(i=0; i<512; i++)
{
buf[i]=Read_Byte_SPI();
}
Read_Byte_SPI();//CRC - Byte
Read_Byte_SPI();//CRC - Byte
reading=0;
SD_CS_H; //关闭SD卡
return(temp);
}
//从指定位置读取一个字
unsigned int SD_Read_Word(unsigned long address,unsigned int offset)
{
unsigned char temp=0;unsigned int i=0;
unsigned char k=0;
unsigned char buf[2];
reading=1;
temp=SD_Write_Command(17,address<<9); //读出RESPONSE
while (Read_Byte_SPI()!= 0xfe);//直到读取到了数据的开始头0XFE,才继续
for(i=0;i<offset;i++)Read_Byte_SPI();
for(;i<offset+2;i++)buf[k++]=Read_Byte_SPI();
for(;i<512;i++)Read_Byte_SPI();
Read_Byte_SPI();
Read_Byte_SPI();
reading=0;
SD_CS_H; //关闭SD卡
return (*((unsigned int*) &((char*)buf)[0])) ;
}
//连续读取指定扇区offset偏移位置,bytes个数据
void SD_Read_Bytes(unsigned long address,unsigned char *buf,unsigned int offset,unsigned int bytes)
{
unsigned char temp=0;unsigned int i=0;
reading=1;
temp=SD_Write_Command(17,address<<9); //读出RESPONSE
while (Read_Byte_SPI()!= 0xfe);//直到读取到了数据的开始头0XFE,才继续
for(i=0;i<offset;i++) Read_Byte_SPI();
for(;i<offset+bytes;i++) *buf++=Read_Byte_SPI();
for(;i<512;i++) Read_Byte_SPI();
Read_Byte_SPI();
Read_Byte_SPI();
reading=0;
SD_CS_H; //关闭SD卡
}
#endif
(正点原子) |