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