📄 sd.c
字号:
//***************************************************
#include "includes.h"
#include "SD.h"
#define SD_WRITE PORTB
#define SD_READ PINB
#define SD_CLOCK 1
#define SD_DO 2
//***************************************************
//函数名称:SD_SPI_Low()
//函数功能:设置SPI为低速模式
//输入:无
//输出:无
//说明:以Fosc/128 SCK频率运行
//***************************************************
void SD_SPI_Low(void)
{
SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
SPSR&=~(1<<SPI2X);
}
//***************************************************
//函数名称:SD_SPI_High()
//函数功能:设置SPI为高速模式
//输入:无
//输出:无
//说明:以Fosc/2 SCK频率运行
//***************************************************
void SD_SPI_High(void)
{
SPCR=(1<<SPE)|(1<<MSTR);
SPSR|=(1<<SPI2X);
}
//***************************************************
//函数名称:SD_SPI_Init()
//函数功能:SPI端口初始化并置为低速模式
//输入:无
//输出:无
//***************************************************
void SD_SPI_Init(void)
{
SPI_PORT_INIT();
SD_SPI_Low();
}
//***************************************************
//函数名称:SD_Init()
//函数功能:SD端口初始化
//输入:无
//输出:无
//***************************************************
void SD_Init(void)
{
SD_SPI_Init();
SD_Disable();
}
//***************************************************
//函数名称:SD_SPI_WriteByte(unsigned char val)
//函数功能:SPI发送或读取一个字节
//输入:val:将发送的字节
//输出:读取到的一字节
//***************************************************
unsigned char SD_SPI_WriteByte(unsigned char val)
{
SPDR=val;
while(!(SPSR&(1<<SPIF)));
return SPDR;
}
//***************************************************
//函数名称:SD_SendCommand(unsigned char cmd,unsigned long arg)
//函数功能:向SD写入命令
//输入:cmd:命令代码 arg:命令参数
//输出:1字节的响应
//***************************************************
unsigned char SD_SendCommand(unsigned char cmd,unsigned long arg)
{
unsigned char r1;
unsigned char retry=0;
PORTG=0XFF;
SD_SPI_WriteByte(0xff);
SD_Enable();
SD_SPI_WriteByte(cmd|0x40);//分别写入命令
SD_SPI_WriteByte(arg>>24);
SD_SPI_WriteByte(arg>>16);
SD_SPI_WriteByte(arg>>8);
SD_SPI_WriteByte(arg);
SD_SPI_WriteByte(0x95);
while((r1=SD_SPI_WriteByte(0xff))==0xff)//等待响应
if(retry++>0xfe)break;//超时退出
SD_Disable();
SD_SPI_WriteByte(0xff);
PORTG=0X00;
return r1;//返回状态值
}
//***************************************************
//函数名称:SD_Reset()
//函数功能:SD卡的软件复位
//输入:无
//输出:复位结果:0正常复位,1超时退出
//***************************************************
unsigned char SD_Reset(void)
{
unsigned char i;
unsigned char retry;
unsigned char r1=0;
retry=0;
SD_SPI_Low();
do
{
for(i=0;i<10;i++)SD_SPI_WriteByte(0xff);
r1=SD_SendCommand(0,0);//发idle命令
retry++;
if(retry>0xfe)return 1;//超时退出
}while(r1!=0x01);
retry=0;
do
{
r1=SD_SendCommand(1,0);//发active命令
retry++;
if(retry>0xfe)return 1;//超时退出
}while(r1);
SD_SPI_High();
r1=SD_SendCommand(59,0);//关闭CRC功能
r1=SD_SendCommand(16,512);//设扇区大小512
return 0;//正常返回
}
//***************************************************
//函数名称:SD_Read_One_Sector(unsigned long sector)
//函数功能:SD卡单块读操作
//输入:sector:4字节块起始地址 buffer:512字节数据缓冲区首址
//输出:操作结果:0:正常读取 1:超时或1字节的响应
//***************************************************
unsigned char SD_Read_One_Sector(unsigned long sector)
{
unsigned char r1;
unsigned int i;
unsigned int retry=0;
PORTG=0XFF;
r1=SD_SendCommand(17,sector<<9);//读命令
if(r1!=0x00)return r1;
SD_Enable();
while(SD_SPI_WriteByte(0xff)!=0xfe)//等数据的开始
if(retry++>0xfffe){SD_Disable();return 1;}
for(i=0;i<512;i++)//读512个数据
{
Sector_Buffer[i]=SD_SPI_WriteByte(0xff);
}
SD_SPI_WriteByte(0xff);//伪CRC
SD_SPI_WriteByte(0xff);
SD_Disable();
SD_SPI_WriteByte(0xff);//额外8个时钟
PORTG=0X00;
return 0;
}
//***************************************************
//函数名称:SD_Write_One_Sector(unsigned long sector)
//函数功能:SD卡写一扇区数据
//输入:sector:4字节块起始地址
//输出:操作结果:0:正常写入 1:超时或1字节的响应
//说明:写入数据为长度为512字节的Sector_Buffer缓冲区
//***************************************************
unsigned char SD_Write_One_Sector(unsigned long sector)
{
unsigned char r1;
unsigned int i;
unsigned int retry=0;
r1=SD_SendCommand(24,sector<<9);//写命令
if(r1!=0x00)return r1;
SD_Enable();
SD_SPI_WriteByte(0xff);
SD_SPI_WriteByte(0xff);
SD_SPI_WriteByte(0xff);
SD_SPI_WriteByte(0xfe);//发送开始符
for(i=0;i<512;i++)//送512字节数据
{
SD_SPI_WriteByte(Sector_Buffer[i]);
}
SD_SPI_WriteByte(0xff); //虚拟CRC
SD_SPI_WriteByte(0xff);
r1=SD_SPI_WriteByte(0xff);
if((r1&0x1f)!=0x05)//等待是否成功
{
SD_Disable();
return r1;
}
while(!SD_SPI_WriteByte(0xff))//等待操作完成
if(retry++>0xfffe){SD_Disable();return 1;}
SD_Disable();
SD_SPI_WriteByte(0xff);//额外8个时钟
return 0;
}
//***************************************************
//函数名称:SD_Read_Capacity(void)
//函数功能:获取SD的总容量
//输入:无
//输出:4字节容量
//说明://memorycapacity=BLOCKNR*BLOCK_LEN
// BLOCKNR=(C_SIZE+1)*MULT
// MULT = 2^(C_SIZE_MULT+2)
// BLOCK_LEN = 2^READ_BL_LEN
//***************************************************
unsigned long SD_Read_Capacity(void)
{
unsigned char r1;
unsigned int i;
unsigned int temp;
unsigned char buffer[16];
unsigned long Capacity;
unsigned int retry=0;
r1=SD_SendCommand(9,0);//写命令
if(r1!=0x00)return r1;
SD_Enable();
while(SD_SPI_WriteByte(0xff)!=0xfe)
if(retry++>0xfffe){SD_Disable();return 1;}
for(i=0;i<16;i++)
{
buffer[i]=SD_SPI_WriteByte(0xff);
}
SD_SPI_WriteByte(0xff);
SD_SPI_WriteByte(0xff);
SD_SPI_WriteByte(0xff);
SD_Disable();
SD_SPI_WriteByte(0xff);//额外8个时钟
//*********************************
//获取C_SIZE
i=buffer[6]&0x03;
i<<=8;
i+=buffer[7];
i<<=2;
i+=((buffer[8]&0xc0)>>6);
//**********************************
//获取C_SIZE_MULT
r1=buffer[9]&0x03;
r1<<=1;
r1+=((buffer[10]&0x80)>>7);
//**********************************
//获取BLOCKNR
r1+=2;
temp=1;
while(r1)
{
temp*=2;
r1--;
}
Capacity=((unsigned long)(i+1))*((unsigned long)temp);
//**********************************
//获取READ_BL_LEN
i=buffer[5]&0x0f;
//*************************
//获取BLOCK_LEN
temp=1;
while(i)
{
temp*=2;
i--;
}
//************************
//最终结果
Capacity*=(unsigned long)temp;
return Capacity;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -