⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sd.c

📁 增强型51单片机fs7821sd卡、mmc卡读写程序
💻 C
📖 第 1 页 / 共 3 页
字号:
                continue;
        }
        else
            return STATUS_SUCCESS;
    }
    return STATUS_FLASH_ERROR;
}

STATUS SdSendAppCmd(BYTE AppCmdIndex, PBYTE AppCmdBuf)
{
    STATUS Status;
    int RetryCount;
    BYTE CmdBuf55[MAX_CMD_LEN]; // for APP_CMD (CMD55)
    
    for(RetryCount = 0; RetryCount < 3; RetryCount++)
    {
        *((UINT32 *)(&CmdBuf55[1])) = RCA;
        
        Status = SdSendCmd(APP_CMD, CmdBuf55);
        
        if(Status != STATUS_SUCCESS)
            continue;
        
        Status = SdSendCmd(AppCmdIndex, AppCmdBuf);
        
        if(Status != STATUS_SUCCESS)
            continue;
        else
            return STATUS_SUCCESS;
    }
    return STATUS_FLASH_ERROR;
}

//----------------------------------------------------------------------------
STATUS SdChangeBusWidth()
{
    STATUS Status;
    BYTE RegValue;
  
    *((UINT32 *)(&SdCmdBuf[1])) = RCA | BUS_WIDTH_4BIT;

    Status = SdSendAppCmd(SET_BUS_WIDTH, SdCmdBuf);
    
    if(Status == STATUS_SUCCESS)
    {
        RegValue = CSRRead(SD_BASE + SD_CLK_CTRL);
		//RegValue |= SD_CLK_NIBBLE;
		RegValue |= 0x10;
        CSRWrite(SD_BASE + SD_CLK_CTRL, RegValue);
    }
    return Status;   
}	

//----------------------------------------------------------------------------
STATUS SdReset()
{
    STATUS Status;
    int i;

    RCA = 0;
    
    SdLoClk();
    Delay(5);  // Wait 5ms for stable clock
    for(i = 1; i <= 4; i++)
        SdCmdBuf[i] = 0;
    Status = SdSendCmd(GO_IDLE_STATE, SdCmdBuf);
    return Status;
}

//----------------------------------------------------------------------------
STATUS SdDetect()
{
    STATUS Status;
    UINT16 RetryCount;

    *((UINT32 *)(&SdCmdBuf[1])) = OPERATION_VOL_RANGE;
    
    Status = SdSendAppCmd(SD_SEND_OP_COND, SdCmdBuf);
    
    if(Status == STATUS_SUCCESS)
    {
        CardType = CARD_SD;	
 
        // Check if card power-up operation finished
        if(SdRespBuf[1] & CARD_PWRUP_FINISH)
            return STATUS_SUCCESS;

        // Wait until card power-up operation finished
        for(RetryCount = 0; RetryCount < 500; RetryCount++)
        {
            *((UINT32 *)(&SdCmdBuf[1])) = OPERATION_VOL_RANGE;
            
            Status = SdSendAppCmd(SD_SEND_OP_COND, SdCmdBuf);
            
            if(Status != STATUS_SUCCESS)
                continue;
                
            if(SdRespBuf[1] & CARD_PWRUP_FINISH)
                return STATUS_SUCCESS;           
        }
        return STATUS_FLASH_ERROR;
    }
    else
    {
        CardType = CARD_MMC;   	
        
        // Wait until card power-up operation finished
        for(RetryCount = 0; RetryCount < 500; RetryCount++)
        {
            *((UINT32 *)(&SdCmdBuf[1])) = OPERATION_VOL_RANGE;
    
            Status = SdSendCmd(SEND_OP_COND, SdCmdBuf);

            if(Status != STATUS_SUCCESS)
                continue;
                
            if(SdRespBuf[1] & CARD_PWRUP_FINISH)
                return STATUS_SUCCESS;           
        }
        return STATUS_FLASH_ERROR;
    }
}	


//----------------------------------------------------------------------------
STATUS SdGoIdentifyState()
{
    STATUS Status;
    int i;

    for(i = 1; i <= 4; i++)
        SdCmdBuf[i] = 0;
    Status = SdSendCmd(ALL_SEND_CID, SdCmdBuf);
    return Status;
}

//--------------------------------------------------------------------
STATUS SdGoStandbyState()
{
    STATUS Status;
    int i;
  	
    if(CardType == CARD_SD)
    {
        for(i = 1; i <= 4; i++)
            SdCmdBuf[i] = 0;
    }
    else
    {
        RCA = 0x00010000;	
        *((UINT32 *)(&SdCmdBuf[1])) = RCA;
    }

    Status = SdSendCmd(SEND_RELATIVE_ADDR, SdCmdBuf);

    if(CardType == CARD_SD)
        RCA = *((UINT32 *)(&SdRespBuf[1])) & 0xffff0000;

    return STATUS_SUCCESS;
    
    // SD and MMC adopt different ways to set their relative card 
    // address. That is, they have different response to CMD3 
    // (SEND_RELATIVE_ADDR).
    //
    // According to SD Standard Version 1.01 page 25:
    //     the host issues CMD3 (SEND_RELATIVE_ADDR) asks the 
    //     card to publish a new relative card address (RCA).
    //
    // According to MMC Standard Version 3.1 page 24:
    //     the host issues CMD3 (SEND_RELATIVE_ADDR) to assign
    //     to this card a relative card address (RCA).
    //
    // This means : when host send CMD3 to SD, it is SD telling host
    // its new address, that is, SD is the one giving the new address
    // (and host decides whether to accept it). Meanwhile, when host 
    // sends CMD3 to MMC, it is host assigning the card a new address,
    // that is, host is the one decides the address (and MMC must 
    // accept it).
    // 
    // For SD, CMD3 has a response of type R6, which contains address
    // value returns by SD. For MMC, CMD3 has a response of type R1, 
    // which tells host if MMC accepts the address or error happens.
}

//--------------------------------------------------------------------
STATUS SdReadCSD()			
{
    STATUS Status;	
    BYTE READ_BL_LEN;
    BYTE C_SIZE_MUTI;
    UINT32 C_SIZE;
     
    *((UINT32 *)(&SdCmdBuf[1])) = RCA;
    
    Status = SdSendCmd(SEND_CSD, SdCmdBuf);
    if(Status != STATUS_SUCCESS)
        return Status;  

    READ_BL_LEN = SdRespBuf[6] & 0xf;
    C_SIZE = SdRespBuf[7] & 0x3;
    C_SIZE <<= 8;
    C_SIZE |= SdRespBuf[8];
    C_SIZE <<= 2;
    C_SIZE |= (SdRespBuf[9] >> 6);
    C_SIZE_MUTI = SdRespBuf[10] & 0x3;
    C_SIZE_MUTI <<= 1;
    C_SIZE_MUTI |= (SdRespBuf[11] >> 7);
  
    SdAvailableBlocks = (UINT32)((C_SIZE + 1) << (C_SIZE_MUTI + 2 + 
                             (READ_BL_LEN - BYTES_PER_SECTOR_SHIFT)));
    SdAvailableBlocks -= 1;  

    return STATUS_SUCCESS;
}	

//----------------------------------------------------------------------------
STATUS SdGoTransferState()
{
    STATUS Status;
    BYTE CurrentState , RegValue;
  	
    *((UINT32 *)(&SdCmdBuf[1])) = RCA;
    Status = SdSendCmd(SELECT_CARD, SdCmdBuf);
    if(Status != STATUS_SUCCESS)
        return Status;  

    *((UINT32 *)(&SdCmdBuf[1])) = RCA;
    Status = SdSendCmd(SEND_STATUS, SdCmdBuf);
    if(Status != STATUS_SUCCESS)
        return Status;  

    CurrentState = (SdRespBuf[3] >> 1) & 0x0F;
    if(CurrentState == TRANSFER_STATE)
    {
        SdHiClk();
        if(CardType == CARD_SD)
        {
            Status = SdChangeBusWidth();
            if(Status != STATUS_SUCCESS)
                return Status;
        }
        else // MMC 3.1
        {
            RegValue = CSRRead(SD_BASE + SD_CLK_CTRL);
            RegValue &= ~SD_CLK_NIBBLE;
            CSRWrite(SD_BASE + SD_CLK_CTRL, RegValue);
        }
    }   
    else
        return STATUS_FLASH_ERROR;
    
    return STATUS_SUCCESS;
}	

//----------------------------------------------------------------------------
//  Description:
//    Stop the read or write command
//----------------------------------------------------------------------------
STATUS SdStopCmd()
{
    STATUS Status;
    BYTE RegValue;
    int i;

    RegValue = CSRRead(SD_BASE + SD_CLK_CTRL);
    RegValue &= ~SD_CLK_AUTO_DIS;
    CSRWrite(SD_BASE + SD_CLK_CTRL, RegValue);

    for(i = 1; i <= 4; i++)
        SdCmdBuf[i] = 0;
    Status = SdSendCmd(STOP_TRANS, SdCmdBuf);
    if(Status != STATUS_SUCCESS)
        return Status;
 
    SdWaitCard();
      
    return STATUS_SUCCESS; 
}
//----------------------------------------------------------------------------
STATUS SdWaitCmd()
{
  CmdTimer = SD_CMD_TIMEOUT;	
  while ((!(CSRRead(SD_BASE + SD_IE) & SD_COMPLETE)) && CmdTimer);
  // Clear command complete INT.	
  CSRWrite(SD_BASE + SD_IE, ~SD_COMPLETE);

  if (CmdTimer)
    return STATUS_SUCCESS;
  else 
  {
    //DebugShow("<SD> Wait TimeOut! Cmd = %02bx\r\n", CmdBuf[0]);
    SdCtrlReset();
    return STATUS_FLASH_ERROR;
  }
}	
//--------------------------------------------------------------------
// Read first sector of data from SD/MMC
//--------------------------------------------------------------------
STATUS SdReadOneSector()
{
    STATUS Status;
    int RetryCount1 , RetryCount2;
    bool ReadyForData;

    if(SectorStart > SdAvailableBlocks)
        return STATUS_PARAM_ERROR;

    SdWaitCard();
  
    for(RetryCount1 = 0; RetryCount1 < 5; RetryCount1++)
    {
        ReadyForData = false;
        for(RetryCount2 = 0; RetryCount2 < 20; RetryCount2++)  //读取SD/MMC卡的状态,SD/MMC卡没准备好发送数据则循环重试20次
        {
            *((UINT32 *)(&SdCmdBuf[1])) = RCA;
            Status = SdSendCmd(SEND_STATUS, SdCmdBuf);	//发送带一个response的命令,以得到当前SD/MMC卡的状态
            if(Status != STATUS_SUCCESS)
                continue;  
            if(SdRespBuf[3] & 0x01) // READY_FOR_DATA in Card Status
            {
                ReadyForData = true;
                break;
            }
        }        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -