专注电子技术学习与研究
当前位置:单片机教程网 >> STM32 >> 浏览文章

STM32f407在调试SDIO中的一些问题

作者:嵌入式高手   来源:会员上传   点击数:  更新时间:2014年05月20日   【字体:

我之前也调了3天,不知道为什么不行,遇到了一些问题,但今天都没有问题了,很稳定,和大家交流一下。

1.首先,一定要确定你的卡是好的,我这个就浪费了我一天的时间,你用笔记本看看是不是能识别和读写这个大卡,不要把小卡拿出来试试放回到卡套里,因为我就是卡套坏了。
2.基于官方给的这两个文件来修改的话,首先要注意引脚是否需要修改,主要是有个检测引脚可能会修改。
 
 3.在刚加入这两个文件后,我也遇到了一些提示错误,但是现在都不见了,我重新加入新的没有改动的这两个文件,也不会提示有问题,我是想说,原厂文件应该 是没有问题的,网上说的会提示的错误我也不知道为什么会有,我的非常稳定,4bit和25mhz,杠杠的,但是可以给出以下的建议,防止一些错误。
4.首先是初始化的时候,网上说应该在上电之后加入74clk时钟,其实可以不加,只要你上电之后初始化其他东西的时间足够,我是没有加,也没有任何问题。
5.然后就是在读写的时候可能有人遇到crc校验不正常或者没有检测到起始信号,给出以下提示:
  • 因为读写块函数调用了DMA的配置函数SD_LowLevel_DMA_TxConfig和SD_LowLevel_DMA_RxConfig,这两个函数中值得注意的是,SDDMA_InitStructure.DMA_BufferSize = xxx;这里的xxx其实可以为任意值,因为后面会有一句 DMA_FlowControllerConfig(SD_SDIO_DMA_STREAM, DMA_FlowCtrl_Peripheral);这个是硬件流控制,不论你设置多少的数,都会在初始化之后成为0xffff,详情看dma的硬件流部分。
  • SDIO也有一个硬件流,劝不要打开,因为打开之后会出现SDIO还需要数据的时候DMA已经停止工作了,具体原因不详。
  • 官方给的读写块函数,里面最好把DMA的使能还有SDIO的使能放在SDIO_DataInitStructure配置玩之后,安全点。举例如下,注意颜色部分是改动的。

 

SD_Error SD_WriteBlock(uint8_t *writebuff, uint64_t WriteAddr, uint16_t BlockSize)
{
  SD_Error errorstatus = SD_OK;

#if defined (SD_POLLING_MODE)
  uint32_t bytestransferred = 0, count = 0, restwords = 0;
  uint32_t *tempbuff = (uint32_t *)writebuff;
#endif

  TransferError = SD_OK;
  TransferEnd = 0;
  StopCondition = 0;
  SDIO->DCTRL = 0x0;


  if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  {
    BlockSize = 512;
    WriteAddr /= 512;
  }

 
  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN);

  if (SD_OK != errorstatus)
  {
    return(errorstatus);
  }

 
  SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)WriteAddr;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_SINGLE_BLOCK;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SD_CMD_WRITE_SINGLE_BLOCK);

  if (errorstatus != SD_OK)
  {
    return(errorstatus);
  }

  SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
  SDIO_DataInitStructure.SDIO_DataLength = BlockSize;
  SDIO_DataInitStructure.SDIO_DataBlockSize = (uint32_t) 9 << 4;
  SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
  SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
  SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
  SDIO_DataConfig(&SDIO_DataInitStructure);

 
#if defined (SD_POLLING_MODE)
  while (!(SDIO->STA & (SDIO_FLAG_DBCKEND | SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_STBITERR)))
  {
    if (SDIO_GetFlagStatus(SDIO_FLAG_TXFIFOHE) != RESET)
    {
      if ((512 - bytestransferred) < 32)
      {
        restwords = ((512 - bytestransferred) % 4 == 0) ? ((512 - bytestransferred) / 4) : (( 512 -  bytestransferred) / 4 + 1);
        for (count = 0; count < restwords; count++, tempbuff++, bytestransferred += 4)
        {
          SDIO_WriteData(*tempbuff);
        }
      }
      else
      {
        for (count = 0; count < 8; count++)
        {
          SDIO_WriteData(*(tempbuff + count));
        }
        tempbuff += 8;
        bytestransferred += 32;
      }
    }
  }
  if (SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT) != RESET)
  {
    SDIO_ClearFlag(SDIO_FLAG_DTIMEOUT);
    errorstatus = SD_DATA_TIMEOUT;
    return(errorstatus);
  }
  else if (SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL) != RESET)
  {
    SDIO_ClearFlag(SDIO_FLAG_DCRCFAIL);
    errorstatus = SD_DATA_CRC_FAIL;
    return(errorstatus);
  }
  else if (SDIO_GetFlagStatus(SDIO_FLAG_TXUNDERR) != RESET)
  {
    SDIO_ClearFlag(SDIO_FLAG_TXUNDERR);
    errorstatus = SD_TX_UNDERRUN;
    return(errorstatus);
  }
  else if (SDIO_GetFlagStatus(SDIO_FLAG_STBITERR) != RESET)
  {
    SDIO_ClearFlag(SDIO_FLAG_STBITERR);
    errorstatus = SD_START_BIT_ERR;
    return(errorstatus);
  }
#elif defined (SD_DMA_MODE)
  SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_RXOVERR | SDIO_IT_STBITERR, ENABLE);
 SD_LowLevel_DMA_TxConfig((uint32_t *)writebuff, BlockSize);
 SDIO_DMACmd(ENABLE);
#endif

 
  return(errorstatus);
}

关闭窗口

相关文章