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

📄 sd_mmc_spi.c

📁 SD卡调试所用的资料
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Define to prevent recursive inclusion -------------------------------------*/
#include "sd_mmc_spi.h"

#define SD_MMC_SPI_SELECT()   GPIO_ResetBits(SD_MMC_SPI_CS, SD_MMC_SPI_CS_Pin_CS) 
#define SD_MMC_SPI_DESELECT() GPIO_SetBits(SD_MMC_SPI_CS, SD_MMC_SPI_CS_Pin_CS)


#if !SD_RAW_SAVE_RAM
  // static data buffer for acceleration
  static u8 raw_block[512];
  // offset where the data within raw_block lies on the card
  static u32 raw_block_address;
  #if SD_RAW_WRITE_BUFFERING
    // flag to remember if raw_block was written to the card
    static u8 raw_block_written;
  #endif
#endif



/*******************************************************************************
* Function Name  : SD_MMC_SPI_Init
* Description    : SD_MMC_SPI_Init
* Input          : None
* Output         : None
* Return         : False init error, True init successerror
*******************************************************************************/
u8 SD_MMC_SPI_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Enable SPI1 and GPIO clocks */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA |
                         RCC_APB2Periph_SD_MMC_SPI_CS, ENABLE);

  /* Configure SPI1 pins: SCK, MISO and MOSI */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure SD_MMC_SPI_CS */
  GPIO_InitStructure.GPIO_Pin = SD_MMC_SPI_CS_Pin_CS;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(SD_MMC_SPI_CS, &GPIO_InitStructure);
  
   /* Configure SD power pins: PD.10 */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
  
  //////////////////////////////////////////////////////////////////////////////
  
    SD_MMC_Power_On_Off(On); //开启SD MMC电源
    
    SD_MMC_Low_Speed();     // 使用低速SPI
    
    
    /* 最少发送 74 时钟启动SD卡 */
    for(u8 i = 0; i < 10; ++i)
    {
        SD_MMC_ReadWrite_Byte(0x00);
    }
    
    SD_MMC_SPI_SELECT();    //使能SD卡的SPI总线

    
    /* reset SD卡 */
    u8 response;
    for(u16 i = 0; ; ++i)
    {
        response = SD_MMC_Send_Command(CMD_GO_IDLE_STATE , 0 );
        if( response == 0x01 ) // 当返回 0x01时 重启成功
            break;

        if(i == 0x1ff)         // 当超时 退出 初始化失败
        {
            SD_MMC_SPI_DESELECT();
            SD_MMC_Power_On_Off(Off);
            return False;
        }
    }
    
    /* 等待 SD卡 准备好 */
    for(u16 i = 0; ; ++i)
    {
        response = SD_MMC_Send_Command(CMD_SEND_OP_COND, 0);
        if( !(response & (1 << R1_IDLE_STATE)) ) // 当返回 0x01时 SD卡准备好
            break;

        if(i == 0x7fff)                         // 当超时 退出 初始化失败
        {
            SD_MMC_SPI_DESELECT();
            SD_MMC_Power_On_Off(Off);
            return False;
        }
    }

    /* 设置 512个字节为一个 BLOCK */
    if(SD_MMC_Send_Command(CMD_SET_BLOCKLEN, 512))
    {
        SD_MMC_SPI_DESELECT();
        return False;
    }

    SD_MMC_High_Speed();// 使用高速SPI
    
    /* 不使用 crc 校验  */
    if(SD_MMC_Send_Command(59, 0))
    {
        SD_MMC_SPI_DESELECT();
        return False;
    }
    
    SD_MMC_SPI_DESELECT();//失能SD卡的SPI总线
    
////////////////////////////////////////////////////////////////////////////////
    
//添加原来文件系统
#if !SD_RAW_SAVE_RAM
    // the first block is likely to be accessed first, so precache it here
    //很可能首先访问第一块,所以在这里预先初始化缓存
    raw_block_address = 0xffffffff;
  #if SD_RAW_WRITE_BUFFERING
    raw_block_written = 1;
  #endif
    //if(!sd_raw_read(0, raw_block, sizeof(raw_block))) return 0;
#endif
    
  return True;
}

/*******************************************************************************
* Function Name  : SPI_SendByte
* Description    : Sends a byte through the SPI interface and return the byte
*                  received from the SPI bus.
* Input          : byte : byte to send.
* Output         : None
* Return         : The value of the received byte.
*******************************************************************************/
u8 SPI1_SendByte(u8 byte)
{
  /* 等待发送寄存器空 */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
  /* 发送一个字节到 SPI1  */
  SPI_I2S_SendData(SPI1, byte);
  /* 等待接收到一个字节 */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
  /* 返回接收到的字节 */
  return SPI_I2S_ReceiveData(SPI1);
}


/*******************************************************************************
* Function Name  : SD_MMC_ReadWrite_Byte
* Description    : SD_MMC_ReadWrite_Byte
* Input          : the char to send
* Output         : None
* Return         : the char received
*******************************************************************************/
u8 SD_MMC_ReadWrite_Byte(u8 ch)
{
  return (SPI1_SendByte(ch));
}

/*******************************************************************************
* Function Name  : SD_MMC_Low_Speed
* Description    : SD_MMC_Low_Speed
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SD_MMC_Low_Speed(void)
{
        SPI_InitTypeDef  SPI_InitStructure;
        /* SPI1 configuration */
        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_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
        SPI_InitStructure.SPI_CRCPolynomial = 7;

        SPI_Init(SPI1, &SPI_InitStructure);

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

/*******************************************************************************
* Function Name  : SD_MMC_High_Speed
* Description    : SD_MMC_High_Speed
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SD_MMC_High_Speed(void)
{
        SPI_InitTypeDef  SPI_InitStructure;
        /* SPI1 configuration */
        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_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
        SPI_InitStructure.SPI_CRCPolynomial = 7;

        SPI_Init(SPI1, &SPI_InitStructure);

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

/*******************************************************************************
* Function Name  : SD_MMC_Send_Command
* Description    : SD_MMC_Send_Command
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
u8 SD_MMC_Send_Command(u8 cmd, u32 arg)
{
        u8 Response;
        u8 Retry = 0;

        SD_MMC_ReadWrite_Byte(0xff);

        SD_MMC_SPI_SELECT();

        //分别写入命令
        SD_MMC_ReadWrite_Byte(cmd | 0x40); 
        SD_MMC_ReadWrite_Byte(arg >> 24);
        SD_MMC_ReadWrite_Byte(arg >> 16);
        SD_MMC_ReadWrite_Byte(arg >> 8);
        SD_MMC_ReadWrite_Byte(arg);
        SD_MMC_ReadWrite_Byte(0x95);


        do{
                // 等待响应,响应的开始位为0 
                Response = SD_MMC_ReadWrite_Byte(0xff);
                Retry++;
        }while( ((Response&0x80)!=0) && (Retry < 200) );

        SD_MMC_SPI_DESELECT();

        return Response;  //返回状态值
}


/*******************************************************************************
* Function Name  : SD_MMC_Read_Single_Block
* Description    : SD_MMC_Read_Single_Block
* Input          : sector number and buffer data point
* Output         : None
* Return         : zero success, non-zero error
*******************************************************************************/
u8 SD_MMC_Read_Single_Block(u32 sector, u8* buffer)
{
        u8 Response;
        u16 i;
        u16 Retry = 0;

         //读命令 send read command
        Response = SD_MMC_Send_Command(CMD_READ_SINGLE_BLOCK, sector<<9);

        if(Response != 0x00)
                return Response;

        SD_MMC_SPI_SELECT();

        // start byte 0xfe
        while(SD_MMC_ReadWrite_Byte(0xff) != 0xfe)
        {
          if(++Retry > 0xfffe)
          {
              SD_MMC_SPI_DESELECT();
              return 1; //timeout
          }
        }

        for(i = 0; i < 512; ++i)
        {
                //读512个数据
                *buffer++ = SD_MMC_ReadWrite_Byte(0xff);
        }

        SD_MMC_ReadWrite_Byte(0xff);  //伪crc
        SD_MMC_ReadWrite_Byte(0xff);  //伪crc

        SD_MMC_SPI_DESELECT();
        SD_MMC_ReadWrite_Byte(0xff);  // extra 8 CLK

        return 0;
}


/*******************************************************************************
* Function Name  : SD_MMC_Write_Single_Block
* Description    : SD_MMC_Write_Single_Block
* Input          : sector number and buffer data point
* Output         : None
* Return         : zero success, non-zero error.
*******************************************************************************/
u8 SD_MMC_Write_Single_Block(u32 sector, u8* buffer)
{
	u8 Response;
	u16 i;
	u16 retry=0;
	
        //写命令  send write command
	Response = SD_MMC_Send_Command(CMD_WRITE_SINGLE_BLOCK, sector<<9);
	if(Response != 0x00)
	  return Response;

	SD_MMC_SPI_SELECT();
	
	SD_MMC_ReadWrite_Byte(0xff);
	SD_MMC_ReadWrite_Byte(0xff);
	SD_MMC_ReadWrite_Byte(0xff);

        //发开始符	start byte 0xfe
	SD_MMC_ReadWrite_Byte(0xfe);
	
        //送512字节数据	send 512 bytes data
	for(i=0; i<512; i++)
	{
		SD_MMC_ReadWrite_Byte(*buffer++);
	}
	
	SD_MMC_ReadWrite_Byte(0xff); //dummy crc
	SD_MMC_ReadWrite_Byte(0xff); //dummy crc
	
	Response = SD_MMC_ReadWrite_Byte(0xff);
	
        //等待是否成功	judge if it successful
	if( (Response&0x1f) != 0x05)
	{
		SD_MMC_SPI_DESELECT();
		return Response;
	}
	//等待操作完  wait no busy
	while(SD_MMC_ReadWrite_Byte(0xff) != 0x00)
	{
		if(retry++ > 0xfffe)
		{
			SD_MMC_SPI_DESELECT();
			return 1;
		}
	}
	SD_MMC_SPI_DESELECT();
	SD_MMC_ReadWrite_Byte(0xff);// extra 8 CLK

	return 0;
}

/*******************************************************************************
* Function Name  : SD_MMC_Power_On_Off
* Description    : SD_MMC_Power_On_Off
* Input          : On or Off
* Output         : None
* Return         : None
*******************************************************************************/
void SD_MMC_Power_On_Off(u8 On_Off)
{
  // 0 power on        1 power off 
  if( On_Off == On )
    GPIO_ResetBits(GPIOD, GPIO_Pin_10);
  else
    GPIO_SetBits(GPIOD, GPIO_Pin_10);
}


/////////////////////////////////////////////////////////////////////////////////////////////


//static void SD_MMC_ReadWrite_Byte(u8 b);
//static u8 SD_MMC_ReadWrite_Byte();
//static u8 SD_MMC_Send_Command(u8 command, u32 arg);


/*******************************************************************************
* Function Name  : SD_Raw_Available
* Description    : 检测SD卡是否插入卡槽
* Input          : None
* Output         : None
* Return         : 0 --- 无卡 1 -- 有卡
*******************************************************************************/
u8 SD_Raw_Available()
{
    return 1;//get_pin_available() == 0x00;
}


/*******************************************************************************
* Function Name  : SD_Raw_Locked
* Description    : 检测SD卡是否写保护状态
* Input          : None
* Output         : None
* Return         : 0 --- 写保护 1 -- 无保护
*******************************************************************************/
u8 SD_Raw_Locked()
{
    return 1;//get_pin_locked() == 0x00;
}

/*******************************************************************************
* Function Name  : SD_Raw_Read
* Description    : SD_Raw_Read
* Input          : None
* Output         : None
* Return         : 0 --- fail 1 -- OK
*******************************************************************************/
u8 SD_Raw_Read(u32 offset, u8* buffer, u16 length)
{
    u32 block_address;
    u16 block_offset;
    u16 read_length;
    while(length > 0)
    {
        /* determine byte count to read at once */
        block_address = offset & 0xfffffe00;
        block_offset = offset & 0x01ff;
        read_length = 512 - block_offset; /* read up to block border */
        if(read_length > length)
            read_length = length;

#if !SD_RAW_SAVE_RAM
        /* check if the requested data is cached */
        if(block_address != raw_block_address)
#endif
        {
#if SD_RAW_WRITE_BUFFERING
            if(!raw_block_written)
            {
                if(!SD_Raw_Write(raw_block_address, raw_block, sizeof(raw_block)))
                    return 0;
            }
#endif

            //这两个次序很重要 begin
            /* send single block request */
            if(SD_MMC_Send_Command(CMD_READ_SINGLE_BLOCK, block_address))
            {
                SD_MMC_SPI_DESELECT();
                return 0;
            }
            /* address card */
            SD_MMC_SPI_SELECT();
            //这两个次序很重要 end

            /* wait for data block (start byte 0xfe) */
            while(SD_MMC_ReadWrite_Byte(0xff) != 0xfe);

#if SD_RAW_SAVE_RAM
            /* read byte block */
            u16 read_to = block_offset + read_length;
            for(u16 i = 0; i < 512; ++i)
            {
                u8 b = SD_MMC_ReadWrite_Byte(0xff);
                if(i >= block_offset && i < read_to)
                    *buffer++ = b;
            }
#else
            /* read byte block */
            u8* cache = raw_block;
            for(u16 i = 0; i < 512; ++i)
                *cache++ = SD_MMC_ReadWrite_Byte(0xff);

            raw_block_address = block_address;

            memcpy(buffer, raw_block + block_offset, read_length);
            buffer += read_length;
#endif

            /* read crc16 */
            SD_MMC_ReadWrite_Byte(0xff);

⌨️ 快捷键说明

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