⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sd.c

📁 VS1003_MP3_SPI_SDHC_FAT32
💻 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 + -