📄 sd.c
字号:
#define IN_SD
#include "User.h"
INT8U sectorBuffer_data[16];
typedef struct
{
INT8U Drive; // 驱动器号
INT16U Len; //长度
INT32U SectorIndex; // 操作的扇区
INT8U *Buf; // 数据存储位置
} Disk_RW_Parameter;
void MSPI_Init(INT8U mode)
{
INT8U CPSDVSR,SCR;
INT16U temp;
if(mode == 0)
{
IO0DIR |= SD_Chip_Select;
PINSEL1 = (PINSEL1 & 0xFFFFF303) | 0xA8;
temp = Fpclk/100000; // CLOCK<=100K
SCR = temp / 255;
CPSDVSR = temp / (SCR + 1);
if(CPSDVSR % 2)
{
CPSDVSR += 1;
}
SSPCR0 = (SCR << 8) | // SPI 时钟设置
(0x00 << 7) | // CPHA = 0,
(0x00 << 6) | // CPOL = 0,
(0x00 << 4) | // FRF 帧格式=SPI,
(0x07 << 0); // DDS 数据长度 = 8,
SSPCR1 = (0x00 << 3) | // SOD 从机输出禁能
(0x00 << 2) | // MS 主从选择 = 0,
(0x01 << 1) | // SSE SSP 使能允许与其它设备通信
(0x00 << 0) ; // LBM 回写模式,
SSPCPSR = CPSDVSR; //SSP 时钟预分频(PCLK/16)
SSPICR = 0x03; //中断清除寄存器
}
else if(mode == 1)
{
temp = Fpclk/10000000; // CLOCK<=10M
SCR = temp / 255;
CPSDVSR = temp / (SCR + 1);
if(CPSDVSR % 2)
{
CPSDVSR += 1;
}
SSPCR0 &= 0x00FF | (SCR << 8);
SSPCPSR = CPSDVSR;
SSPICR = 0x03; //中断清除寄存器
}
}
INT8U SPI_RW(INT8U data)
{
SSPDR = data;
while((SSPSR & 0x01) == 0); //等待SPI将数据发送完毕
return(SSPDR);
}
INT8U Write_Command_SD(INT8U *CMD)
{
INT8U i = 0, tmep = 0, retry = 0;
SD_Disable();
SPI_RW(0xff); //发送8个时钟
SD_Enable();
//发送6比特的命令到SD/SD卡
CMD[0] = (CMD[0] & 0x3f) | 0x40;
for(i = 0; i < 0x06; i++)
{
SPI_RW(*CMD++);
}
//获得16比特的响应
SPI_RW(0xff); //读取并放弃第一个比特,只有最后一个比特是需要的.
do
{
tmep = SPI_RW(0xff);
retry++;
}
while((tmep == 0xff) && (retry < 100));
return(tmep);
}
INT8U SD_Init(void)
{
INT8U retry, temp;
INT8U i = 0;
INT8U CMD[] = {CMD0, 0x00, 0x00, 0x00, 0x00, 0x95};
MSPI_Init(0);
SD_Enable();
for(i=0;i<250;i++)
__asm
{
NOP
}
for(i = 0; i < 0x0f; i++)
{
SPI_RW(0xff); //发送至少74个时钟
}
//Send Command CMD0 to SD/SD Card
retry = 0;
do
{ //retry 200 times to send CMD0 command
temp = Write_Command_SD(CMD);
retry++;
if(retry >= 200)
{ //time out
return(INIT_CMD0_ERROR); //CMD0 Error!
}
}
while(temp != 1);
//Send Command CMD1 to SD/SD-Card
CMD[0] = CMD1; //Command 1
CMD[5] = 0xFF;
retry = 0;
do
{ //retry 100 times to send CMD1 command
temp=Write_Command_SD(CMD);
retry++;
if(retry>=100)
{ //time out
return(INIT_CMD1_ERROR);//CMD1 Error!
}
}
while(temp != 0);
MSPI_Init(1);
SD_Disable();
return(0);
}
void SD_get_volume_info(VOLUME_INFO_TYPE* vinf)
{
// read the CSD register
Read_CSD_SD(sectorBuffer_data);
vinf->sector_count = sectorBuffer_data[6] & 0x03;
vinf->sector_count <<= 8;
vinf->sector_count += sectorBuffer_data[7];
vinf->sector_count <<= 2;
vinf->sector_count += (sectorBuffer_data[8] & 0xc0) >> 6;
vinf->sector_multiply = sectorBuffer_data[9] & 0x03;
vinf->sector_multiply <<= 1;
vinf->sector_multiply += (sectorBuffer_data[10] & 0x80) >> 7;
vinf->size_MB = vinf->sector_count >> (9-vinf->sector_multiply);
// get the name of the card
Read_CID_SD(sectorBuffer_data);
vinf->name[0] = sectorBuffer_data[3];
vinf->name[1] = sectorBuffer_data[4];
vinf->name[2] = sectorBuffer_data[5];
vinf->name[3] = sectorBuffer_data[6];
vinf->name[4] = sectorBuffer_data[7];
vinf->name[5] = 0x00;
}
INT8U SD_write_sector(INT32U Number_Sector, INT8U* Buffer)
{
INT8U tmp,retry;
INT16U i;
//Command 24 is a writing blocks command for SD/SD-Card.
INT8U CMD[] = {0x58, 0x00, 0x00, 0x00, 0x00, 0xFF};
//asm("cli"); //clear all interrupt.
Number_Sector <<= 9; //addr = addr * 512
CMD[1] = ((Number_Sector & 0xFF000000) >> 24 );
CMD[2] = ((Number_Sector & 0x00FF0000) >> 16 );
CMD[3] = ((Number_Sector & 0x0000FF00) >> 8 );
//CMD[4] = (INT8U)((Number_Sector & 0x000000FF) >> 0 );
//Send Command CMD24 to SD/SD-Card (Write 1 Block/512 Bytes)
retry = 0;
do
{ //Retry 100 times to send command.
tmp = Write_Command_SD(CMD);
if(++retry >= 100)
{
return(tmp); //send commamd Error!
}
}
while(tmp != 0);
//发送至少100个时钟到SD/SD卡
for(i = 0; i < 100; i++)
SPI_RW(0xff);
//Send Start Byte to SD/SD-Card
SPI_RW(0xFE);
//Now send real data Bolck (512Bytes) to SD/SD-Card
for(i = 0; i < 512; i++)
SPI_RW(*Buffer++); //send 512 bytes to Card
//CRC-Byte
SPI_RW(0xFF); //Dummy CRC
SPI_RW(0xFF); //CRC Code
tmp = SPI_RW(0xff); // read response
if((tmp & 0x1F) != 0x05)
{// data block accepted ?
SD_Disable();
return(WRITE_BLOCK_ERROR); //Error!
}
//Wait till SD/SD-Card is not busy
while(SPI_RW(0xff) != 0xff);
//set SD_Chip_Select to high (SD/SD-Card Invalid)
SD_Disable();
return(0);
}
INT8U SD_Read_Block(INT8U *CMD, INT8U *Buffer, INT16U Bytes)
{
INT16U i;
INT8U retry,temp;
static INT16U Block_Len;
INT8U CMD_SET_BLOCKLEN[]={CMD16,0x00,0x00,0x00,0x00,0xFF};
//INT8U CMD_Read_Block[]={CMD17,0x00,0x00,0x00,0x00,0xFF};
if(Bytes != Block_Len)
{ //Reset Block Length
CMD_SET_BLOCKLEN[3] = (INT8U)((Bytes & 0x0000FF00) >> 8 );
CMD_SET_BLOCKLEN[4] = (INT8U)((Bytes & 0x000000FF) >> 0 );
retry = 0;
do
{ //Retry 100 times to send command.
temp = Write_Command_SD(CMD_SET_BLOCKLEN);
if(++retry >= 100)
return(READ_BLOCK_ERROR); //block read Error!
}
while(temp != 0);
Block_Len = Bytes;
}
//Send reads a block Command CMD to SD/SD-Card
retry = 0;
/*if(CMD == (void *)0)
CMD = CMD_Read_Block;*/
do
{ //Retry 100 times to send command.
temp = Write_Command_SD(CMD);
if(++retry >= 100)
return(READ_BLOCK_ERROR); //block read Error!
}
while(temp != 0);
//Read Start Byte form SD/SD-Card (FEh/Start Byte)
while(SPI_RW(0xff) != 0xfe);
//Write blocks(normal 512Bytes) to SD/SD-Card
for(i = 0; i < Bytes; i++)
*Buffer++ = SPI_RW(0xff);
//CRC-Byte
SPI_RW(0xff);//CRC - Byte
SPI_RW(0xff);//CRC - Byte
SD_Disable();
return(0);
}
INT8U SD_read_sector(INT32U Number_Sector,INT8U *Buffer)
{
//Command 17 is reading Blocks from SD/SD-Card
INT8U CMD_Read_Block[]={CMD17,0x00,0x00,0x00,0x00,0xFF};
INT8U temp;
//Address conversation(logic block address-->byte address)
Number_Sector <<= 9; //addr = addr * 512
CMD_Read_Block[1] = (INT8U)((Number_Sector & 0xFF000000) >> 24 );
CMD_Read_Block[2] = (INT8U)((Number_Sector & 0x00FF0000) >> 16 );
CMD_Read_Block[3] = (INT8U)((Number_Sector & 0x0000FF00) >> 8 );
temp = SD_Read_Block(CMD_Read_Block, Buffer, 512);
return(temp);
}
INT8U Read_CID_SD(INT8U *Buffer)
{
//Command for reading CID Registers
INT8U CMD[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
INT8U temp;
temp = SD_Read_Block(CMD, Buffer, 16); //read 16 bytes
return(temp);
}
INT8U Read_CSD_SD(INT8U *Buffer)
{
//Command for reading CSD Registers
INT8U CMD[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
INT8U temp;
temp = SD_Read_Block(CMD, Buffer, 16); //read 16 bytes
return(temp);
}
INT8U SDKardCMD(INT8U Cammand, void *Parameter)
{
INT8U CMD_Read_Block[]={CMD17,0x00,0x00,0x00,0x00,0xFF};
Disk_RW_Parameter *pDP;
pDP = (Disk_RW_Parameter *)Parameter;
switch(Cammand)
{
case ReadSec:
SD_read_sector(pDP->SectorIndex,pDP->Buf);
break;
case ReadBlock:
CMD_Read_Block[1] = (INT8U)((pDP->SectorIndex & 0xFF000000) >> 24 );
CMD_Read_Block[2] = (INT8U)((pDP->SectorIndex & 0x00FF0000) >> 16 );
CMD_Read_Block[3] = (INT8U)((pDP->SectorIndex & 0x0000FF00) >> 8 );
CMD_Read_Block[4] = (INT8U)((pDP->SectorIndex & 0x000000FF) >> 0 );
SD_Read_Block(CMD_Read_Block, pDP->Buf, pDP->Len);
break;
case WriteSec:
SD_write_sector(pDP->SectorIndex, pDP->Buf);
break;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -