STM之SD卡

SD卡基本函数

SPI_InitTypeDef结构体  SPI 初始化结构体

1.SD_Lowlevel_Init( );

    该函数初始化SPI相关外围时钟,配置GPIO引脚,调用SPI_Init( )初始化SPI_InitStructre结构体-->SPI_Init(SD_SPI, &SPI_InitStructure);

    SPI_Cmd(SD_SPI, ENABLE)使能SPI功能


2.SD_SPI_SetSpeedLow( );

    里面调用SD_SPI_SetSpeed(SPI_BaudRatePrescaler_256)降低SPI的时钟,初始化时需要使用低速模式


3.SD卡初始化的时候, SD_CS_HIGH( );挂起SD卡.延时至少74个时钟,等待SD卡完成内部操作,MMC协议中说明

/*!< Send dummy byte 0xFF, 10 times with CS high */
    /*!< Rise CS and MOSI for 80 clocks cycles */
    for (i = 0; i <= 9; i++)
    {
      /*!< Send dummy byte 0xFF */
      SD_WriteByte(SD_DUMMY_BYTE);
    } 

4.SD_GoIdleState( );  将SD卡设置在空闲状态

    之前SD_CS_HIGH( ),在这一步需要将CS_Low,在SD_GoIdleState( )函数中,

SD_Error SD_GoIdleState(void)
{
  SD_CS_LOW();   //设置CS_LOW
  
  /*!< Send CMD0 (SD_CMD_GO_IDLE_STATE) to put SD in SPI mode */
  SD_SendCmd(SD_CMD_GO_IDLE_STATE, 0, 0x95);          //发送CMD0,等待应答为0x01发送CMD0,收到的应答是0x01
  
  /*!< Wait for In Idle State Response (R1 Format) equal to 0x01 */
  if (SD_GetResponse(SD_IN_IDLE_STATE))         //SD_GetResponse()返回值: SD_RESPONSE_FAILURE,SD_RESPONSE_NO_ERROR         
  {
    /*!< No Idle State Response: return response failue */
    return SD_RESPONSE_FAILURE;
  }
  /*----------Activates the card initialization process-----------*/      //激活卡的初始化进程
  do
  {
    /*!< SD chip select high */
    SD_CS_HIGH();
    
    /*!< Send Dummy byte 0xFF */
    SD_WriteByte(SD_DUMMY_BYTE);
    
    /*!< SD chip select low */
    SD_CS_LOW();
    
    /*!< Send CMD1 (Activates the card process) until response equal to 0x0 */     //接着发送CMD1,收到的应答应该是0x00接着发送CMD1=0x41,收到的应答应该是0x00
    SD_SendCmd(SD_CMD_SEND_OP_COND, 0, 0xFF);
    /*!< Wait for no error Response (R1 Format) equal to 0x00 */
  }
  while (SD_GetResponse(SD_RESPONSE_NO_ERROR));        //SD_RESPONSE_NO_ERROR = (0x00),初始化成功后返回0x00,跳出while循环
 
 /*!< SD chip select high */ SD_CS_HIGH(); //最后拉高 /*!< Send dummy byte 0xFF */ SD_WriteByte(SD_DUMMY_BYTE); return SD_RESPONSE_NO_ERROR;}
5.获取SD卡信息SD_GetCardInfo(SD_CardInfo *cardinfo),定义了SD卡信息结构体,SD_CardInfo,

typedef struct
{
  SD_CSD SD_csd;               //csd  128位宽度 卡的工作条件的相关信息
  SD_CID SD_cid;               //cid  128位宽度 卡的识别码,用于识别单个卡的编号
  uint32_t CardCapacity;  /*!< Card Capacity */          //卡的大小
  uint32_t CardBlockSize; /*!< Card Block Size */        //块大小
} SD_CardInfo;
SD/MMC内部寄存器见 http://www.cnblogs.com/Efronc/archive/2010/03/27/1698474.html

SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo)
{
  SD_Error status = SD_RESPONSE_FAILURE;

  status = SD_GetCSDRegister(&(cardinfo->SD_csd));
  status = SD_GetCIDRegister(&(cardinfo->SD_cid));
  cardinfo->CardCapacity = (cardinfo->SD_csd.DeviceSize + 1) ;
  cardinfo->CardCapacity *= (1 << (cardinfo->SD_csd.DeviceSizeMul + 2));
  cardinfo->CardBlockSize = 1 << (cardinfo->SD_csd.RdBlockLen);
  cardinfo->CardCapacity *= cardinfo->CardBlockSize;

  /*!< Returns the reponse */
  return status;
}

6.STM   SPI数据发送接收过程,移位寄存器,状态位

   SPI_DR在发送和接收时用作数据缓冲器使用。在发送时,当数据从SPI_DR传送到移位寄存器时,TXE发送缓冲空标志置位,此时表示SPI_DR可以再次接收一个数据。所以在发送新的数据前,软件必须确认TXE标志位为'1',否则新的数据会覆盖已经写入SPI_DR里面的数据。

/*!< Wait until the transmit buffer is empty */
  while(SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_TXE) == RESET)    //当TXE置位时即=SET时,跳出循环。表示可以像SPI_DR写入新的数据
  {
  }
FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG)
{
  FlagStatus bitstatus = RESET;
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(SPIx));
  assert_param(IS_SPI_I2S_GET_FLAG(SPI_I2S_FLAG));
  /* Check the status of the specified SPI/I2S flag */
  if ((SPIx->SR & SPI_I2S_FLAG) != (uint16_t)RESET)
  {
    /* SPI_I2S_FLAG is set */
    bitstatus = SET;
  }
  else
  {
    /* SPI_I2S_FLAG is reset */
    bitstatus = RESET;
  }
  /* Return the SPI_I2S_FLAG status */
  return  bitstatus;
}
接收时,当数据被从移位寄存器传送到SPI_DR寄存器中时,设置RXNE标志位,此时可以从SPI_DR中读取数据,读出SPI_DR即可清除RXNE标志位
while (SPI_I2S_GetFlagStatus(SD_SPI, SPI_I2S_FLAG_RXNE) == RESET)
  {
  }

7.SPI_SendData( )其实就是往SPI_DR里写数据

void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data)
{
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(SPIx));
  
  /* Write in the DR register the data to be sent */
  SPIx->DR = Data;
}
8.读一个单块的过程

1. CS_LOW-->8个clk-->发送CMD17(单块)或CMD18(多块)读命令,返回0x00

2. 接收数据开始令牌0xfe -->正式接收数据512Bytes --> 接收CRC 校验2Bytes-->8个clk-->CS_HIGH

SD_Error SD_ReadBlock(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t BlockSize) 
   pBuffer是一个指针,指向接收到SD卡数据的地址。
   ReadAddr指向要读取的SD卡内部数据的起始地址
   BlockSize  SD卡块大小

SD_Error SD_ReadBlock(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t BlockSize)
{
  uint32_t i = 0;
  SD_Error rvalue = SD_RESPONSE_FAILURE;

  SD_CS_LOW();
  
if(flag_SDHC == 1)
{
	ReadAddr = ReadAddr/512;
}
  SD_SendCmd(SD_CMD_READ_SINGLE_BLOCK, ReadAddr, 0xFF);    //发送CMD17
  
  if (!SD_GetResponse(SD_RESPONSE_NO_ERROR))               //SD_RESPONSE_NO_ERROR=0x00,返回0x00,执行下面的if语句
  {
    if (!SD_GetResponse(SD_START_DATA_SINGLE_BLOCK_READ))  //获取接收数据开始令牌0XFE,Data token start byte,Start single Block Read
    {
      for (i = 0; i < BlockSize; i++)                      //循环写入,pBuffer-->data[512]
      {
        *pBuffer = SD_ReadByte();
        pBuffer++;
      }
      /*!< Get CRC bytes (not really needed by us, but required by SD) */
      SD_ReadByte();                                       //CRC校验
      SD_ReadByte();   
      
      rvalue = SD_RESPONSE_NO_ERROR;
    }
  }
  
  SD_CS_HIGH();                                            //拉高
  /*!< Send dummy byte: 8 Clock pulses of delay */            
  SD_WriteByte(SD_DUMMY_BYTE);                             //8个clk
 
  return rvalue;
}

9.写一个单块的过程写入单块数据流程:CS_LOW‐‐>8个clk‐‐>发送CMD24‐‐>接收响应R1‐‐>写入读数据起始令牌0xFE‐‐>写入数据‐‐>接收CRC‐‐>8个clk‐‐>CS_HIGH

SD_Error SD_WriteBlock(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t BlockSize)
{
  uint32_t i = 0;
  SD_Error rvalue = SD_RESPONSE_FAILURE;

  /*!< SD chip select low */
  SD_CS_LOW();

  if(flag_SDHC == 1)
  {
  	WriteAddr = WriteAddr/512;
  }
  /*!< Send CMD24 (SD_CMD_WRITE_SINGLE_BLOCK) to write multiple block */
  SD_SendCmd(SD_CMD_WRITE_SINGLE_BLOCK, WriteAddr, 0xFF);
  
  /*!< Check if the SD acknowledged the write block command: R1 response (0x00: no errors) */
  if (!SD_GetResponse(SD_RESPONSE_NO_ERROR))
  {
    /*!< Send a dummy byte */
    SD_WriteByte(SD_DUMMY_BYTE);

    /*!< Send the data token to signify the start of the data */
    SD_WriteByte(0xFE);

    /*!< Write the block data to SD : write count data by block */
    for (i = 0; i < BlockSize; i++)
    {
      /*!< Send the pointed byte */
      SD_WriteByte(*pBuffer);
      /*!< Point to the next location where the byte read will be saved */
      pBuffer++;
    }
    /*!< Put CRC bytes (not really needed by us, but required by SD) */
    SD_ReadByte();
    SD_ReadByte();

    /*!< Read data response */
    if (SD_GetDataResponse() == SD_DATA_OK)
    {
      rvalue = SD_RESPONSE_NO_ERROR;
    }
  }
  /*!< SD chip select high */
  SD_CS_HIGH();
  /*!< Send dummy byte: 8 Clock pulses of delay */
  SD_WriteByte(SD_DUMMY_BYTE);

  /*!< Returns the reponse */
  return rvalue;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值