OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3873|回复: 1

stm32f107上移植一个FATFS文件系统,SD卡驱动读写问题

[复制链接]

2

主题

13

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2015-10-13
在线时间
0 小时
发表于 2015-10-19 17:54:58 | 显示全部楼层 |阅读模式
5金钱

本人在stm32f107上移植一个FATFS文件系统,想把VS1053录制的音频文件存放到SD卡中,现在SD驱动老是不行,现请教下各位神仙帮忙解决下,vs1053驱动已完成就差SD卡驱动了

MCUSTM32F107VCT6

FATFS: V0.10B

SD :金士顿SDC4 8G卡  传输速度为4M/s

目前代码参考的是《》

代码如下:

函数:

#include <stdio.h>
#include "stm32f1xx_hal_sd.h"
#include "stm32f1xx_hal.h"
#include "stm32f1xx_hal_conf.h"
#include "MicroCard.h"
#include "Spi.h"

uint8_t SdStatus = SD_PRESENT;
SD_CardInfo SDCardInfo;
void SD_Delay(uint32_t nTime)
{
 while (nTime)
 {
  nTime--;
 }
}
#define EVAL_SPIx_TIMEOUT_MAX                   1000

#ifdef HAL_SPI_MODULE_ENABLED
uint32_t SpixTimeout = EVAL_SPIx_TIMEOUT_MAX;        /*<! Value of Timeout when SPI communication fails */

SPI_HandleTypeDef heval_Spi;
#endif /* HAL_SPI_MODULE_ENABLED */

void GetSPI_Handle(SPI_HandleTypeDef pSpiDef)
{
 heval_Spi = pSpiDef;
}

uint8_t MicroSD_init(void)
{

 uint8_t counter;
 uint32_t timeout = 0XFFFE;
 uint8_t szBuf[4];
   
 /* SD chip select high */
 uint16_t i;

 MICROSD_CS_HIGH();

 for (counter = 0; counter < 0x0F; counter++) // 发送至少74个脉冲
 {
  /* Send dummy byte 0xFF */
  MicroSD_IO_WriteByte(SD_DUMMY_BYTE);
 }

 /*SD initialized and set to SPI mode properly */
 /* Send CMD0 (SD_CMD_GO_IDLE_STATE) to put SD in SPI mode and wait for In Idle State Response (R1 Format) equal to 0x01 */

 if (MicroSD_SendCmd(MICROSD_CMD_GO_IDLE_STATE, 0, 0x95, SD_IN_IDLE_STATE) != MSD_OK)
 {
  /* No Idle State Response: return response failure */
  return MSD_ERROR;
 }

 /*----------Activates the card initialization process-----------*/
 /* Send CMD1 (Activates the card process) until response equal to 0x0 and
 Wait for no error Response (R1 Format) equal to 0x00 */
 //while (MicroSD_SendCmd(MICROSD_CMD_SEND_OP_COND, 0, 0xFF, SD_RESPONSE_NO_ERROR) != MSD_OK);   --参考其他说是MMC卡才使用cmd1 故注释掉

    if (MicroSD_SendCmd(MICROSD_CMD_SEND_IF_COND, 0x1AA, 0x87, 0x01) == MSD_OK)             //SD V2.0
 {
  for (i = 0; i < 4; i++)
  {
   szBuf = MicroSD_IO_ReadByte();
  }  //Get trailing return value of R7 resp
 
     while(MicroSD_SendCmd(MICROSD_CMD_APP, 0, 0X01, 0x01) != MSD_OK);         //发送CMD55    //参考SD 2.0标准说是需要发送cmd8 、acmd41以及cmd55才能初始化完成
  while(MicroSD_SendCmd(MICROSD_CMD_41, 0x40000000, 0X01, 0x00) != MSD_OK); //发送CMD41   
 }
   
   
 return MSD_OK;
}

uint8_t MicroSD_IsDetected(void)
{
 __IO uint8_t status = SD_PRESENT;

 /* Check SD card detect pin */
 if (HAL_GPIO_ReadPin(SD_DETECT_GPIO_PORT, SD_DETECT_PIN) != GPIO_PIN_RESET)
 {
  status = SD_NOT_PRESENT;
 }

 return status;
}

uint8_t MicroSD_SendCmd(uint8_t Cmd, uint32_t Arg, uint8_t Crc, uint8_t Response)
{
 uint8_t status = MSD_ERROR;

 if (MicroSD_IO_WriteCmd(Cmd, Arg, Crc, Response) == HAL_OK)
 {
  status = MSD_OK;
 }

 /* Send Dummy Byte */
 MicroSD_IO_WriteDummy();
 //printf("MicroSD_SendCmd end\r\n");
 return status;
}

void MicroSD_IO_WriteDummy(void)
{
 /* SD chip select high */
 MICROSD_CS_HIGH();

 /* Send Dummy byte 0xFF */
 MicroSD_IO_WriteByte(SD_DUMMY_BYTE);
}

HAL_StatusTypeDef  MicroSD_IO_WriteCmd(uint8_t Cmd, uint32_t Arg, uint8_t Crc, uint8_t Response)
{
 uint8_t frame[6];
    uint32_t counter = 0x00;
   
 /* Prepare Frame to send */
 frame[0] = Cmd | 0x40;        /* Construct byte 1 */
 frame[1] = Arg >> 24;         /* Construct byte 2 */
 frame[2] = Arg >> 16;         /* Construct byte 3 */
 frame[3] = Arg >> 8;          /* Construct byte 4 */
 frame[4] = Arg;               /* Construct byte 5 */
 frame[5] = Crc;               /* Construct CRC: byte 6 */

 /* SD chip select low */
 MICROSD_CS_LOW();

 /* Send Frame */
      for (counter = 0; counter < 6; counter++)
      {
         MicroSD_IO_WriteByte(frame[counter]); /* Send the Cmd bytes */
      }
     SD_Delay(5);
    
 if (Response != SD_NO_RESPONSE_EXPECTED)
 {
  return MicroSD_IO_WaitResponse(Response);
 }

 return HAL_OK;
}

void MicroSD_IO_WriteByte(uint8_t Data)
{
 /* Send the byte */
 HAL_StatusTypeDef status = HAL_OK;
 status = HAL_SPI_Transmit(&heval_Spi, (uint8_t *) &Data, 1,10000);
 if (status != HAL_OK)
 {
  /* Execute user timeout callback */
  printf("status=%d", status);
 }
}

HAL_StatusTypeDef MicroSD_IO_WaitResponse(uint8_t Response)
{
 uint32_t timeout = 0xFFFF;
 uint8_t resp = 0;
 /* Check if response is got or a timeout is happen */
 do
 {
  resp = MicroSD_IO_ReadByte();
  timeout--;
 }
 while ((resp != Response) && timeout);

 if (timeout == 0)
 {
  /* After time out */
  return HAL_TIMEOUT;
 }
 else
 {
  /* Right response got */
  return HAL_OK;
 }
}

uint8_t MicroSD_IO_ReadByte(void)
{
 HAL_StatusTypeDef status = HAL_OK;
 uint8_t          rdval = 0;
 uint8_t          wrval = 0xFF;

 status = HAL_SPI_TransmitReceive(&heval_Spi, &wrval, &rdval, 1,10000);
 //SD_Delay(10);
 /* Check the communication status */
 if (status != HAL_OK)
 {
  /* Execute user timeout callback */
  status = HAL_ERROR;
 }
 return rdval;
}

/**
  * @brief SPI Read 4 bytes from device
  * @retval Read data
*/


uint8_t MicroSD_ReadBlocks(uint32_t *p32Data, uint64_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)
{
 uint32_t counter = 0, offset = 0;
 uint8_t rvalue = MSD_ERROR;
 uint8_t *pData = (uint8_t *)p32Data;

 /* Send CMD16 (MICROMICROSD_CMD_SET_BLOCKLEN) to set the size of the block and
    Check if the SD acknowledged the set block length command: R1 response (0x00: no errors) */
 if (MicroSD_IO_WriteCmd(MICROSD_CMD_SET_BLOCKLEN, BlockSize, 0xFF, SD_RESPONSE_NO_ERROR) != HAL_OK)
 {
  return MSD_ERROR;
 }

 /* Data transfer */
 while (NumberOfBlocks--)
 {
  /* Send dummy byte: 8 Clock pulses of delay */
  MicroSD_IO_WriteDummy();

  /* Send CMD17 (MICROMICROSD_CMD_READ_SINGLE_BLOCK) to read one block */
  /* Check if the SD acknowledged the read block command: R1 response (0x00: no errors) */
  if (MicroSD_IO_WriteCmd(MICROSD_CMD_READ_SINGLE_BLOCK, ReadAddr + offset, 0xFF, SD_RESPONSE_NO_ERROR) != HAL_OK)
  {
   return MSD_ERROR;
  }

  /* Now look for the data token to signify the start of the data */
  if (MicroSD_IO_WaitResponse(SD_START_DATA_SINGLE_BLOCK_READ) == HAL_OK)
  {
   /* Read the SD block data : read NumByteToRead data */
   for (counter = 0; counter < BlockSize; counter++)
   {
    /* Read the pointed data */
    *pData = MicroSD_IO_ReadByte();
    /* Point to the next location where the byte read will be saved */
    pData++;
   }
   /* Set next read address*/
   offset += BlockSize;
   /* get CRC bytes (not really needed by us, but required by SD) */
   MicroSD_IO_ReadByte();
   MicroSD_IO_ReadByte();
   /* Set response value to success */
   rvalue = MSD_OK;
  }
  else
  {
   /* Set response value to failure */
   rvalue = MSD_ERROR;
  }
 }

 /* Send dummy byte: 8 Clock pulses of delay */
 MicroSD_IO_WriteDummy();
 /* Returns the reponse */
 return rvalue;
}

uint8_t MicroSD_WriteBlocks(uint32_t *p32Data, uint64_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)
{
 uint32_t counter = 0, offset = 0;
 uint8_t rvalue = MSD_ERROR;
 uint8_t *pData = (uint8_t *)p32Data;

 /* Data transfer */
 while (NumberOfBlocks--)
 {
  /* Send CMD24 (MICROMICROSD_CMD_WRITE_SINGLE_BLOCK) to write blocks  and Check if the SD acknowledged the write block command: R1 response (0x00: no errors) */
  if (MicroSD_IO_WriteCmd(MICROSD_CMD_WRITE_SINGLE_BLOCK, WriteAddr << 9 + offset, 0xFF, SD_RESPONSE_NO_ERROR) != HAL_OK)
  {
   return MSD_ERROR;
  }

  /* Send dummy byte */
  MicroSD_IO_WriteByte(SD_DUMMY_BYTE);

  /* Send the data token to signify the start of the data */
  MicroSD_IO_WriteByte(SD_START_DATA_SINGLE_BLOCK_WRITE);

  /* Write the block data to SD : write count data by block */
  for (counter = 0; counter < BlockSize; counter++)
  {
   /* Send the pointed byte */
   //printf("counter=%d",counter);
   MicroSD_IO_WriteByte(*pData);
   SD_Delay(5);

   /* Point to the next location where the byte read will be saved */
   pData++;
  }

  /* Set next write address */
  offset += BlockSize;

  /* Put CRC bytes (not really needed by us, but required by SD) */
  MicroSD_IO_ReadByte();
  MicroSD_IO_ReadByte();

  /* Read data response */
  if (MicroSD_GetDataResponse() == SD_DATA_OK)
  {
   /* Set response value to success */
   rvalue = MSD_OK;
  }
  else
  {
   /* Set response value to failure */
   rvalue = MSD_ERROR;
  }
 }

 /* Send dummy byte: 8 Clock pulses of delay */
 MicroSD_IO_WriteDummy();

 /* Returns the reponse */
 return rvalue;
}

SD_Info MicroSD_GetDataResponse(void)
{
 uint32_t counter = 0;
 SD_Info response, rvalue;

 while (counter <= 0xff)
 {
  /* Read response */
  response = (SD_Info)MicroSD_IO_ReadByte();

  /* Mask unused bits */
  response &= 0x1F;
  switch (response)
  {
   case SD_DATA_OK:
   {
    rvalue = SD_DATA_OK;
    break;
   }
   case SD_DATA_CRC_ERROR:
    return SD_DATA_CRC_ERROR;
   case SD_DATA_WRITE_ERROR:
    return SD_DATA_WRITE_ERROR;
   default:
   {
    rvalue = SD_DATA_OTHER_ERROR;
    break;
   }
  }
  /* Exit loop in case of data ok */
  if (rvalue == SD_DATA_OK)
  {
   break;
  }
  /* Increment loop counter */
  counter++;
 }

 /* Wait null data */
 while (MicroSD_IO_ReadByte() != 0);

 /* Return response */
 return response;
}


uint8_t MicroSD_GetCardInfo(SD_CardInfo *pCardInfo)
{
 uint8_t status = MSD_ERROR;

 MicroSD_GetCSDRegister(&(pCardInfo->Csd));
 status = MicroSD_GetCIDRegister(&(pCardInfo->Cid));
 pCardInfo->CardCapacity = (pCardInfo->Csd.DeviceSize + 1) ;
 pCardInfo->CardCapacity *= (1 << (pCardInfo->Csd.DeviceSizeMul + 2));
 pCardInfo->CardBlockSize = 1 << (pCardInfo->Csd.RdBlockLen);
 pCardInfo->CardCapacity *= pCardInfo->CardBlockSize;

 /* Returns the reponse */
 return status;
}

uint8_t MicroSD_GetCSDRegister(SD_CSD *Csd)
{
 uint32_t counter = 0;
 uint8_t rvalue = MSD_ERROR;
 uint8_t szCSDBuf[16];

 /* Send CMD9 (CSD register) or CMD10(CSD register) and Wait for response in the R1 format (0x00 is no errors) */
 if (MicroSD_IO_WriteCmd(MICROSD_CMD_SEND_CSD, 0, 0xFF, SD_RESPONSE_NO_ERROR) == HAL_OK)
 {
  if (MicroSD_IO_WaitResponse(SD_START_DATA_SINGLE_BLOCK_READ) == HAL_OK)
  {
   for (counter = 0; counter < 16; counter++)
   {
    /* Store CSD register value on szCSDBuf */
    szCSDBuf[counter] = MicroSD_IO_ReadByte();
    SD_Delay(5);
   }

   /* Get CRC bytes (not really needed by us, but required by SD) */
   MicroSD_IO_WriteByte(SD_DUMMY_BYTE);
   MicroSD_IO_WriteByte(SD_DUMMY_BYTE);

   /* Set response value to success */
   rvalue = MSD_OK;
  }
 }
 /* Send dummy byte: 8 Clock pulses of delay */
 MicroSD_IO_WriteDummy();

 if (rvalue == SD_RESPONSE_NO_ERROR)
 {
  /* Byte 0 */
  Csd->CSDStruct = (szCSDBuf[0] & 0xC0) >> 6;
  Csd->SysSpecVersion = (szCSDBuf[0] & 0x3C) >> 2;
  Csd->Reserved1 = szCSDBuf[0] & 0x03;

  /* Byte 1 */
  Csd->TAAC = szCSDBuf[1];

  /* Byte 2 */
  Csd->NSAC = szCSDBuf[2];

  /* Byte 3 */
  Csd->MaxBusClkFrec = szCSDBuf[3];

  /* Byte 4 */
  Csd->CardComdClasses = szCSDBuf[4] << 4;

  /* Byte 5 */
  Csd->CardComdClasses |= (szCSDBuf[5] & 0xF0) >> 4;
  Csd->RdBlockLen = szCSDBuf[5] & 0x0F;

  /* Byte 6 */
  Csd->artBlockRead = (szCSDBuf[6] & 0x80) >> 7;
  Csd->WrBlockMisalign = (szCSDBuf[6] & 0x40) >> 6;
  Csd->RdBlockMisalign = (szCSDBuf[6] & 0x20) >> 5;
  Csd->DSRImpl = (szCSDBuf[6] & 0x10) >> 4;
  Csd->Reserved2 = 0; /*!< Reserved */

  Csd->DeviceSize = (szCSDBuf[6] & 0x03) << 10;

  /* Byte 7 */
  Csd->DeviceSize |= (szCSDBuf[7]) << 2;

  /* Byte 8 */
  Csd->DeviceSize |= (szCSDBuf[8] & 0xC0) >> 6;

  Csd->MaxRdCurrentVDDMin = (szCSDBuf[8] & 0x38) >> 3;
  Csd->MaxRdCurrentVDDMax = (szCSDBuf[8] & 0x07);

  /* Byte 9 */
  Csd->MaxWrCurrentVDDMin = (szCSDBuf[9] & 0xE0) >> 5;
  Csd->MaxWrCurrentVDDMax = (szCSDBuf[9] & 0x1C) >> 2;
  Csd->DeviceSizeMul = (szCSDBuf[9] & 0x03) << 1;
  /* Byte 10 */
  Csd->DeviceSizeMul |= (szCSDBuf[10] & 0x80) >> 7;

  Csd->EraseGrSize = (szCSDBuf[10] & 0x40) >> 6;
  Csd->EraseGrMul = (szCSDBuf[10] & 0x3F) << 1;

  /* Byte 11 */
  Csd->EraseGrMul |= (szCSDBuf[11] & 0x80) >> 7;
  Csd->WrProtectGrSize = (szCSDBuf[11] & 0x7F);

  /* Byte 12 */
  Csd->WrProtectGrEnable = (szCSDBuf[12] & 0x80) >> 7;
  Csd->ManDeflECC = (szCSDBuf[12] & 0x60) >> 5;
  Csd->WrSpeedFact = (szCSDBuf[12] & 0x1C) >> 2;
  Csd->MaxWrBlockLen = (szCSDBuf[12] & 0x03) << 2;

  /* Byte 13 */
  Csd->MaxWrBlockLen |= (szCSDBuf[13] & 0xC0) >> 6;
  Csd->WriteBlockPaPartial = (szCSDBuf[13] & 0x20) >> 5;
  Csd->Reserved3 = 0;
  Csd->ContentProtectAppli = (szCSDBuf[13] & 0x01);

  /* Byte 14 */
  Csd->FileFormatGrouop = (szCSDBuf[14] & 0x80) >> 7;
  Csd->CopyFlag = (szCSDBuf[14] & 0x40) >> 6;
  Csd->ermWrProtect = (szCSDBuf[14] & 0x20) >> 5;
  Csd->TempWrProtect = (szCSDBuf[14] & 0x10) >> 4;
  Csd->FileFormat = (szCSDBuf[14] & 0x0C) >> 2;
  Csd->ECC = (szCSDBuf[14] & 0x03);

  /* Byte 15 */
  Csd->CSD_CRC = (szCSDBuf[15] & 0xFE) >> 1;
  Csd->Reserved4 = 1;
 }
 /* Return the reponse */
 return rvalue;
}

uint8_t MicroSD_GetCIDRegister(SD_CID *Cid)
{
 uint32_t counter = 0;
 uint8_t rvalue = MSD_ERROR;
 uint8_t szCIDBuf[16];

 /* Send CMD10 (CID register) and Wait for response in the R1 format (0x00
 is no errors) */
 if (MicroSD_IO_WriteCmd(MICROSD_CMD_SEND_CID, 0, 0xFF, SD_RESPONSE_NO_ERROR) == HAL_OK)
 {
  if (MicroSD_IO_WaitResponse(SD_START_DATA_SINGLE_BLOCK_READ) == HAL_OK)
  {
   /* Store CID register value on szCIDBuf */
   for (counter = 0; counter < 16; counter++)
   {
    szCIDBuf[counter] = MicroSD_IO_ReadByte();
   }

   /* Get CRC bytes (not really needed by us, but required by SD) */
   MicroSD_IO_WriteByte(SD_DUMMY_BYTE);
   MicroSD_IO_WriteByte(SD_DUMMY_BYTE);

   /* Set response value to success */
   rvalue = MSD_OK;
  }
 }

 /* Send dummy byte: 8 Clock pulses of delay */
 MicroSD_IO_WriteDummy();

 if (rvalue == MSD_OK)
 {
  /* Byte 0 */
  Cid->ManufacturerID = szCIDBuf[0];

  /* Byte 1 */
  Cid->OEM_AppliID = szCIDBuf[1] << 8;

  /* Byte 2 */
  Cid->OEM_AppliID |= szCIDBuf[2];

  /* Byte 3 */
  Cid->rodName1 = szCIDBuf[3] << 24;

  /* Byte 4 */
  Cid->rodName1 |= szCIDBuf[4] << 16;

  /* Byte 5 */
  Cid->rodName1 |= szCIDBuf[5] << 8;

  /* Byte 6 */
  Cid->rodName1 |= szCIDBuf[6];

  /* Byte 7 */
  Cid->rodName2 = szCIDBuf[7];

  /* Byte 8 */
  Cid->rodRev = szCIDBuf[8];

  /* Byte 9 */
  Cid->rodSN = szCIDBuf[9] << 24;

  /* Byte 10 */
  Cid->rodSN |= szCIDBuf[10] << 16;

  /* Byte 11 */
  Cid->ProdSN |= szCIDBuf[11] << 8;

  /* Byte 12 */
  Cid->ProdSN |= szCIDBuf[12];

  /* Byte 13 */
  Cid->Reserved1 |= (szCIDBuf[13] & 0xF0) >> 4;
  Cid->ManufactDate = (szCIDBuf[13] & 0x0F) << 8;

  /* Byte 14 */
  Cid->ManufactDate |= szCIDBuf[14];

  /* Byte 15 */
  Cid->CID_CRC = (szCIDBuf[15] & 0xFE) >> 1;
  Cid->Reserved2 = 1;
 }
 /* Return the reponse */
 return rvalue;
}

目前问题:

1. 初始化时有时可以通过,有时不行

2.在读时需要读取响应值0xfe但实际一直为0

3.在写时需要读取响应值为0x05,但实际也为0 或ff

请各位大神指点指点,搞了好久了,头大的每天。。。欢迎各位给予指导

参考文献:使用stm32cubemx生成源文件是需要的的库函数《stm32cube_fw_f1_v110.zip》里的范例eval

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-10-20 22:57:20 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-18 20:01

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表