目錄
一、SDIO寄存器
1.1 SDIO電源控制寄存器(SDIO_POWER)
1.2 SDIO時(shí)鐘控制寄存器(SDIO_CLKCR)
1.3 SDIO參數(shù)寄存器(SDIO_ARG)
1.4 SDIO命令寄存器(SDIO_CMD)
1.5 SDIO命令響應(yīng)寄存器(SDIO_RESPCMD)
1.6 SDIO響應(yīng) 1..4 寄存器(SDIO_RESPx)
1.7 SDIO數(shù)據(jù)定時(shí)器寄存器(SDIO_DTIMER)
1.8?SDIO數(shù)據(jù)長(zhǎng)度寄存器(SDIO_DLEN)
1.9 SDIO數(shù)據(jù)控制寄存器(SDIO_DCTRL)
1.10 SDIO數(shù)據(jù)計(jì)數(shù)器寄存器(SDIO_DCOUNT)
1.11 SDIO狀態(tài)寄存器(SDIO_STA)
1.12 SDIO清除中斷寄存器(SDIO_ICR)
1.13 SDIO中斷屏蔽寄存器(SDIO_MASK)
1.14 SDIO FIFO計(jì)數(shù)器寄存器(SDIO_FIFOCNT)
1.15 SDIO數(shù)據(jù)FIFO寄存器(SDIO_FIFO)
1.16 SDIO寄存器映像
二、開(kāi)發(fā)思路
三、具體實(shí)例
書(shū)接上回:
STM32——SDIO的學(xué)習(xí)(驅(qū)動(dòng)SD卡)(理論篇)_宇努力學(xué)習(xí)的博客-CSDN博客
在寫(xiě)程序前在最后了解一下SDIO的寄存器
一、SDIO寄存器
設(shè)備通過(guò)可以在AHB上操作的32位控制寄存器與系統(tǒng)通信。
必須以字(32位)的方式操作這些外設(shè)寄存器。
1.1 SDIO電源控制寄存器(SDIO_POWER)
地址偏移: 0x00
復(fù)位值: 0x0000 0000
注意: 寫(xiě)數(shù)據(jù)后的7個(gè)HCLK時(shí)鐘周期內(nèi),不能寫(xiě)入這個(gè)寄存器.
1.2 SDIO時(shí)鐘控制寄存器(SDIO_CLKCR)
地址偏移: 0x04
復(fù)位值: 0x0000 0000
SDIO_CLKCR寄存器控制SDIO_CK輸出時(shí)鐘
注意:
1 當(dāng)SD/SDIO卡或多媒體卡在識(shí)別模式, SDIO_CK的頻率必須低于400kHz。
2 當(dāng)所有卡都被賦予了相應(yīng)的地址后,時(shí)鐘頻率可以改變到卡總線允許的最大頻率。
3 寫(xiě)數(shù)據(jù)后的7個(gè)HCLK時(shí)鐘周期內(nèi)不能寫(xiě)入這個(gè)寄存器。對(duì)于SD I/O卡,在讀等待期間可以停
止SDIO_CK,此時(shí)SDIO_CLKCR寄存器不控制SDIO_CK
?
1.3 SDIO參數(shù)寄存器(SDIO_ARG)
地址偏移: 0x08
復(fù)位值: 0x0000 0000
SDIO_ARG寄存器包含32位命令參數(shù),它將作為命令的一部分發(fā)送到卡中。
1.4 SDIO命令寄存器(SDIO_CMD)
地址偏移: 0x0C
復(fù)位值: 0x0000 0000
SDIO_CMD寄存器包含命令索引和命令類(lèi)型位。命令索引是作為命令的一部分發(fā)送到卡中。命
令類(lèi)型位控制命令通道狀態(tài)機(jī)(CPSM)。
?
注意:
1 寫(xiě)數(shù)據(jù)后的7個(gè)HCLK時(shí)鐘周期內(nèi)不能寫(xiě)入這個(gè)寄存器。
2 多媒體卡可以發(fā)送2種響應(yīng): 48位長(zhǎng)的短響應(yīng),或136位長(zhǎng)的長(zhǎng)響應(yīng)。 SD卡和SD I/O卡只能發(fā)
送短響應(yīng),參數(shù)可以根據(jù)響應(yīng)的類(lèi)型而變化,軟件將根據(jù)發(fā)送的命令區(qū)分響應(yīng)的類(lèi)型。 CE-ATA
設(shè)備只發(fā)送短響應(yīng)
?
1.5 SDIO命令響應(yīng)寄存器(SDIO_RESPCMD)
地址偏移: 0x10
復(fù)位值: 0x0000 0000
SDIO_RESPCMD寄存器包含最后收到的命令響應(yīng)中的命令索引。如果傳輸?shù)拿铐憫?yīng)不包含
命令索引(長(zhǎng)響應(yīng)或OCR響應(yīng)),盡管它應(yīng)該包含111111b(響應(yīng)中的保留域值),但RESPCMD域
的內(nèi)容未知。
?
1.6 SDIO響應(yīng) 1..4 寄存器(SDIO_RESPx)
地址偏移: 0x14 + 4*(x-1),其中 x = 1..4
復(fù)位值: 0x0000 0000
SDIO_RESP1/2/3/4寄存器包含卡的狀態(tài),即收到響應(yīng)的部分信息。
?
1.7 SDIO數(shù)據(jù)定時(shí)器寄存器(SDIO_DTIMER)
地址偏移: 0x24
復(fù)位值: 0x0000 0000
SDIO_DTIMER寄存器包含以卡總線時(shí)鐘周期為單位的數(shù)據(jù)超時(shí)時(shí)間。
一個(gè)計(jì)數(shù)器從SDIO_DTIMER寄存器加載數(shù)值,并在數(shù)據(jù)通道狀態(tài)機(jī)(DPSM)進(jìn)入Wait_R或繁忙
狀態(tài)時(shí)進(jìn)行遞減計(jì)數(shù),當(dāng)DPSM處在這些狀態(tài)時(shí),如果計(jì)數(shù)器減為0,則設(shè)置超時(shí)標(biāo)志。
?
注意 在寫(xiě)入數(shù)據(jù)控制寄存器進(jìn)行數(shù)據(jù)傳輸之前,必須先寫(xiě)入數(shù)據(jù)定時(shí)器寄存器和數(shù)據(jù)長(zhǎng)度寄存器。
1.8?SDIO數(shù)據(jù)長(zhǎng)度寄存器(SDIO_DLEN)
地址偏移: 0x28
復(fù)位值: 0x0000 0000
SDIO_DLEN寄存器包含需要傳輸?shù)臄?shù)據(jù)字節(jié)長(zhǎng)度。當(dāng)數(shù)據(jù)傳輸開(kāi)始時(shí),這個(gè)數(shù)值被加載到數(shù)據(jù)
計(jì)數(shù)器中。
?
?
注意 | 對(duì)于塊數(shù)據(jù)傳輸,數(shù)據(jù)長(zhǎng)度寄存器中的數(shù)值必須是數(shù)據(jù)塊長(zhǎng)度(見(jiàn)SDIO_DCTRL)的倍數(shù)。在寫(xiě) 入數(shù)據(jù)控制寄存器進(jìn)行數(shù)據(jù)傳輸之前,必須先寫(xiě)入數(shù)據(jù)定時(shí)器寄存器和數(shù)據(jù)長(zhǎng)度寄存器。 |
1.9 SDIO數(shù)據(jù)控制寄存器(SDIO_DCTRL)
地址偏移: 0x2C
復(fù)位值: 0x0000 0000
SDIO_DCTRL寄存器控制數(shù)據(jù)通道狀態(tài)機(jī)(DPSM)。
?
注意 寫(xiě)數(shù)據(jù)后的7個(gè)HCLK時(shí)鐘周期內(nèi)不能寫(xiě)入這個(gè)寄存器。
?
1.10 SDIO數(shù)據(jù)計(jì)數(shù)器寄存器(SDIO_DCOUNT)
地址偏移: 0x30
復(fù)位值: 0x0000 0000
當(dāng)DPSM從空閑狀態(tài)進(jìn)入Wait_R或Wait_S狀態(tài)時(shí), SDIO_DCOUNT寄存器從數(shù)據(jù)長(zhǎng)度寄存器加
載數(shù)值(見(jiàn)SDIO_DLEN),在數(shù)據(jù)傳輸過(guò)程中,該計(jì)數(shù)器的數(shù)值遞減直到減為0,然后DPSM進(jìn)入
空閑狀態(tài)并設(shè)置數(shù)據(jù)狀態(tài)結(jié)束標(biāo)志DATAEND。
?
注意 只能在數(shù)據(jù)傳輸結(jié)束時(shí)讀這個(gè)寄存器
1.11 SDIO狀態(tài)寄存器(SDIO_STA)
地址偏移: 0x34
復(fù)位值: 0x0000 0000
SDIO_STA是一個(gè)只讀寄存器,它包含兩類(lèi)標(biāo)志:
● 靜態(tài)標(biāo)志(位[23:22、 10:0]):寫(xiě)入SDIO中斷清除寄存器(見(jiàn)SDIO_ICR),可以清除這些位。
● 動(dòng)態(tài)標(biāo)志(位[21:11]):這些位的狀態(tài)變化根據(jù)它們對(duì)應(yīng)的那部分邏輯而變化(例如: FIFO滿
和空標(biāo)志變高或變低隨FIFO的數(shù)據(jù)寫(xiě)入變化)。
?
1.12 SDIO清除中斷寄存器(SDIO_ICR)
地址偏移: 0x38
復(fù)位值: 0x0000 0000
SDIO_ICR是一個(gè)只寫(xiě)寄存器,在對(duì)應(yīng)寄存器位寫(xiě)’1’將清除SDIO_STA狀態(tài)寄存器中的對(duì)應(yīng)位。
?
?
?
1.13 SDIO中斷屏蔽寄存器(SDIO_MASK)
地址偏移: 0x3C
復(fù)位值: 0x0000 0000
在對(duì)應(yīng)位置’1’, SDIO_MASK中斷屏蔽寄存器決定哪一個(gè)狀態(tài)位產(chǎn)生中斷。
?
?
?
1.14 SDIO FIFO計(jì)數(shù)器寄存器(SDIO_FIFOCNT)
地址偏移: 0x48
復(fù)位值: 0x0000 0000
SDIO_FIFOCNT寄存器包含還未寫(xiě)入FIFO或還未從FIFO讀出的數(shù)據(jù)字?jǐn)?shù)目。當(dāng)在數(shù)據(jù)控制寄
存器(SDIO_DCTRL)中設(shè)置了數(shù)據(jù)傳輸使能位DTEN,并且DPSM處于空閑狀態(tài)時(shí), FIFO計(jì)數(shù)
器從數(shù)據(jù)長(zhǎng)度寄存器(見(jiàn)SDIO_DLEN)加載數(shù)值。如果數(shù)據(jù)長(zhǎng)度未與字對(duì)齊(4的倍數(shù)),則最后剩
下的1~3個(gè)字節(jié)被當(dāng)成一個(gè)字處理。
?
1.15 SDIO數(shù)據(jù)FIFO寄存器(SDIO_FIFO)
地址偏移: 0x80
復(fù)位值: 0x0000 0000
接收和發(fā)送FIFO是32位的寬度讀或?qū)懸唤M寄存器,它在連續(xù)的32個(gè)地址上包含32個(gè)寄存器,
CPU可以使用FIFO讀寫(xiě)多個(gè)操作數(shù)。
1.16 SDIO寄存器映像
下表是SDIO寄存器的總結(jié)。
?
?
?
二、開(kāi)發(fā)思路
????????略掉。我們按照ST官方文檔來(lái)學(xué)習(xí)。從程序中學(xué)習(xí)他們的開(kāi)發(fā)流程。我覺(jué)得這時(shí)最快的方式。在外面都學(xué)會(huì)了以后開(kāi)創(chuàng)直接的東西的時(shí)候才需要按照基礎(chǔ)知識(shí)到程序的流程。
三、具體實(shí)例
使用之前先來(lái)看看怎么取消初始化。?
/**
* @brief DeInitializes the SDIO interface.
* @param None
* @retval None
*/
void SD_LowLevel_DeInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*!< Disable SDIO Clock */
SDIO_ClockCmd(DISABLE);
/*!< Set Power State to OFF */
SDIO_SetPowerState(SDIO_PowerState_OFF);
/*!< DeInitializes the SDIO peripheral */
SDIO_DeInit();
/*!< Disable the SDIO AHB Clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SDIO, DISABLE);
/*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/*!< Configure PD.02 CMD line */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
?先關(guān)閉時(shí)鐘和電源。
然后對(duì)SDIO外設(shè)的相關(guān)寄存器進(jìn)行設(shè)置。
/**
* @brief Deinitializes the SDIO peripheral registers to their default reset values.
* @param None
* @retval None
*/
void SDIO_DeInit(void)
{
SDIO->POWER = 0x00000000;
SDIO->CLKCR = 0x00000000;
SDIO->ARG = 0x00000000;
SDIO->CMD = 0x00000000;
SDIO->DTIMER = 0x00000000;
SDIO->DLEN = 0x00000000;
SDIO->DCTRL = 0x00000000;
SDIO->ICR = 0x00C007FF;
SDIO->MASK = 0x00000000;
}
其實(shí)就是按照流程給對(duì)應(yīng)寄存器寫(xiě)對(duì)應(yīng)的值。
然后關(guān)閉AHB總線
這時(shí)得注意有沒(méi)有其它設(shè)備使用這條總線。
然后配置使用的引腳模式為浮空輸入。
上面的五個(gè)引腳分別是四根數(shù)據(jù)線和一根時(shí)鐘線。
下面那根是控制線。
看完取消使能再看使能
/**
* @brief Initializes the SD Card and put it into StandBy State (Ready for
* data transfer).
* @param None
* @retval None
*/
void SD_LowLevel_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*!< GPIOC and GPIOD Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
/*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/*!< Configure PD.02 CMD line */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/*!< Enable the SDIO AHB Clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SDIO, ENABLE);
/*!< Enable the DMA2 Clock */
RCC_AHBPeriphClockCmd(SD_SDIO_DMA_CLK, ENABLE);
}
和取消相反,先使能引腳對(duì)應(yīng)的時(shí)鐘總線。
將四個(gè)數(shù)據(jù)引腳 和時(shí)鐘引腳初始化為復(fù)用推挽輸出。
使能控制引腳和SDIO與DMA的總線。
/**
* @brief Allows to erase memory area specified for the given card.
* @param startaddr: the start address.
* @param endaddr: the end address.
* @retval SD_Error: SD Card Error code.
*/
SD_Error SD_Erase(uint32_t startaddr, uint32_t endaddr)
{
SD_Error errorstatus = SD_OK;
uint32_t delay = 0;
__IO uint32_t maxdelay = 0;
uint8_t cardstate = 0;
/*!< Check if the card coomnd class supports erase command */
if (((CSD_Tab[1] >> 20) & SD_CCCC_ERASE) == 0)
{
errorstatus = SD_REQUEST_NOT_APPLICABLE;
return(errorstatus);
}
maxdelay = 120000 / ((SDIO->CLKCR & 0xFF) + 2);
if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED)
{
errorstatus = SD_LOCK_UNLOCK_FAILED;
return(errorstatus);
}
if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
{
startaddr /= 512;
endaddr /= 512;
}
/*!< According to sd-card spec 1.0 ERASE_GROUP_START (CMD32) and erase_group_end(CMD33) */
if ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType))
{
/*!< Send CMD32 SD_ERASE_GRP_START with argument as addr */
SDIO_CmdInitStructure.SDIO_Argument = startaddr;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_ERASE_GRP_START;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
errorstatus = CmdResp1Error(SD_CMD_SD_ERASE_GRP_START);
if (errorstatus != SD_OK)
{
return(errorstatus);
}
/*!< Send CMD33 SD_ERASE_GRP_END with argument as addr */
SDIO_CmdInitStructure.SDIO_Argument = endaddr;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_ERASE_GRP_END;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
errorstatus = CmdResp1Error(SD_CMD_SD_ERASE_GRP_END);
if (errorstatus != SD_OK)
{
return(errorstatus);
}
}
/*!< Send CMD38 ERASE */
SDIO_CmdInitStructure.SDIO_Argument = 0;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_ERASE;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
errorstatus = CmdResp1Error(SD_CMD_ERASE);
if (errorstatus != SD_OK)
{
return(errorstatus);
}
for (delay = 0; delay < maxdelay; delay++)
{}
/*!< Wait till the card is in programming state */
errorstatus = IsCardProgramming(&cardstate);
delay = SD_DATATIMEOUT;
while ((delay > 0) && (errorstatus == SD_OK) && ((SD_CARD_PROGRAMMING == cardstate) || (SD_CARD_RECEIVING == cardstate)))
{
errorstatus = IsCardProgramming(&cardstate);
delay--;
}
return(errorstatus);
}
上面這個(gè)函數(shù)是擦除SD卡某個(gè)區(qū)域的。
下面的函數(shù)是初始化整個(gè)SD卡,并讓其進(jìn)入待機(jī)狀態(tài)。
/**
* @brief Initializes the SD Card and put it into StandBy State (Ready for data
* transfer).
* @param None
* @retval SD_Error: SD Card Error code.
*/
SD_Error SD_Init(void)
{
__IO SD_Error errorstatus = SD_OK;
NVIC_Configuration();
/* SDIO Peripheral Low Level Init */
SD_LowLevel_Init();
SDIO_DeInit();
errorstatus = SD_PowerON();
if (errorstatus != SD_OK)
{
/*!< CMD Response TimeOut (wait for CMDSENT flag) */
return(errorstatus);
}
errorstatus = SD_InitializeCards();
if (errorstatus != SD_OK)
{
/*!< CMD Response TimeOut (wait for CMDSENT flag) */
return(errorstatus);
}
/*!< Configure the SDIO peripheral */
/*!< SDIO_CK = SDIOCLK / (SDIO_TRANSFER_CLK_DIV + 2) */
SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV;
SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;
SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;
SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;
SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;
SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;
SDIO_Init(&SDIO_InitStructure);
/*----------------- Read CSD/CID MSD registers ------------------*/
errorstatus = SD_GetCardInfo(&SDCardInfo);
if (errorstatus == SD_OK)
{
/*----------------- Select Card --------------------------------*/
errorstatus = SD_SelectDeselect((uint32_t) (SDCardInfo.RCA << 16));
}
if (errorstatus == SD_OK)
{
errorstatus = SD_EnableWideBusOperation(SDIO_BusWide_4b);
}
return(errorstatus);
}
?對(duì)單個(gè)數(shù)據(jù)塊做讀寫(xiě)測(cè)試。之前學(xué)習(xí)系統(tǒng)移植的時(shí)候,我們了解到SD卡是以512個(gè)字節(jié)為一個(gè)塊的。所以這個(gè)Blocksize就是一個(gè)宏定義的512
/*
* 函數(shù)名:SD_SingleBlockTest
* 描述 : 單個(gè)數(shù)據(jù)塊讀寫(xiě)測(cè)試
* 輸入 :無(wú)
* 輸出 :無(wú)
*/
void SD_SingleBlockTest(void)
{
/* Fill the buffer to send */
Fill_Buffer(Buffer_Block_Tx, BLOCK_SIZE, 0x320F);
if (Status == SD_OK)
{
/* Write block of 512 bytes on address 0 */
Status = SD_WriteBlock(Buffer_Block_Tx, 0x00, BLOCK_SIZE);
/* Check if the Transfer is finished */
Status = SD_WaitWriteOperation();
while(SD_GetStatus() != SD_TRANSFER_OK);
}
if (Status == SD_OK)
{
/* Read block of 512 bytes from address 0 */
Status = SD_ReadBlock(Buffer_Block_Rx, 0x00, BLOCK_SIZE);//讀取數(shù)據(jù)
/* Check if the Transfer is finished */
Status = SD_WaitReadOperation();
while(SD_GetStatus() != SD_TRANSFER_OK);
}
/* Check the correctness of written data */
if (Status == SD_OK)
{
TransferStatus1 = Buffercmp(Buffer_Block_Tx, Buffer_Block_Rx, BLOCK_SIZE); //比較
}
if(TransferStatus1 == PASSED)
printf("》單塊讀寫(xiě)測(cè)試成功!\n" );
else
printf("》單塊讀寫(xiě)測(cè)試失??!\n " );
}
?這里是自己實(shí)現(xiàn)的三個(gè)小函數(shù)。方便在操作時(shí)使用對(duì)應(yīng)功能。
/*
* 函數(shù)名:Buffercmp
* 描述 :比較兩個(gè)緩沖區(qū)中的數(shù)據(jù)是否相等
* 輸入 :-pBuffer1, -pBuffer2 : 要比較的緩沖區(qū)的指針
* -BufferLength 緩沖區(qū)長(zhǎng)度
* 輸出 :-PASSED 相等
* -FAILED 不等
*/
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint32_t BufferLength)
{
while (BufferLength--)
{
if (*pBuffer1 != *pBuffer2)
{
return FAILED;
}
pBuffer1++;
pBuffer2++;
}
return PASSED;
}
/*
* 函數(shù)名:Fill_Buffer
* 描述 :在緩沖區(qū)中填寫(xiě)數(shù)據(jù)
* 輸入 :-pBuffer 要填充的緩沖區(qū)
* -BufferLength 要填充的大小
* -Offset 填在緩沖區(qū)的第一個(gè)值
* 輸出 :無(wú)
*/
void Fill_Buffer(uint8_t *pBuffer, uint32_t BufferLength, uint32_t Offset)
{
uint16_t index = 0;
/* Put in global buffer same values */
for (index = 0; index < BufferLength; index++ )
{
pBuffer[index] = index + Offset;
}
}
/*
* 函數(shù)名:eBuffercmp
* 描述 :檢查緩沖區(qū)的數(shù)據(jù)是否為0
* 輸入 :-pBuffer 要比較的緩沖區(qū)
* -BufferLength 緩沖區(qū)長(zhǎng)度
* 輸出 :PASSED 緩沖區(qū)的數(shù)據(jù)全為0
* FAILED 緩沖區(qū)的數(shù)據(jù)至少有一個(gè)不為0
*/
TestStatus eBuffercmp(uint8_t* pBuffer, uint32_t BufferLength)
{
while (BufferLength--)
{
/* In some SD Cards the erased state is 0xFF, in others it's 0x00 */
if ((*pBuffer != 0xFF) && (*pBuffer != 0x00))//擦除后是0xff或0x00
{
return FAILED;
}
pBuffer++;
}
return PASSED;
}
對(duì)多塊讀寫(xiě)如下:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-604399.html
/*
* 函數(shù)名:SD_MultiBlockTest
* 描述 : 多數(shù)據(jù)塊讀寫(xiě)測(cè)試
* 輸入 :無(wú)
* 輸出 :無(wú)
*/
void SD_MultiBlockTest(void)
{
/* Fill the buffer to send */
Fill_Buffer(Buffer_MultiBlock_Tx, MULTI_BUFFER_SIZE, 0x0);
if (Status == SD_OK)
{
/* Write multiple block of many bytes on address 0 */
Status = SD_WriteMultiBlocks(Buffer_MultiBlock_Tx, 0x00, BLOCK_SIZE, NUMBER_OF_BLOCKS);
/* Check if the Transfer is finished */
Status = SD_WaitWriteOperation();
while(SD_GetStatus() != SD_TRANSFER_OK);
}
if (Status == SD_OK)
{
/* Read block of many bytes from address 0 */
Status = SD_ReadMultiBlocks(Buffer_MultiBlock_Rx, 0x00, BLOCK_SIZE, NUMBER_OF_BLOCKS);
/* Check if the Transfer is finished */
Status = SD_WaitReadOperation();
while(SD_GetStatus() != SD_TRANSFER_OK);
}
/* Check the correctness of written data */
if (Status == SD_OK)
{
TransferStatus2 = Buffercmp(Buffer_MultiBlock_Tx, Buffer_MultiBlock_Rx, MULTI_BUFFER_SIZE);
}
if(TransferStatus2 == PASSED)
printf("》多塊讀寫(xiě)測(cè)試成功!\n " );
else
printf("》多塊讀寫(xiě)測(cè)試失?。n " );
}
以上驅(qū)動(dòng)程序來(lái)自ST官方驅(qū)動(dòng)庫(kù)。應(yīng)用層測(cè)試demo來(lái)自硬石頭。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-604399.html
到了這里,關(guān)于STM32——SDIO的學(xué)習(xí)(驅(qū)動(dòng)SD卡)(實(shí)戰(zhàn)篇)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!