📄 sd_card.h
字号:
#include "system.h"
#include "altera_avalon_pio_regs.h"
#ifndef __SD_Card_H__
#define __SD_Card_H__
//-------------------------------------------------------------------------
// SD Card Set I/O Direction
#define SD_CMD_IN IOWR(SD_CMD_BASE, 1, 0)
#define SD_CMD_OUT IOWR(SD_CMD_BASE, 1, 1)
#define SD_DAT_IN IOWR(SD_DAT_BASE, 1, 0x0)
#define SD_DAT_OUT IOWR(SD_DAT_BASE, 1, 0x0f)
// SD Card Output High/Low
#define SD_CMD_LOW IOWR(SD_CMD_BASE, 0, 0)
#define SD_CMD_HIGH IOWR(SD_CMD_BASE, 0, 1)
#define SD_DAT_LOW IOWR(SD_DAT_BASE, 0, 0x0)
#define SD_DAT_HIGH IOWR(SD_DAT_BASE, 0, 0x0f)
#define SD_CLK_LOW IOWR(SD_CLK_BASE, 0, 0)
#define SD_CLK_HIGH IOWR(SD_CLK_BASE, 0, 1)
// SD Card Input Read
#define SD_TEST_CMD IORD(SD_CMD_BASE, 0)
#define SD_TEST_DAT IORD(SD_DAT_BASE, 0)
#define SDDAT0 (1<<0)
#define SDDAT1 (1<<1)
#define SDDAT2 (1<<2)
#define SDDAT3 (1<<3)
#define PIOSET(PIN) IOWR_ALTERA_AVALON_PIO_DATA(\
(SD_DAT_BASE),(PIN))//方便修改位置端口
//-------------------------------------------------------------------------
#define BYTE unsigned char
#define UINT16 unsigned int
#define UINT32 unsigned long
//-------------------------------------------------------------------------
void Ncr(void);
void Ncc(void);
BYTE response_R(BYTE);
BYTE send_cmd(BYTE *);
BYTE SD_read_lba(BYTE *,UINT32,UINT32);
BYTE SD_card_init(void);
UINT16 GetCRC16(BYTE *, UINT16);
BYTE exam_crc(void);
//unsigned int BlockCRC16Table(unsigned char *,int);
BYTE statshift(void);
BYTE disconnect(void);
//-------------------------------------------------------------------------
BYTE read_status;
BYTE response_buffer[20];
BYTE RCA[2];
BYTE cmd_buffer[5];
const BYTE cmd0[5] = {0x40,0x00,0x00,0x00,0x00};
const BYTE cmd55[5] = {0x77,0x00,0x00,0x00,0x00};
const BYTE cmd2[5] = {0x42,0x00,0x00,0x00,0x00};
const BYTE cmd3[5] = {0x43,0x00,0x00,0x00,0x00};
const BYTE cmd7[5] = {0x47,0x00,0x00,0x00,0x00};
const BYTE cmd9[5] = {0x49,0x00,0x00,0x00,0x00};
const BYTE cmd16[5] = {0x50,0x00,0x00,0x02,0x00};
const BYTE cmd17[5] = {0x51,0x00,0x00,0x00,0x00};
const BYTE cmd24[5] = {0x58,0x00,0x00,0x00,0x00}; //写命令
const BYTE acmd6[5] = {0x46,0x00,0x00,0x00,0x02};
const BYTE cmd32[5] = {0x60,0x00,0x00,0x00,0x00};//erase block start
const BYTE cmd33[5] = {0x61,0x00,0x00,0x00,0x00};//erase block end
const BYTE cmd38[5] = {0x66,0x00,0x00,0x00,0x00};
const BYTE acmd41[5] = {0x69,0x0f,0xf0,0x00,0x00};
const BYTE acmd42[5] = {0x6a,0x00,0x00,0x00,0x00};
const BYTE acmd51[5] = {0x73,0x00,0x00,0x00,0x00};
/////////////////////////////////////////////////////
void N_busy(void)
{
int i;
SD_CMD_IN;
for(i=0;i<6;i++)
{
SD_CLK_LOW;
SD_CLK_HIGH;
}
}
////////////////////////////////////////////////////////
//-------------------------------------------------------------------------
void Ncr(void)
{
SD_CMD_IN;
SD_CLK_LOW;
SD_CLK_HIGH;
SD_CLK_LOW;
SD_CLK_HIGH;
}
//-------------------------------------------------------------------------
void Ncc(void)
{
int i;
for(i=0;i<8;i++)
{
SD_CLK_LOW;
SD_CLK_HIGH;
}
}
//-------------------------------------------------------------------------
BYTE SD_card_init(void)
{
BYTE x,y;
SD_DAT_OUT;
//PIOSET(SDDAT3);
IOWR(SD_DAT_BASE, 1, 0x8); //设置SD_DAT[3]
IOWR(SD_DAT_BASE, 0, 0x8);
SD_CMD_OUT;
SD_DAT_IN;
SD_CLK_HIGH;
SD_CMD_HIGH;
SD_DAT_LOW;
read_status=0;
for(x=0;x<40;x++)
Ncr();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd0[x];
y = send_cmd(cmd_buffer);
do
{
for(x=0;x<40;x++);
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd55[x];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1) //response too long or crc error
return 1;
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=acmd41[x];
y = send_cmd(cmd_buffer);
Ncr();
} while(response_R(3)==1);
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd2[x];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(2)>1)
return 1;
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd3[x];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(6)>1)
return 1;
RCA[0]=response_buffer[1];
RCA[1]=response_buffer[2];
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd9[x];
cmd_buffer[1] = RCA[0];
cmd_buffer[2] = RCA[1];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(2)>1)
return 1;
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd7[x];
cmd_buffer[1] = RCA[0];
cmd_buffer[2] = RCA[1];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd16[x];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
///////////////////////////////////
for(x=0;x<40;x++); // 1 to 4 line
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd55[x];
cmd_buffer[1] = RCA[0];
cmd_buffer[2] = RCA[1];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=acmd6[x];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
//////////////////////////////////
//sd card ready
for(x=0;x<40;x++); //
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd55[x];
cmd_buffer[1] = RCA[0];
cmd_buffer[2] = RCA[1];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=acmd42[x];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
read_status =1;
return 0;
}
//-------------------------------------------------------------------------
BYTE statshift(void)
{ BYTE x,y;
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd7[x];
cmd_buffer[1] = RCA[0];
cmd_buffer[2] = RCA[1];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd7[x];
cmd_buffer[1] = RCA[0];
cmd_buffer[2] = RCA[1];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
}
BYTE disconnect(void)
{
BYTE x,y;
Ncc();
for(x=0;x<5;x++)
cmd_buffer[x]=cmd7[x];
cmd_buffer[1] = RCA[0];
cmd_buffer[2] = RCA[1];
y = send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
}
////////////////////////
//-------------------------------------------------------------
BYTE SD_EraseBlock(UINT32 startaddr, UINT32 num)
{
BYTE i;
startaddr+=97;
Ncc();
for(i=0;i<5;i++)
cmd_buffer[0]= cmd32[0];
cmd_buffer[1] = (startaddr>>15)&0xff;
cmd_buffer[2] = (startaddr>>7)&0xff;
cmd_buffer[3] = (startaddr<<1)&0xff;
cmd_buffer[4] = 0;
send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
Ncc();
for(i=0;i<5;i++)
cmd_buffer[0]= cmd33[0];
cmd_buffer[1] = ((startaddr+num-1)>>15)&0xff;
cmd_buffer[2] = ((startaddr+num-1)>>7)&0xff;
cmd_buffer[3] = ((startaddr+num-1)<<1)&0xff;
cmd_buffer[4] = 0;
send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
Ncc();
for(i=0;i<5;i++)
cmd_buffer[i]=cmd38[i];
send_cmd(cmd_buffer);
Ncr();
if(response_R(1)>1)
return 1;
while(1)
{
SD_CLK_LOW;
SD_CLK_HIGH;
if((IORD(SD_DAT_BASE, 0)&0x0f)!=0)////////////////////////////////////////
break;
}
}
//-------------------------------------------------------------------------
BYTE SD_read_lba(BYTE *buff,UINT32 lba,UINT32 seccnt)
{
BYTE c=0, x,y;
UINT32 i,j;
lba+=97;
//SD_CMD_OUT;
SD_DAT_IN;
for(j=0;j<seccnt;j++)
{
{
Ncc();
cmd_buffer[0] = cmd17[0];
cmd_buffer[1] = (lba>>15)&0xff;
cmd_buffer[2] = (lba>>7)&0xff;
cmd_buffer[3] = (lba<<1)&0xff;
cmd_buffer[4] = 0;
lba++;
send_cmd(cmd_buffer);
Ncr();
//if(response_R(1)>1)
// return 1;
}
while(1)
{
SD_CLK_LOW;
SD_CLK_HIGH;
if((IORD(SD_DAT_BASE, 0)&0x0f)==0)//检测到起始位值为0
break;
}
for(i=0;i<512;i++)
{
BYTE j;
c=0;
for(j=0;j<2;j++)
{
SD_CLK_LOW;
SD_CLK_HIGH;
c <<= 4;
c |= (IORD(SD_DAT_BASE, 0)&0x0f);
//if(SD_TEST_DAT)
// c |= 0x0f;
//SD_CLK_LOW;
//SD_CLK_HIGH;
}
*buff=c;
buff++;
}
for(i=0; i<16; i++)//16位CRC检验值不接收
{
SD_CLK_LOW;
SD_CLK_HIGH;
}
}
read_status = 1; //SD data next in
return 0;
}
//-------------------------------------------------------------------------
BYTE response_R(BYTE s)
{
BYTE a=0,b=0,c=0,r=0,crc=0;
BYTE i,j=6,k;
while(1)
{
SD_CLK_LOW;
SD_CLK_HIGH;
if(!(SD_TEST_CMD))
break;
if(crc++ >100)
return 2;
}
crc =0;
if(s == 2)
j = 17;
for(k=0; k<j; k++)
{
c = 0;
if(k > 0) //for crc culcar
b = response_buffer[k-1];
for(i=0; i<8; i++)
{
SD_CLK_LOW;
if(a > 0)
c <<= 1;
else
i++;
a++;
SD_CLK_HIGH;
if(SD_TEST_CMD)
c |= 0x01;
if(k > 0)
{
crc <<= 1;
if((crc ^ b) & 0x80)
crc ^= 0x09;
b <<= 1;
crc &= 0x7f;
}
}
if(s==3)
{
if( k==1 &&(!(c&0x80)))
r=1;
}
response_buffer[k] = c;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -