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

📄 spi_msd_driver.c

📁 STM32_fatfs_shell_SDHC.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
/**
  ******************************************************************************
  * @file    SDFatFS/source/SPI_SD_Driver.c 
  * @author  deliang_zhu
  * @version V1.0.0
  * @date    25/12/2009
  * @brief   
  ******************************************************************************
  * @copy
  *
  */

/* Includes ------------------------------------------------------------------*/
//#include "stm32f10x_lib.h"
#include "config.h"

#define PRINT_INFO TRUE



/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
MSD_CARDINFO CardInfo;




/*******************************************************************************
* Function Name  : MSD_SPIConfig
* Description    : 
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void MSD_SPIConfig(void)
{		
	GPIO_InitTypeDef GPIO_InitStructure;

 	// Enable SPI1 clock
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    //SPI1模块对应的SCK、MISO、MOSI为AF引脚
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//PB6 pin: SD_CS 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);  
	//_card_power_off();
	_card_disable(); 


	// SPI1 low speed mode
	MSD_SPIHighSpeed(0);		

	// Enable SPI1
	SPI_Cmd(SPI1, ENABLE);

/*
		GPIO_InitTypeDef GPIO_InitStructure;

 	// Enable SPI1 clock
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

	// SPI1 -> SD
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// PD9 pin: CS, PD10 : SD power on
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOD, &GPIO_InitStructure); 
	_card_power_off();
	_card_disable(); 

	//PA2: SD detect
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_Init(GPIOA, &GPIO_InitStructure); 	

	// SPI1 low speed mode
	MSD_SPIHighSpeed(0);		

	// Enable SPI1
	SPI_Cmd(SPI1, ENABLE);
	*/
}

/*******************************************************************************
* Function Name  : MSD_SPIHighSpeed
* Description    : 
* Input          : - b_high : 	1 = 18MHz, 0 = 281.25Hz
* Output         : None
* Return         : None
*******************************************************************************/
void MSD_SPIHighSpeed(u8 b_high)
{
  SPI_InitTypeDef SPI_InitStructure;

  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
	SPI_InitStructure.SPI_CRCPolynomial = 7;

	// Speed select
  if(b_high == FALSE)
  {
		SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
  }
  else
  {
		SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  }

	SPI_Init(SPI1, &SPI_InitStructure);
}

/*******************************************************************************
* Function Name  : MSD_Init
* Description    : 
* Input          : None
* Output         : None
* Return         :
*******************************************************************************/
u8 MSD_Init(void)
{
	u8 r1;	
	u8 buff[6] = {0};
	u16 retry; 

/*
	// Check, if no card insert, return;
	if(!_card_insert())
	{ 
#if PRINT_INFO == TRUE
		printf("There is no card detected!\r\n");
#endif

		// FATFS error flag
    return STA_NODISK;
	}
*/	
	// Power on and delay some times	
	for(retry=0; retry<0x100; retry++)
	{
		_card_power_on();
	}	

	// Satrt send 74 clocks at least
	for(retry=0; retry<10; retry++)
	{
		_spi_read_write(DUMMY_BYTE);
	}	
	
	// Start send CMD0 till return 0x01 means in IDLE state
	for(retry=0; retry<0xFFF; retry++)
	{
		r1 = _send_command(CMD0, 0, 0x95);
		if(r1 == 0x01)
		{
			retry = 0;
			break;
		}
	}
	// Timeout return
	if(retry == 0xFFF)
	{
#if PRINT_INFO == TRUE
		printf("Reset card into IDLE state failed!\r\n");
#endif
		return 1;
	}
	
	// Get the card type, version
	r1 = _send_command_hold(CMD8, 0x1AA, 0x87);
	// r1=0x05 -> V1.0
	if(r1 == 0x05)
	{
		CardInfo.CardType = CARDTYPE_SDV1;

		// End of CMD8, chip disable and dummy byte 
	  _card_disable();
	  _spi_read_write(DUMMY_BYTE);
		
		// SD1.0/MMC start initialize
		// Send CMD55+ACMD41, No-response is a MMC card, otherwise is a SD1.0 card
		for(retry=0; retry<0xFFF; retry++)
		{
			r1 = _send_command(CMD55, 0, 0);			// should be return 0x01
			if(r1 != 0x01)
			{
#if PRINT_INFO == TRUE
				printf("Send CMD55 should return 0x01, response=0x%02x\r\n", r1);
#endif
				return r1;
			}

			r1 = _send_command(ACMD41, 0, 0);			// should be return 0x00
			if(r1 == 0x00)
			{
				retry = 0;
				break;
			}
		}

		// MMC card initialize start 
		if(retry == 0xFFF)
		{
			for(retry=0; retry<0xFFF; retry++)
			{
				r1 = _send_command(CMD1, 0, 0);			// should be return 0x00
				if(r1 == 0x00)
				{
					retry = 0;
					break;
				}
			}

		 	// Timeout return
			if(retry == 0xFFF)
			{
#if PRINT_INFO == TRUE
				printf("Send CMD1 should return 0x00, response=0x%02x\r\n", r1);
#endif
				return 2;
			}	
			
			CardInfo.CardType = CARDTYPE_MMC;		
#if PRINT_INFO == TRUE
			printf("Card Type                     : MMC\r\n");
#endif 				
		}		
		// SD1.0 card detected, print information
#if PRINT_INFO == TRUE
		else
		{
			printf("Card Type                     : SD V1\r\n");
		}
#endif 
		
		// Set spi speed high
		MSD_SPIHighSpeed(1);		
		
		// CRC disable
		r1 = _send_command(CMD59, 0, 0x01);
		if(r1 != 0x00)
		{
#if PRINT_INFO == TRUE
				printf("Send CMD59 should return 0x00, response=0x%02x\r\n", r1);
#endif
			return r1;		// response error, return r1
		}
		  
		// Set the block size
		r1 = _send_command(CMD16, MSD_BLOCKSIZE, 0xFF);
		if(r1 != 0x00)
		{
#if PRINT_INFO == TRUE
			printf("Send CMD16 should return 0x00, response=0x%02x\r\n", r1);
#endif
			return r1;		// response error, return r1
		}
	}	
	
	// r1=0x01 -> V2.x, read OCR register, check version
	else if(r1 == 0x01)
	{
		// 4Bytes returned after CMD8 sent
		buff[0] = _spi_read_write(DUMMY_BYTE);					//should be 0x00
		buff[1] = _spi_read_write(DUMMY_BYTE);					//should be 0x00
		buff[2] = _spi_read_write(DUMMY_BYTE);					//should be 0x01
		buff[3] = _spi_read_write(DUMMY_BYTE);					//should be 0xAA
		
		// End of CMD8, chip disable and dummy byte 
	  _card_disable();
	  _spi_read_write(DUMMY_BYTE);
		
		// Check voltage range be 2.7-3.6V
		if(buff[2]==0x01 && buff[3]==0xAA)
		{
			for(retry=0; retry<0xFFF; retry++)
			{
				r1 = _send_command(CMD55, 0, 0);							// should be return 0x01
				if(r1!=0x01)
				{
#if PRINT_INFO == TRUE
					printf("Send CMD55 should return 0x01, response=0x%02x\r\n", r1);
#endif
					return r1;
				}				

				r1 = _send_command(ACMD41, 0x40000000, 0);		// should be return 0x00
				if(r1 == 0x00)
				{
					retry = 0;
					break;
				}
			}
 		 	
			// Timeout return
			if(retry == 0xFFF)
			{
#if PRINT_INFO == TRUE
				printf("Send ACMD41 should return 0x00, response=0x%02x\r\n", r1);
#endif
				return 3;
			}

			// Read OCR by CMD58
	    r1 = _send_command_hold(CMD58, 0, 0);
	    if(r1!=0x00)
	    {
#if PRINT_INFO == TRUE
				printf("Send CMD58 should return 0x00, response=0x%02x\r\n", r1);
#endif
        return r1;		// response error, return r1
	    }

	    buff[0] = _spi_read_write(DUMMY_BYTE);					
			buff[1] = _spi_read_write(DUMMY_BYTE);					
			buff[2] = _spi_read_write(DUMMY_BYTE);					
			buff[3] = _spi_read_write(DUMMY_BYTE);					

			// End of CMD58, chip disable and dummy byte 
		  _card_disable();
		  _spi_read_write(DUMMY_BYTE);
	
	    // OCR -> CCS(bit30) 
			// 	1: SDV2HC
			//	0: SDV2
	    if(buff[0] & 0x40)
	    {
        CardInfo.CardType = CARDTYPE_SDV2HC;
#if PRINT_INFO == TRUE == 1
				printf("Card Type                     : SD V2HC\r\n");
#endif 	
	    }
	    else
	    {
        CardInfo.CardType = CARDTYPE_SDV2;
#if PRINT_INFO == TRUE == 1
				printf("Card Type                     : SD V2\r\n");
#endif 	
	    }

			// Set spi speed high
			MSD_SPIHighSpeed(1);
		}	
	}

	return 0;
}

/*******************************************************************************
* Function Name  : MSD_GetCardInfo
* Description    : 
* Input          : - *pCID
* Output         : None
* Return         : 0:NO_ERR; TRUE: Error
*******************************************************************************/
u8 MSD_GetCardInfo(PMSD_CARDINFO cardinfo)
{
  u8 r1;
	u8 CSD_Tab[16];
	u8 CID_Tab[16];

  // Send CMD9, Read CSD
 	r1 = _send_command(CMD9, 0, 0xFF);
  if(r1 != 0x00)
  {
    return r1;
  }

	if(_read_buffer(CSD_Tab, 16, RELEASE))
	{
		return 1;
	}

  // Send CMD10, Read CID
 	r1 = _send_command(CMD10, 0, 0xFF);
  if(r1 != 0x00)
  {
    return r1;
  }

	if(_read_buffer(CID_Tab, 16, RELEASE))
	{
		return 2;
	}  

  /* Byte 0 */
  cardinfo->CSD.CSDStruct = (CSD_Tab[0] & 0xC0) >> 6;
  cardinfo->CSD.SysSpecVersion = (CSD_Tab[0] & 0x3C) >> 2;
  cardinfo->CSD.Reserved1 = CSD_Tab[0] & 0x03;
  /* Byte 1 */
  cardinfo->CSD.TAAC = CSD_Tab[1] ;
  /* Byte 2 */
  cardinfo->CSD.NSAC = CSD_Tab[2];
  /* Byte 3 */
  cardinfo->CSD.MaxBusClkFrec = CSD_Tab[3];
  /* Byte 4 */
  cardinfo->CSD.CardComdClasses = CSD_Tab[4] << 4;
  /* Byte 5 */
  cardinfo->CSD.CardComdClasses |= (CSD_Tab[5] & 0xF0) >> 4;
  cardinfo->CSD.RdBlockLen = CSD_Tab[5] & 0x0F;
  /* Byte 6 */
  cardinfo->CSD.PartBlockRead = (CSD_Tab[6] & 0x80) >> 7;
  cardinfo->CSD.WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6;
  cardinfo->CSD.RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5;
  cardinfo->CSD.DSRImpl = (CSD_Tab[6] & 0x10) >> 4;
  cardinfo->CSD.Reserved2 = 0; /* Reserved */
  cardinfo->CSD.DeviceSize = (CSD_Tab[6] & 0x03) << 10;
  /* Byte 7 */
  cardinfo->CSD.DeviceSize |= (CSD_Tab[7]) << 2;
  /* Byte 8 */
  cardinfo->CSD.DeviceSize |= (CSD_Tab[8] & 0xC0) >> 6;
  cardinfo->CSD.MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3;
  cardinfo->CSD.MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07);
  /* Byte 9 */
  cardinfo->CSD.MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5;
  cardinfo->CSD.MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2;
  cardinfo->CSD.DeviceSizeMul = (CSD_Tab[9] & 0x03) << 1;
  /* Byte 10 */
  cardinfo->CSD.DeviceSizeMul |= (CSD_Tab[10] & 0x80) >> 7;
  cardinfo->CSD.EraseGrSize = (CSD_Tab[10] & 0x7C) >> 2;
  cardinfo->CSD.EraseGrMul = (CSD_Tab[10] & 0x03) << 3;
  /* Byte 11 */
  cardinfo->CSD.EraseGrMul |= (CSD_Tab[11] & 0xE0) >> 5;
  cardinfo->CSD.WrProtectGrSize = (CSD_Tab[11] & 0x1F);
  /* Byte 12 */
  cardinfo->CSD.WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7;
  cardinfo->CSD.ManDeflECC = (CSD_Tab[12] & 0x60) >> 5;
  cardinfo->CSD.WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2;
  cardinfo->CSD.MaxWrBlockLen = (CSD_Tab[12] & 0x03) << 2;
  /* Byte 13 */
  cardinfo->CSD.MaxWrBlockLen |= (CSD_Tab[13] & 0xc0) >> 6;
  cardinfo->CSD.WriteBlockPaPartial = (CSD_Tab[13] & 0x20) >> 5;
  cardinfo->CSD.Reserved3 = 0;
  cardinfo->CSD.ContentProtectAppli = (CSD_Tab[13] & 0x01);
  /* Byte 14 */
  cardinfo->CSD.FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7;
  cardinfo->CSD.CopyFlag = (CSD_Tab[14] & 0x40) >> 6;
  cardinfo->CSD.PermWrProtect = (CSD_Tab[14] & 0x20) >> 5;
  cardinfo->CSD.TempWrProtect = (CSD_Tab[14] & 0x10) >> 4;
  cardinfo->CSD.FileFormat = (CSD_Tab[14] & 0x0C) >> 2;
  cardinfo->CSD.ECC = (CSD_Tab[14] & 0x03);
  /* Byte 15 */
  cardinfo->CSD.CSD_CRC = (CSD_Tab[15] & 0xFE) >> 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -