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

📄 sd_mmc_spi.c

📁 基于STM32的 模拟时序
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************Copyright (c)**************************************************
**                       思 蜕 盟 豆 皮 开 发 小 组
**                             stmfans 论坛
**
**                   QQ 群: 65081316  StmFans思蜕盟 1组
**                   QQ 群: 68584951  StmFans思蜕盟 2组
**                      http://www.stmfans.com/bbs/
**
** This program was produced by the
** IAR Embedded Workbench 4.0 Kickstart 442
** Copyright 2008-2009 stmfans 
** Chip type           : STM32F103VB
** Program type        : Application
** Clock frequency     : 8.000000 MHz
** Memory model        : 
** External SRAM size  : 
** Data Stack size     : 
**--------------文件信息--------------------------------------------------------------------------------
**文   件   名: sd_mmc_spi.c
**创   建   人: 陈海
**最后修改日期: 2008年10月23日
**描        述: 豆皮开发板教程
**              
**--------------历史版本信息----------------------------------------------------------------------------
** 创建人: 陈海
** 版  本: v0.01
** 日 期: 2008年10月23日
** 描 述: 原始版本
**
**--------------当前版本信息----------------------------------------------------------------------------
** 创建人: 陈海
** 版  本: v0.01
** 日 期: 2008年10月23日
** 描 述: 当前版本
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/

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

/* Define to prevent recursive inclusion -------------------------------------*/
#include "sd_mmc_spi.h"
#include "string.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         : non-zero init success, zero init error (迁就原系统 优化时修改) 
*******************************************************************************/
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 |RCC_APB2Periph_SD_MMC_SPI_POWER, ENABLE);

  /* Configure SD_MMC_SPI_POWER */
  GPIO_InitStructure.GPIO_Pin = SD_MMC_SPI_POWER_Pin;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(SD_MMC_SPI_POWER, &GPIO_InitStructure);

  //关闭SD卡电源
  GPIO_SetBits(SD_MMC_SPI_POWER, SD_MMC_SPI_POWER_Pin);
  Delay_Ms(3000);
  
  /* 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_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(SD_MMC_SPI_CS, &GPIO_InitStructure);


  GPIO_ResetBits(SD_MMC_SPI_POWER, SD_MMC_SPI_POWER_Pin);
  Delay_Ms(100);
  //////////////////////////////////////////////////////////////////////////////
    /* initialize SPI with lowest frequency */
    SD_MMC_Low_Speed();
    
    /* card needs 74 cycles minimum to start up */
   // for(u8 i = 0; i < 10; ++i)
    for(u8 i = 0; i < 0x20; ++i)
    {
        /* wait 8 clock cycles */
        SD_MMC_ReadWrite_Byte(0xff);
    }

    /* address card */
    SD_MMC_SPI_SELECT();

    /* reset card */
    u8 response;
    for(u16 i = 0; ; ++i)
    {
        response = SD_MMC_Send_Command(CMD_GO_IDLE_STATE , 0 );
        if( response == 0x01 )
            break;

        if(i == 0xfff)
        {
            SD_MMC_SPI_DESELECT();
            return 0;
        }
    }
    
    /* wait for card to get ready */
    for(u16 i = 0; ; ++i)
    {
        response = SD_MMC_Send_Command(CMD_SEND_OP_COND, 0);
        if(!(response & (1 << R1_IDLE_STATE)))
            break;

        if(i == 0x7fff)
        {
            SD_MMC_SPI_DESELECT();
            return 0;
        }
    }

    /* set block size to 512 bytes */
    if(SD_MMC_Send_Command(CMD_SET_BLOCKLEN, 512))
    {
        SD_MMC_SPI_DESELECT();
        return 0;
    }

     GPIO_ResetBits(GPIOB, GPIO_Pin_15);
    
    /* deaddress card */
    SD_MMC_SPI_DESELECT();

    /* switch to highest SPI frequency possible */
    SD_MMC_High_Speed();

    //添加原来文件系统
#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 1;
  //////////////////////////////////////////////////////////////////////////////
}

/*******************************************************************************
* 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)
{
    /* Loop while DR register in not emplty */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

  /* Send byte through the SPI1 peripheral */
  SPI_I2S_SendData(SPI1, ch);

  /* Wait to receive a byte */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

  /* Return the byte read from the SPI bus */
  return SPI_I2S_ReceiveData(SPI1);
}

/*******************************************************************************
* 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;

        /* wait some clock cycles */
        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(cmd == CMD_GO_IDLE_STATE ? 0x95 : 0xff);

        /* receive response */
        for(u8 i = 0; i < 20; ++i)
        {
            response = SD_MMC_ReadWrite_Byte(0xff);
            if(response != 0xff)
                break;
        }
        
        //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;
}


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


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


/**
 * \ingroup sd_raw
 * Checks wether a memory card is located in the slot.
 *
 * \returns 1 if the card is available, 0 if it is not.
 */
u8 sd_raw_available()
{
    return 1;//get_pin_available() == 0x00;
}

/**
 * \ingroup sd_raw
 * Checks wether the memory card is locked for write access.
 *
 * \returns 1 if the card is locked, 0 if it is not.
 */
u8 sd_raw_locked()
{
    return 1;//get_pin_locked() == 0x00;
}


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

            /* address card */
            SD_MMC_SPI_SELECT();

            /* send single block request */
            if(SD_MMC_Send_Command(CMD_READ_SINGLE_BLOCK, block_address))
            {
                SD_MMC_SPI_DESELECT();
                return 0;
            }

            /* 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;

⌨️ 快捷键说明

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