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

📄 sd.c

📁 可以在ARM单片机上移植的SD卡的驱动程序的原码
💻 C
📖 第 1 页 / 共 5 页
字号:
    if(SD_WriteCmd(ptSDCard, CMD38, CMD38_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_ERASE_CMD38_ERROR;
    }

    /* Check for an error, like a misaligned write */
    if(g_ucResponse[0] != 0)
    {
        return SD_ERASE_RESPONSE_ERROR3 | (g_ucResponse[0])<<8;
    }
    
    /* Signal that the card may be busy, so any subsequent commands
    should wait for the busy signalling to end (indicated by a
    nonzero response). */
    ptSDCard->bBusyFlag = 1;
    if ((result = SD_WaitNotBusy( ptSDCard)) != SD_SUCCESS)
    {
    	return result;
    }
    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    This function is used to set write protect blocks.
//  Author:         Benjamin.Wang
//  Note:           This function will be supported in the future.
/*****************************************************************************/
PUBLIC uint32 SD_SetWriteProtect(       // return status. SD_SUCCESS - success
    SD_CARD_T* ptSDCard,     // the card vector
    uint32 uiBlocknum           // the write protect block num
    )
{
    //Optional
    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    This function is used to clear write protect blocks.
//  Author:         Benjamin.Wang
//  Note:           This function will be supported in the future.
/*****************************************************************************/
PUBLIC uint32 SD_ClrWriteProtect(       // return status. SD_SUCCESS - success
    SD_CARD_T* ptSDCard,        // the card vector
    uint32 uiBlocknum               // the block num
    )
{
    //Optional
    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    This function is used to know whether the block is write protected.
//  Author:         Benjamin.Wang
//  Note:           This function will be supported in the future.
/*****************************************************************************/
PUBLIC BOOLEAN SD_GetWriteProtStatus(       // return status. SD_SUCCESS - success
    SD_CARD_T* ptSDCard,        // the card vector
    uint32 uiBlocknum               // the block num
    )
{
    //Optional
    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    The CID register is 16 bytes long and contains a unique card identification 
//                      number. It is programmed during card manufacturing and cannot be changed 
//                      by miniSD Card hosts. Note that the CID register in the miniSD Card has a 
//                      different structure than the CID register in the MultiediaCard.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_ReadCID(       // return status. SD_SUCCESS - success
    SD_CARD_T* ptSDCard,        // the card vector
    uint8* pucData                      // CID register value. The data length should be 18 bytes: 16 bytes reg value + 2 bytes CRC
    )
{
    uint32 i = 0;
    uint8 tmp;

    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    
    SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
    
    /* Wait until any old transfers are finished */
    //SD_WaitNotBusy(ptSDCard);
    
    /* Pack the address */
    SD_Packarg(g_ucArgument, 0);
    
    /* Need to add size checking */
    if(SD_WriteCmd(ptSDCard, CMD10, CMD10_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_READCID_CMD10_ERROR;
    }
    
    /* Check for an error, like a misaligned read */
    if(g_ucResponse[0] != 0)
    {
        return SD_READCID_RESPONSE_ERROR | (g_ucResponse[0])<<8;
    }
    
    /* Re-assert CS to continue the transfer */
    SPI_SetCS(ptSDCard->eSPIId, ptSDCard->uiCSId);

    /* Wait for the token */
    i = 0;
    do
    {
        tmp = (uint8)SPI_GetChar(ptSDCard->eSPIId);
        i++;
    }
    while((tmp == 0xFF) && i < ptSDCard->uiReadTimeout);

    if(i == ptSDCard->uiReadTimeout)
    {
        return SD_READCID_TIMEOUT_ERROR;
    }
    
    if((tmp & MSK_TOK_DATAERROR) == 0)
    {
        /* Clock out a byte before returning */
        SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0xFF);
        
        /* The card returned an error response. Bail and return 0 */
        return SD_READCID_TOKEN_ERROR | tmp<<8;
    }
    
    for(i = 0; i < 16 + 2; i++)         //16Bytes CID + 2 CRC Bytes
    {
        pucData[i] = (uint8)SPI_GetChar(ptSDCard->eSPIId);
    }

    SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
    SD_Delay(ptSDCard->eSPIId, CS_NONE, 6); //send some clock to let SDCard have enough time to finish it's work.
    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    The 32-bit operation conditions register stores the VDD voltage profile of the 
//                      card. The miniSD Card is capable of executing the voltage recognition 
//                      procedure(CMD1) with any standard miniSD Card host using operating 
//                      voltages from 2 to 3.6 Volts.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_ReadOCR(       // return status. SD_SUCCESS - success
    SD_CARD_T* ptSDCard,        // the card vector
    uint32* puiData                     // the OCR shows the voltage range
    )
{
    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    
    SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
    
    /* Wait until any old transfers are finished */
    //SD_WaitNotBusy(ptSDCard);
    
    /* Pack the address */
    SD_Packarg(g_ucArgument, 0);
    
    /* Need to add size checking */
    if(SD_WriteCmd(ptSDCard, CMD58, CMD58_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_READOCR_CMD58_ERROR;
    }
    
    /* Check for an error, like a misaligned read */
    if(g_ucResponse[4] != 0)
    {
        return SD_READOCR_RESPONSE_ERROR | (g_ucResponse[4])<<8;
    }
    
    *puiData = g_ucResponse[0] + (g_ucResponse[1] << 8) + (g_ucResponse[2] << 16) + (g_ucResponse[3] << 24);
    
    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    The Card Specific Data(CSD) register contains configuration information 
//                      required to access the card data.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_ReadCSD(       // return status. SD_SUCCESS - success
    SD_CARD_T* ptSDCard,    // the card vector 
    uint8* pucData                  // CSD register value. The data length should be 18 bytes: 16 bytes reg value + 2 bytes CRC
    )
{
    uint32 i = 0;
    uint8 tmp;

    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    
    SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
    
    /* Wait until any old transfers are finished */
    //SD_WaitNotBusy(ptSDCard);
    
    /* Pack the address */
    SD_Packarg(g_ucArgument, 0);
    
    /* Need to add size checking */
    if(SD_WriteCmd(ptSDCard, CMD9, CMD9_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_READCSD_CMD9_ERROR;
    }
    
    /* Check for an error, like a misaligned read */
    if(g_ucResponse[0] != 0)
    {
        return SD_READCSD_RESPONSE_ERROR | (g_ucResponse[0])<<8;
    }
    
    /* Re-assert CS to continue the transfer */
    SPI_SetCS(ptSDCard->eSPIId, ptSDCard->uiCSId);

    /* Wait for the token */
    i = 0;
    do
    {
        tmp = (uint8)SPI_GetChar(ptSDCard->eSPIId);
        i++;
    }
    while((tmp == 0xFF) && i < ptSDCard->uiReadTimeout);

    if(i == ptSDCard->uiReadTimeout)
    {
        return SD_READCSD_TIMEOUT_ERROR;
    }
    
    if((tmp & MSK_TOK_DATAERROR) == 0)
    {
        /* Clock out a byte before returning */
        SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0xFF);
        
        /* The card returned an error response. Bail and return 0 */
        return SD_READCSD_TOKEN_ERROR | tmp<<8;
    }
    
    for(i = 0; i < 16 + 2; i++)         //16Bytes CSD + 2 CRC Bytes
    {
        pucData[i] = (uint8)SPI_GetChar(ptSDCard->eSPIId);
    }

    SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
    SD_Delay(ptSDCard->eSPIId, CS_NONE, 6); //send some clock to let SDCard have enough time to finish it's work.
    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    This function is used to get the card size. Unit: block
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_GetDeviceSize(     // return the device block number. 0 - ERROR!
    SD_CARD_T* ptSDCard         // the card vector
    )
{
    uint8 card_specific_data[16 + 2];   //16Bytes CSD + 2 CRC Bytes
    if(SD_ReadCSD(ptSDCard, (uint8*)card_specific_data) == SD_SUCCESS)
    {
        uint32 blocknr;
        uint32 mult = 1;
        uint32 c_size;
        uint32 c_size_mult;
        int32 i;

        /*c_size: CSD-Slice [73:62]*/
        c_size = ((card_specific_data[6] & 0x3) << 10) | (card_specific_data[7] << 2) | ((card_specific_data[8] & 0xC0) >> 6);
        /*c_size_mult: CSD-Slice [49:47]*/
        c_size_mult = ((card_specific_data[9] & 0x3) << 1) | ((card_specific_data[10] & 0x80) >> 7);

        /*mult = 2 ^ (c_size_mult + 2)*/
        for(i = 0; i < c_size_mult + 2; i++)
        {
            mult *= 2;
        }
        blocknr = (c_size + 1) * mult;

        return blocknr;
    }

    return 0;
}

/*****************************************************************************/
//  Description:    This function is used to set the clock rate which will be used in SPI operating.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_SetClockRate(     // return SD_SUCCESS
    SD_CARD_T* ptSDCard,         // the card vector
    uint32 uiClockRate              // the clock rate
    )
{
    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    ptSDCard->uiClockRate = uiClockRate;
    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    This function is used to set the clock rate which will be used in SPI operating.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_GetClockRate(     // return the clock rate.
    SD_CARD_T* ptSDCard         // the card vector
    )
{
    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return 0;
    }
    return ptSDCard->uiClockRate;
}

/*****************************************************************************/
//  Description:    This function is used to set read timeout times which will be used in read operating.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_SetReadTimeout(     // return SD_SUCCESS
    SD_CARD_T* ptSDCard,         // the card vector
    uint32 uiReadTimeout              // read timeout times
    )
{
    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    ptSDCard->uiReadTimeout = uiReadTimeout;
    return SD_SUCCESS;

⌨️ 快捷键说明

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