?? sd.c
字號:
#include "sd.h"
extern SPI_InitTypeDef SPI_InitStructure;
void FCLK_SLOW() /*set SPI clk <= 400kHz*/
{
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_Init (SPI1, &SPI_InitStructure) ;
}
void FCLK_FAST() /*set SPI clk fast*/
{
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_Init (SPI1, &SPI_InitStructure) ;
}
void SPI_transmit_m(uint8_t ch)
{
while((SPI1->SR &SPI_I2S_FLAG_TXE)==RESET);
SPI_I2S_SendData(SPI1,ch);
while((SPI1->SR &SPI_I2S_FLAG_RXNE)==RESET);
SPI_I2S_ReceiveData(SPI1);
}
void SPI_receive_m(uint8_t *ch)
{
while((SPI1->SR &SPI_I2S_FLAG_TXE)==RESET);
SPI_I2S_SendData(SPI1,0xff);
while((SPI1->SR &SPI_I2S_FLAG_RXNE)==RESET);
*ch = SPI_I2S_ReceiveData(SPI1);
}
uint8_t SD_sendCommand(uint8_t cmd, uint32_t arg)
{
uint8_t response = 0xff;
uint8_t retry = 0;
SD_CS_ASSERT;
SPI_transmit_m(cmd); /*send command, first two bits always '01'*****/
SPI_transmit_m(arg>>24);
SPI_transmit_m(arg>>16);
SPI_transmit_m(arg>>8);
SPI_transmit_m(arg);
if(cmd == CMD0)
SPI_transmit_m(0x95); /*CRC, it must be 0x95 when cmd0*/
else if(cmd == CMD8)
SPI_transmit_m(0x87);
else
SPI_transmit_m(0xff);
do/*wait response*/
{
SPI_receive_m(&response); /*equal to "response = SPI_receive();"*/
if(retry++ > 0xfe) break; /*time out*/
}while(response == 0xff);
SD_CS_DEASSERT;
SPI_transmit_m(0xff); //delay 8 clock
return response;
}
uint8_t SD_init(void)
{
uint8_t response = 0xff;
uint8_t retry = 0;
uint8_t i = 0;
FCLK_SLOW(); /*set SPI clk <= 400kHz*/
SD_CS_DEASSERT;
for(i=0;i<10;i++)
SPI_transmit_m(0xff); /*74 clk*/
retry = 0;
do
{
response = SD_sendCommand(CMD0, 0); /*send 'reset & go idle' command, the response should be 0x01 if successfull*/
retry++;
if(retry > 0xfe)
return 1; /*time out*/
}while(response != 0x01);
retry = 0;
do
{
response = SD_sendCommand(CMD8, 0x1aa); /* 判斷 SDHC */
retry++;
if(retry > 0xfe)
return 1; /*time out*/
}while(response != 0x01);
retry = 0;
do
{
response = SD_sendCommand(CMD55, 0); /*activate card's initialization process, the response should be 0x00 if successfull*/
response = SD_sendCommand(0x40+41, 0x40000000);
retry++;
if(retry > 0xfe)
return 1; /*time out*/
}while(response);
SD_sendCommand(CMD16, 512); /*set block size to 512*/
FCLK_FAST(); /*set SPI clk fast*/
return 0; /*normal return*/
}
uint8_t transmit_DataBlock(
const uint8_t *buff, /* 512 byte data block to be transmitted */
uint8_t token /* Data/Stop token */
)
{
uint8_t response = 0xff;
uint8_t bc = 0;
uint32_t retry = 0;
SD_CS_ASSERT;
SPI_transmit_m(token); /*send start block token 0xfe (0x11111110)*/
do /*transmit the 512 byte data block to SD card*/
{
SPI_transmit_m(*buff++);
SPI_transmit_m(*buff++);
}while (--bc);
SPI_transmit_m(0xff); /*CRC (Dummy)*/
SPI_transmit_m(0xff);
SPI_receive_m(&response);
if( (response & 0x1f) != 0x05) /*response= 0bXXX0AAA1 ; AAA='010' - data accepted*/
{ /*AAA='101'-data rejected due to CRC error*/
SD_CS_DEASSERT; /*AAA='110'-data rejected due to write error*/
return 1;
}
SPI_receive_m(&response);
while(response != 0xff) //wait until the SD is not busy
{
SPI_receive_m(&response);
if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;}
}
SD_CS_DEASSERT;
SPI_transmit_m(0xff); /*extra 8 clk*/
return 0;
}
uint8_t receive_DataBlock(
uint8_t *buff, /* Data buffer to store received data */
uint32_t btr /* Byte count (must be multiple of 4) */
)
{
uint8_t response = 0xff;
uint32_t retry = 0;
SD_CS_ASSERT;
do /*wait for start block token 0xfe (0x11111110)*/
{
SPI_receive_m(&response);
if(retry++ > 0xfffe) /*time out error*/
{
SD_CS_DEASSERT;
return 1;
}
}while(response != 0xfe); /*wait response*/
do /*Receive the data block into buffer*/
{
SPI_receive_m(buff++);
SPI_receive_m(buff++);
SPI_receive_m(buff++);
SPI_receive_m(buff++);
}while(btr -= 4);
SPI_receive_m(&response); /*Discard CRC two bytes*/
SPI_receive_m(&response);
SD_CS_DEASSERT;
SPI_transmit_m(0xff); /*extra 8 clk*/
return 0;
}
uint8_t SD_writeSingleBlock(const uint8_t *buff, uint32_t startBlock)
{
if(SD_sendCommand(CMD24, startBlock)) return 1; //SDHC //startBlock * 512 字節
if(transmit_DataBlock(buff, 0xfe)) return 1;
return 0;
}
uint8_t SD_readSingleBlock(uint8_t *buff, uint32_t startBlock)
{
if(SD_sendCommand(CMD17, startBlock)) return 1; //SDHC //startBlock 字節
if(receive_DataBlock(buff, 512)) return 1;
return 0;
}
uint8_t SD_writeMultipleBlock(const uint8_t *buff, uint32_t startBlock, uint32_t totalBlocks)
{
uint8_t response = 0xff; /*response from sd card*/
uint8_t bc = 0;
uint32_t retry = 0;
if(SD_sendCommand(CMD25, startBlock)) return 1;
SD_CS_ASSERT;
do
{
SPI_transmit_m(0xfc); /*Send start block token 0xfc (0x11111100)*/
do /*ransmit the 512 byte data block to SDC*/
{
SPI_transmit_m(*buff++);
SPI_transmit_m(*buff++);
} while (--bc);
SPI_transmit_m(0xFF); /* CRC (Dummy) */
SPI_transmit_m(0xFF);
SPI_receive_m(&response);
if( (response & 0x1f) != 0x05) /*response= 0bXXX0AAA1 ; AAA='010' - data accepted*/
{ /*AAA='101'-data rejected due to CRC error*/
SD_CS_DEASSERT; /*AAA='110'-data rejected due to write error*/
return 1;
}
retry = 0;
SPI_receive_m(&response);
while(response != 0xff) /*wait for SD card to complete writing and get idle*/
{
SPI_receive_m(&response);
if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;}
}
SPI_transmit_m(0xff); /*extra 8 bits*/
}while (--totalBlocks);
SPI_transmit_m(0xfd); /*send 'stop transmission token'**/
retry = 0;
SPI_receive_m(&response);
while(response != 0xff) //wait for SD card to complete writing and get idle
{
SPI_receive_m(&response);
if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;}
}
SD_CS_DEASSERT;
SPI_transmit_m(0xff);
return 0;
}
uint8_t SD_readMultipleBlock(uint8_t *buff, uint32_t startBlock, uint32_t totalBlocks)
{
uint8_t response = 0xff;
uint32_t retry = 0;
uint32_t nbyte = 512;
if(SD_sendCommand(CMD18, startBlock)) return 1;
SD_CS_ASSERT;
do
{
do /*wait for start block token 0xfe (0x11111110)*/
{
SPI_receive_m(&response);
if(retry++ > 0xfffe) /*time out error*/
{
SD_CS_DEASSERT;
return 1;
}
}while(response != 0xfe); /*wait response*/
do /*Receive the data block into buffer*/
{
SPI_receive_m(buff++);
SPI_receive_m(buff++);
SPI_receive_m(buff++);
SPI_receive_m(buff++);
}while (nbyte -= 4);
SPI_receive_m(&response); /*Discard CRC*/
SPI_receive_m(&response);
nbyte = 512;
retry = 0;
}while (--totalBlocks);
SD_sendCommand(CMD12, 0); /*STOP_TRANSMISSION*/
SD_CS_DEASSERT;
SPI_transmit_m(0xff); /*extra 8 clk*/
return 0;
}
uint8_t SD_erase(uint32_t startBlock, uint32_t totalBlocks)
{
uint8_t response;
response = SD_sendCommand(CMD32, startBlock); /*send starting block address*/
if(response != 0x00) /*check for SD status: 0x00 is OK*/
return response;
response = SD_sendCommand(CMD33,(startBlock + totalBlocks - 1)); /*send end block address*/
if(response != 0x00)
return response;
response = SD_sendCommand(CMD38, 0); /*erase all selected blocks*/
if(response != 0x00)
return response;
return 0; /*normal return*/
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -