在线时间68 小时
UID3090820
注册时间2015-1-9
NXP金币0
该用户从未签到
中级会员
 
- 积分
- 458
- 最后登录
- 2021-10-17
|
收到板子 ,改好调试接口后果断试了下光盘的DEMO 文件。。发现USB 代码不能用,SD代码 也不行。。。前阵子搞过KL25 把代码移植过来了。。。现在测试可以用了。。。我用的TF卡是 低速的卡。。。
void spiInit (SPI_MemMapPtr SPI,BOOLEAN bMode)
{
SIM_SCGC4 |= SIM_SCGC4_SPI0_MASK; /* 开启SPI0 */
/* CPOL = 0, SCK 为低有效 */
/* MSTR = 1, SPI 处于主模式 */
/* LSBF = 0, MSB (位7)在先 */
/* SPIE = 0, SPI 中断被禁止 */
/* CPHA = 0, SCK第一个时钟沿采样*/
SPI->C1 |= SPI_C1_SPE_MASK ; /* SPI使能 */
SPI->C1 &= ~(1 << SPI_C1_CPHA_SHIFT);
if(bMode == Master) { /* 主模式 */
SPI->C1 |= SPI_C1_MSTR_MASK;
} else { /* 从模式 */
SPI->C1 &= ~(1 << SPI_C1_MSTR_SHIFT);
}
SPI->BR = 0;//SPI_BR_SPPR(0) ; /* 时钟分频 */
}
#define MSD_CS_L FGPIOC_PCOR |= 1 << 4;
#define MSD_CS_H FGPIOC_PSOR |= 1 << 4;
下边是我用的sd驱动
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Global Variable ------------------------------------------------------------*/
u8 SD_Type=0;//SD卡的类型,为了支持高速卡而加入
u32 Mass_Block_Count;
u32 Mass_Block_Size;
u32 Mass_Memory_Size;
sMSD_CSD MSD_csd;
sMSD_CID MSD_cid;
u8 CSD_Tab[16];
u8 MSD_Reset ()
{
u8 val;
MSD_CS_H;
for ( val = 0; val < 12; val ++ )
Send_Byte( DUMMY );
val = SD_SendCommand(CMD0, 0, 0x95);
if ( val == 0x01 ) return 0; // 成功
else return 1; // 失败
}
/*******************************************************************************
* Function Name : MSD_Init
* Description : Initializes the MSD/SD communication.
* Input : None
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
extern void SD_SPI_Configuration(void);
/*******************************************************************************
* Function Name : MSD_WriteBlock
* Description : Writes a block on the MSD
* Input : - pBuffer : pointer to the buffer containing the data to be
* written on the MSD.
* - WriteAddr : address to write on.
* - NumByteToWrite: number of data to write
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_WriteBlock(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
u32 i = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
MSD_CS_L;
MSD_SendCmd(MSD_WRITE_BLOCK, WriteAddr, 0xFF);
if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
Send_Byte(DUMMY);
Send_Byte(0xFE);
for (i = 0; i < NumByteToWrite; i++)
{
Send_Byte(*pBuffer);
pBuffer++;
}
Send_Byte(0xff);
Send_Byte(0xff);
if (MSD_GetDataResponse() == MSD_DATA_OK)
{
rvalue = MSD_RESPONSE_NO_ERROR;
}
}
MSD_CS_H;
Send_Byte(DUMMY);
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_WriteBuffer
* Description : Writes many blocks on the MSD
* Input : - pBuffer : pointer to the buffer containing the data to be
* written on the MSD.
* - WriteAddr : address to write on.
* - NumByteToWrite: number of data to write
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_WriteBuffer(u8* pBuffer, u32 WriteAddr, u32 NumByteToWrite)
{
u32 i = 0;
u32 NbrOfBlock = 0;
u32 Offset = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
NbrOfBlock = NumByteToWrite / BLOCK_SIZE;
MSD_CS_L;
while (NbrOfBlock --)
{
MSD_SendCmd(MSD_WRITE_BLOCK, WriteAddr + Offset, 0xFF);
if (MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
return MSD_RESPONSE_FAILURE;
}
Send_Byte(DUMMY);
Send_Byte(MSD_START_DATA_SINGLE_BLOCK_WRITE);
for (i = 0; i < BLOCK_SIZE; i++)
{
Send_Byte(*pBuffer);
pBuffer++;
}
Offset += 512;
Send_Byte(0xff);
Send_Byte(0xff);
if (MSD_GetDataResponse() == MSD_DATA_OK)
{
rvalue = MSD_RESPONSE_NO_ERROR;
}
else
{
rvalue = MSD_RESPONSE_FAILURE;
}
}
MSD_CS_H;
Send_Byte(DUMMY);
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_ReadBlock
* Description : Reads a block of data from the MSD.
* Input : - pBuffer : pointer to the buffer that receives the data read
* from the MSD.
* - ReadAddr : MSD's internal address to read from.
* - NumByteToRead : number of bytes to read from the MSD.
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
{
u32 i = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
MSD_CS_L;
MSD_SendCmd(MSD_READ_SINGLE_BLOCK, ReadAddr, 0xFF);
if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
if(!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))
{
for(i = 0; i < NumByteToRead; i++)
{
*pBuffer = Send_Byte(0xff);
pBuffer++;
}
Send_Byte(0xff);
Send_Byte(0xff);
rvalue = MSD_RESPONSE_NO_ERROR;
}
}
MSD_CS_H;
Send_Byte(DUMMY);
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_ReadBuffer
* Description : Reads multiple block of data from the MSD.
* Input : - pBuffer : pointer to the buffer that receives the data read
* from the MSD.
* - ReadAddr : MSD's internal address to read from.
* - NumByteToRead : number of bytes to read from the MSD.
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_ReadBuffer(u8* pBuffer, u32 ReadAddr, u32 NumByteToRead)
{
u32 i = 0;
u32 NbrOfBlock = 0;
u32 Offset = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
NbrOfBlock = NumByteToRead / BLOCK_SIZE;
MSD_CS_L;
while (NbrOfBlock --)
{
MSD_SendCmd (MSD_READ_SINGLE_BLOCK, ReadAddr + Offset, 0xFF);
if (MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
return MSD_RESPONSE_FAILURE;
}
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))
{
for (i = 0; i < BLOCK_SIZE; i++)
{
*pBuffer = Send_Byte(0xff);
pBuffer++;
}
Offset += 512;
Send_Byte(0xff);
Send_Byte(0xff);
rvalue = MSD_RESPONSE_NO_ERROR;
}
else
{
rvalue = MSD_RESPONSE_FAILURE;
}
}
MSD_CS_H;
Send_Byte(DUMMY);
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_GetCSDRegister
* Description : Read the CSD card register.
* Reading the contents of the CSD register in SPI mode
* is a simple read-block transaction.
* Input : - MSD_csd: pointer on an SCD register structure
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_GetCSDRegister(sMSD_CSD* MSD_csd)
{
u32 i = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
u8 CSD_Tab[16];
/* MSD chip select low */
MSD_CS_L;
/* Send CMD9 (CSD register) or CMD10(CSD register) */
MSD_SendCmd(MSD_SEND_CSD, 0, 0xFF);
/* Wait for response in the R1 format (0x00 is no errors) */
if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))
{
for (i = 0; i < 16; i++)
{
/* Store CSD register value on CSD_Tab */
CSD_Tab[i] = Send_Byte(0xff);
}
}
/* Get CRC bytes (not really needed by us, but required by MSD) */
Send_Byte(DUMMY);
Send_Byte(DUMMY);
/* Set response value to success */
rvalue = MSD_RESPONSE_NO_ERROR;
}
/* MSD chip select high */
MSD_CS_H;
/* Send dummy byte: 8 Clock pulses of delay */
Send_Byte(DUMMY);
/* Byte 0 */
MSD_csd->CSDStruct = (CSD_Tab[0] & 0xC0) >> 6;
MSD_csd->SysSpecVersion = (CSD_Tab[0] & 0x3C) >> 2;
MSD_csd->Reserved1 = CSD_Tab[0] & 0x03;
/* Byte 1 */
MSD_csd->TAAC = CSD_Tab[1] ;
/* Byte 2 */
MSD_csd->NSAC = CSD_Tab[2];
/* Byte 3 */
MSD_csd->MaxBusClkFrec = CSD_Tab[3];
/* Byte 4 */
MSD_csd->CardComdClasses = CSD_Tab[4] << 4;
/* Byte 5 */
MSD_csd->CardComdClasses |= (CSD_Tab[5] & 0xF0) >> 4;
MSD_csd->RdBlockLen = CSD_Tab[5] & 0x0F;
/* Byte 6 */
MSD_csd->PartBlockRead = (CSD_Tab[6] & 0x80) >> 7;
MSD_csd->WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6;
MSD_csd->RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5;
MSD_csd->DSRImpl = (CSD_Tab[6] & 0x10) >> 4;
MSD_csd->Reserved2 = 0; /* Reserved */
MSD_csd->DeviceSize = (CSD_Tab[6] & 0x03) << 10;
/* Byte 7 */
MSD_csd->DeviceSize |= (CSD_Tab[7]) << 2;
/* Byte 8 */
MSD_csd->DeviceSize |= (CSD_Tab[8] & 0xC0) >> 6;
MSD_csd->MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3;
MSD_csd->MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07);
/* Byte 9 */
MSD_csd->MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5;
MSD_csd->MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2;
MSD_csd->DeviceSizeMul = (CSD_Tab[9] & 0x03) << 1;
/* Byte 10 */
MSD_csd->DeviceSizeMul |= (CSD_Tab[10] & 0x80) >> 7;
MSD_csd->EraseGrSize = (CSD_Tab[10] & 0x7C) >> 2;
MSD_csd->EraseGrMul = (CSD_Tab[10] & 0x03) << 3;
/* Byte 11 */
MSD_csd->EraseGrMul |= (CSD_Tab[11] & 0xE0) >> 5;
MSD_csd->WrProtectGrSize = (CSD_Tab[11] & 0x1F);
/* Byte 12 */
MSD_csd->WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7;
MSD_csd->ManDeflECC = (CSD_Tab[12] & 0x60) >> 5;
MSD_csd->WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2;
MSD_csd->MaxWrBlockLen = (CSD_Tab[12] & 0x03) << 2;
/* Byte 13 */
MSD_csd->MaxWrBlockLen |= (CSD_Tab[13] & 0xc0) >> 6;
MSD_csd->WriteBlockPaPartial = (CSD_Tab[13] & 0x20) >> 5;
MSD_csd->Reserved3 = 0;
MSD_csd->ContentProtectAppli = (CSD_Tab[13] & 0x01);
/* Byte 14 */
MSD_csd->FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7;
MSD_csd->CopyFlag = (CSD_Tab[14] & 0x40) >> 6;
MSD_csd->PermWrProtect = (CSD_Tab[14] & 0x20) >> 5;
MSD_csd->TempWrProtect = (CSD_Tab[14] & 0x10) >> 4;
MSD_csd->FileFormat = (CSD_Tab[14] & 0x0C) >> 2;
MSD_csd->ECC = (CSD_Tab[14] & 0x03);
/* Byte 15 */
MSD_csd->CRC_Check = (CSD_Tab[15] & 0xFE) >> 1;
MSD_csd->Reserved4 = 1;
/* Return the reponse */
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_GetCIDRegister
* Description : Read the CID card register.
* Reading the contents of the CID register in SPI mode
* is a simple read-block transaction.
* Input : - MSD_cid: pointer on an CID register structure
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_GetCIDRegister(sMSD_CID* MSD_cid)
{
u32 i = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
u8 CID_Tab[16];
/* MSD chip select low */
MSD_CS_L;
/* Send CMD10 (CID register) */
MSD_SendCmd(MSD_SEND_CID, 0, 0xFF);
/* Wait for response in the R1 format (0x00 is no errors) */
if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
if (!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))
{
/* Store CID register value on CID_Tab */
for (i = 0; i < 16; i++)
{
CID_Tab[i] = Send_Byte(0xff);
}
}
/* Get CRC bytes (not really needed by us, but required by MSD) */
Send_Byte(DUMMY);
Send_Byte(DUMMY);
/* Set response value to success */
rvalue = MSD_RESPONSE_NO_ERROR;
}
/* MSD chip select high */
MSD_CS_H;
/* Send dummy byte: 8 Clock pulses of delay */
Send_Byte(DUMMY);
/* Byte 0 */
MSD_cid->ManufacturerID = CID_Tab[0];
/* Byte 1 */
MSD_cid->OEM_AppliID = CID_Tab[1] << 8;
/* Byte 2 */
MSD_cid->OEM_AppliID |= CID_Tab[2];
/* Byte 3 */
MSD_cid->ProdName1 = CID_Tab[3] << 24;
/* Byte 4 */
MSD_cid->ProdName1 |= CID_Tab[4] << 16;
/* Byte 5 */
MSD_cid->ProdName1 |= CID_Tab[5] << 8;
/* Byte 6 */
MSD_cid->ProdName1 |= CID_Tab[6];
/* Byte 7 */
MSD_cid->ProdName2 = CID_Tab[7];
/* Byte 8 */
MSD_cid->ProdRev = CID_Tab[8];
/* Byte 9 */
MSD_cid->ProdSN = CID_Tab[9] << 24;
/* Byte 10 */
MSD_cid->ProdSN |= CID_Tab[10] << 16;
/* Byte 11 */
MSD_cid->ProdSN |= CID_Tab[11] << 8;
/* Byte 12 */
MSD_cid->ProdSN |= CID_Tab[12];
/* Byte 13 */
MSD_cid->Reserved1 |= (CID_Tab[13] & 0xF0) >> 4;
/* Byte 14 */
MSD_cid->ManufactDate = (CID_Tab[13] & 0x0F) << 8;
/* Byte 15 */
MSD_cid->ManufactDate |= CID_Tab[14];
/* Byte 16 */
MSD_cid->CRC_Check = (CID_Tab[15] & 0xFE) >> 1;
MSD_cid->Reserved2 = 1;
/* Return the reponse */
return rvalue;
}
/*******************************************************************************
* Function Name : MSD_SendCmd
* Description : Send 5 bytes command to the MSD card.
* Input : - Cmd: the user expected command to send to MSD card
* - Arg: the command argument
* - Crc: the CRC
* Output : None
* Return : None
*******************************************************************************/
void MSD_SendCmd(u8 Cmd, u32 Arg, u8 Crc)
{
u32 i = 0x00;
u8 Frame[6];
/* Construct byte1 */
Frame[0] = (Cmd | 0x40);
/* Construct byte2 */
Frame[1] = (u8)(Arg >> 24);
/* Construct byte3 */
Frame[2] = (u8)(Arg >> 16);
/* Construct byte4 */
Frame[3] = (u8)(Arg >> 8);
/* Construct byte5 */
Frame[4] = (u8)(Arg);
/* Construct CRC: byte6 */
Frame[5] = (Crc);
/* Send the Cmd bytes */
for (i = 0; i < 6; i++)
{
Send_Byte(Frame[i]);
}
}
/*******************************************************************************
* Function Name : MSD_GetDataResponse
* Description : Get MSD card data response.
* Input : None
* Output : None
* Return : The MSD status: Read data response xxx0<status>1
* - status 010: Data accecpted
* - status 101: Data rejected due to a crc error
* - status 110: Data rejected due to a Write error.
* - status 111: Data rejected due to other error.
*******************************************************************************/
u8 MSD_GetDataResponse(void)
{
u32 i = 0;
u8 response, rvalue;
while (i <= 64)
{
/* Read resonse */
response = Send_Byte(0xff);
/* Mask unused bits */
response &= 0x1F;
switch (response)
{
case MSD_DATA_OK:
{
rvalue = MSD_DATA_OK;
break;
}
case MSD_DATA_CRC_ERROR:
return MSD_DATA_CRC_ERROR;
case MSD_DATA_WRITE_ERROR:
return MSD_DATA_WRITE_ERROR;
default:
{
rvalue = MSD_DATA_OTHER_ERROR;
break;
}
}
/* Exit loop in case of data ok */
if (rvalue == MSD_DATA_OK)
break;
/* Increment loop counter */
i++;
}
/* Wait null data */
while (Send_Byte(0xff) == 0);
/* Return response */
return response;
}
/*******************************************************************************
* Function Name : MSD_GetResponse
* Description : Returns the MSD response.
* Input : None
* Output : None
* Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed
* - MSD_RESPONSE_NO_ERROR: Sequence succeed
*******************************************************************************/
u8 MSD_GetResponse(u8 Response)
{
u32 Count = 0xFFF;
while((Send_Byte(0xff) != Response) && Count)
{
Count--;
}
if (Count == 0) return MSD_RESPONSE_FAILURE;
else return MSD_RESPONSE_NO_ERROR;
}
/*******************************************************************************
* Function Name : MSD_GetStatus
* Description : Returns the MSD status.
* Input : None
* Output : None
* Return : The MSD status.
*******************************************************************************/
u16 MSD_GetStatus(void)
{
u16 Status = 0;
/* MSD chip select low */
MSD_CS_L;
/* Send CMD13 (MSD_SEND_STATUS) to get MSD status */
MSD_SendCmd(MSD_SEND_STATUS, 0, 0xFF);
Status = Send_Byte(0xff);
Status |= (u16)(Send_Byte(0xff) << 8);
/* MSD chip select high */
MSD_CS_H;
/* Send dummy byte 0xFF */
Send_Byte(DUMMY);
return Status;
}
/*******************************************************************************
* Function Name : Get_Medium_Characteristics.
* Description : Get the microSD card size.
* Input : None.
* Output : None.
* Return : None.
*******************************************************************************/
void Get_Medium_Characteristics(void)
{
u32 temp1 = 0;
u32 temp2 = 0;
MSD_GetCSDRegister(&MSD_csd);
MSD_GetCIDRegister(&MSD_cid);
temp1 = MSD_csd.DeviceSize + 1;
temp2 = 1 << (MSD_csd.DeviceSizeMul + 2);
Mass_Block_Count = temp1 * temp2;
Mass_Block_Size = 1 << MSD_csd.RdBlockLen;
Mass_Memory_Size = (Mass_Block_Count * Mass_Block_Size);
}
/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/
//>>>>>>>>>>>>>>>>>>>>>>>>>>>start of code<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//整理者: Sasukewxt
//时间 : 2011/02/27
//说明 : 以下加入的代码是为了使系统支持高速SDHC卡
//------------------------------------------------
/*******************************************************************************
* 本文件为SPI操作SD卡的底层驱动文件
* 包括SPI模块及相关IO的初始化,SPI读写SD卡(写指令,读数据等)
*******************************************************************************/
/*******************************************************************************
* Function Name : SD_SendCommand
* Description : 向SD卡发送一个命令
* Input : u8 cmd 命令
* u32 arg 命令参数
* u8 crc crc校验值
* Output : None
* Return : u8 r1 SD卡返回的响应
*******************************************************************************/
u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc)
{
unsigned char r1;
unsigned char Retry = 0;
Send_Byte(0xff);
//片选端置低,选中SD卡
MSD_CS_L;
//发送
Send_Byte(cmd | 0x40); //分别写入命令
Send_Byte(arg >> 24);
Send_Byte(arg >> 16);
Send_Byte(arg >> 8);
Send_Byte(arg);
Send_Byte(crc);
//等待响应,或超时退出
while((r1 = Send_Byte(0xFF))==0xFF)
{
Retry++;
if(Retry > RE_TRY_CNT)break;
}
//关闭片选
MSD_CS_H;
//在总线上额外增加8个时钟,让SD卡完成剩下的工作
Send_Byte(0xFF);
//返回状态值
return r1;
}
/*******************************************************************************
* Function Name : SD_SendCommand_NoDeassert
* Description : 向SD卡发送一个命令(结束是不失能片选,还有后续数据传来)
* Input : u8 cmd 命令
* u32 arg 命令参数
* u8 crc crc校验值
* Output : None
* Return : u8 r1 SD卡返回的响应
*******************************************************************************/
u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc)
{
unsigned char r1;
unsigned char Retry = 0;
Send_Byte(0xff);
//片选端置低,选中SD卡
MSD_CS_L;
//发送
Send_Byte(cmd | 0x40); //分别写入命令
Send_Byte(arg >> 24);
Send_Byte(arg >> 16);
Send_Byte(arg >> 8);
Send_Byte(arg);
Send_Byte(crc);
//等待响应,或超时退出
while((r1 = Send_Byte(0xFF))==0xFF)
{
Retry++;
if(Retry > RE_TRY_CNT)break;
}
//返回响应值
return r1;
}
/*******************************************************************************
* Function Name : SDHC_Init
* Description : 初始化SDHC卡
* Input : None
* Output : None
* Return : u8
* 0:NO_ERR
* 1:TIME_OUT
* 99:NO_CARD
*******************************************************************************/
u8 SDHC_Init(void)// 初始化高速SD卡,由MSD_Init调用
{
u16 i; // 用来循环计数
u8 r1; // 存放SD卡的返回值
u16 retry; // 用来进行超时计数
u8 buff[6];
MSD_CS_L;
for(i=0;i<0x2f00;i++);
for(i=0;i<15;i++)
{
Send_Byte(0xFF);
}
retry = 0;
do
{
r1 = SD_SendCommand(CMD0, 0, 0x95);
retry++;
} while((r1 != 0x01) && (retry<RE_TRY_CNT));
if(retry==RE_TRY_CNT) return 1; //超时返回1
r1 = SD_SendCommand_NoDeassert(8, 0x1aa, 0x87);
if(r1 == 0x05)
{
//设置卡类型为SDV1.0,如果后面检测到为MMC卡,再修改为MMC
SD_Type = SD_TYPE_V1;
MSD_CS_H;
Send_Byte(0xFF);
retry = 0;
do
{
r1 = SD_SendCommand(CMD55, 0, 0);
if(r1 != 0x01)return r1;
//得到正确响应后,发ACMD41,应得到返回值0x00,否则重试200次
r1 = SD_SendCommand(ACMD41, 0, 0);
retry++;
myDelay(200);
} while((r1!=0x00) && (retry<RE_TRY_CNT));
// 判断是超时还是得到正确回应
// 若有回应:是SD卡;没有回应:是MMC卡
if(retry==RE_TRY_CNT)
{
retry = 0;
//发送MMC卡初始化命令(没有测试)
do
{
r1 = SD_SendCommand(1, 0, 0);
retry++;
}while((r1!=0x00)&& (retry<RE_TRY_CNT));
if(retry==RE_TRY_CNT)return 1; //MMC卡初始化超时
//写入卡类型
SD_Type = SD_TYPE_MMC;
}
Send_Byte(0xFF);
r1 = SD_SendCommand(CMD59, 0, 0x95);
if(r1 != 0x00)return r1; //命令错误,返回r1
r1 = SD_SendCommand(CMD16, 512, 0x95);
if(r1 != 0x00)return r1; //命令错误,返回r1
}
//SD卡为V1.0版本的初始化结束
//下面是V2.0卡的初始化
//其中需要读取OCR数据,判断是SD2.0还是SD2.0HC卡
else if(r1 == 0x01)
{
//V2.0的卡,CMD8命令后会传回4字节的数据,要跳过再结束本命令
buff[0] = Send_Byte(0xFF); //should be 0x00
buff[1] = Send_Byte(0xFF); //should be 0x00
buff[2] = Send_Byte(0xFF); //should be 0x01
buff[3] = Send_Byte(0xFF); //should be 0xAA
MSD_CS_H;
Send_Byte(0xFF);//the next 8 clocks
//发卡初始化指令CMD55+ACMD41
do
{
r1 = SD_SendCommand(CMD55, 0, 0);
if(r1!=0x01)return r1;
r1 = SD_SendCommand(ACMD41, 0x40000000, 0);
if(retry>RE_TRY_CNT)return r1; //超时则返回r1状态
} while(r1!=0);
//初始化指令发送完成,接下来获取OCR信息
//-----------鉴别SD2.0卡版本开始-----------
r1 = SD_SendCommand_NoDeassert(CMD58, 0, 0);
if(r1!=0x00)return r1; //如果命令没有返回正确应答,直接退出,返回应答
//读OCR指令发出后,紧接着是4字节的OCR信息
buff[0] = Send_Byte(0xFF);
buff[1] = Send_Byte(0xFF);
buff[2] = Send_Byte(0xFF);
buff[3] = Send_Byte(0xFF);
MSD_CS_H;
Send_Byte(0xFF);
//检查接收到的OCR中的bit30位(CCS),确定其为SD2.0还是SDHC
//如果CCS=1:SDHC CCS=0:SD2.0
if(buff[0]&0x40)SD_Type = SD_TYPE_V2HC; //检查CCS
else SD_Type = SD_TYPE_V2;
}
return r1;
}
//获取SD卡的CSD信息,包括容量和速度信息
//输入:u8 *cid_data(存放CID的内存,至少16Byte)
//返回值: 0:NO_ERR
// 1:错误
u8 SD_GetCSD(u8 *csd_data)
{
u32 i = 0;
u8 rvalue = MSD_RESPONSE_FAILURE;
MSD_CS_L;
MSD_SendCmd(MSD_SEND_CSD, 0, 0xFF);
if(!MSD_GetResponse(MSD_RESPONSE_NO_ERROR))
{
if(!MSD_GetResponse(MSD_START_DATA_SINGLE_BLOCK_READ))
{
for (i = 0; i < 16; i++)
{
CSD_Tab[i] = Send_Byte(0xff);
}
}
Send_Byte(DUMMY);
Send_Byte(DUMMY);
rvalue = MSD_RESPONSE_NO_ERROR;
}
MSD_CS_H;
Send_Byte(DUMMY);
return rvalue;
}
//获取SD卡的总扇区数(扇区数)
//返回值:0: 取容量出错
//其他:SD卡的容量(扇区数/512字节)
//每扇区的字节数必为512,因为如果不是512,则初始化不能通过.
u32 SD_GetSectorCount(void)
{
u32 Capacity;
u8 n;
u16 csize;
u8* csd = CSD_Tab;
if(SD_GetCSD(csd)!=0) return 0;
if((csd[0]&0xC0)==0x40) //V2.00的卡
{
csize = csd[9] + ((u16)csd[8] << 8) + 1;
Capacity = (u32)csize << 10; //得到扇区数
}
else//V1.XX的卡
{
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
csize = (csd[8] >> 6) + ((u16)csd[7] << 2) + ((u16)(csd[6] & 3) << 10) + 1;
Capacity= (u32)csize << (n - 9);//得到扇区数
}
return Capacity;
}
下边是测试函数
FATFS fatfs;
FIL fil;
DIR dir;
FATFS *pfs;
FILINFO f_info;
SDHC_Init();
pfs = &fatfs;
f_mount(&fatfs,&flag,0);
res = f_opendir(&dir,"");
res = f_readdir(&dir,&f_info);
f_open(&fil,f_info.fname,FA_OPEN_EXISTING |FA_READ);
f_read(&fil,Buffer,512,&clust);
|
|