查看: 10949|回复: 30

[分享] 【YL-KL26Z试用】+SPI SD驱动搞好了。。发帖庆贺一下、。。

[复制链接]

该用户从未签到

11

主题

126

帖子

0

中级会员

Rank: 3Rank: 3

积分
458
最后登录
2021-10-17
发表于 2015-3-19 17:30:29 | 显示全部楼层 |阅读模式
收到板子 ,改好调试接口后果断试了下光盘的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);
回复

使用道具 举报

该用户从未签到

11

主题

126

帖子

0

中级会员

Rank: 3Rank: 3

积分
458
最后登录
2021-10-17
 楼主| 发表于 2015-3-19 17:35:26 | 显示全部楼层
QQ截图20150319173235.png QQ截图20150319173300.png QQ截图20150319173319.png QQ截图20150319173340.png QQ截图20150319173413.png
回复 支持 反对

使用道具 举报

该用户从未签到

11

主题

126

帖子

0

中级会员

Rank: 3Rank: 3

积分
458
最后登录
2021-10-17
 楼主| 发表于 2015-3-19 17:39:36 | 显示全部楼层
FSL_TICS_ZJJ 发表于 2015-3-19 17:33
楼主这个经验贴非常好,赞!
是否可以直接把修改好的工程也分享出来呢。 ...

可以,正在上传。。。 Demo_SD_wav.rar (2.07 MB, 下载次数: 111)
回复 支持 反对

使用道具 举报

该用户从未签到

145

主题

4926

帖子

0

金牌会员

Rank: 6Rank: 6

积分
9267
最后登录
1970-1-1
发表于 2015-3-19 17:33:52 | 显示全部楼层
楼主这个经验贴非常好,赞!
是否可以直接把修改好的工程也分享出来呢。
回复 支持 反对

使用道具 举报

该用户从未签到

145

主题

4926

帖子

0

金牌会员

Rank: 6Rank: 6

积分
9267
最后登录
1970-1-1
发表于 2015-3-19 17:35:21 | 显示全部楼层
非常感谢你关于Kinetis的经验分享!
回复 支持 反对

使用道具 举报

该用户从未签到

11

主题

126

帖子

0

中级会员

Rank: 3Rank: 3

积分
458
最后登录
2021-10-17
 楼主| 发表于 2015-3-19 17:40:16 | 显示全部楼层
文档很乱,大家凑活着看。。呵呵。。这可是新鲜出炉的。。。
回复 支持 反对

使用道具 举报

该用户从未签到

11

主题

126

帖子

0

中级会员

Rank: 3Rank: 3

积分
458
最后登录
2021-10-17
 楼主| 发表于 2015-3-19 17:40:55 | 显示全部楼层
FSL_TICS_ZJJ 发表于 2015-3-19 17:35
非常感谢你关于Kinetis的经验分享!

demo 里的USB 怎么不好用。。程序烧写进去,电脑没有显示硬件连接。。。。
回复 支持 反对

使用道具 举报

该用户从未签到

145

主题

4926

帖子

0

金牌会员

Rank: 6Rank: 6

积分
9267
最后登录
1970-1-1
发表于 2015-3-23 09:50:42 | 显示全部楼层
FlyMyself 发表于 2015-3-19 17:40
demo 里的USB 怎么不好用。。程序烧写进去,电脑没有显示硬件连接。。。。 ...

你烧的是哪个USB例程?
回复 支持 反对

使用道具 举报

该用户从未签到

11

主题

126

帖子

0

中级会员

Rank: 3Rank: 3

积分
458
最后登录
2021-10-17
 楼主| 发表于 2015-3-23 11:12:46 | 显示全部楼层
FSL_TICS_ZJJ 发表于 2015-3-23 09:50
你烧的是哪个USB例程?

先谢了,我有给折腾好了。。原来我的默认装的是别的驱动。着了老半天才对照出来,今天换了驱动已经好了,,。。
回复 支持 反对

使用道具 举报

该用户从未签到

145

主题

4926

帖子

0

金牌会员

Rank: 6Rank: 6

积分
9267
最后登录
1970-1-1
发表于 2015-3-23 11:14:22 | 显示全部楼层
FlyMyself 发表于 2015-3-23 11:12
先谢了,我有给折腾好了。。原来我的默认装的是别的驱动。着了老半天才对照出来,今天换了驱动已经好了, ...

问题解决了就好,后续如果还有问题,欢迎继续发帖交流。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|恩智浦技术社区

GMT+8, 2025-7-28 07:55 , Processed in 0.109848 second(s), 30 queries , MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

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