SD卡(Secure Digital Memory Card)即:安全數(shù)字內(nèi)存卡,它是在MMC的基礎(chǔ)上發(fā)展而來,是一種基于半導(dǎo)體快閃記憶器的新一代記憶設(shè)備,它被廣泛地于便攜式裝置上使用,例如數(shù)碼相機(jī)、個人數(shù)碼助理(PDA)和多媒體播放器等。SD卡由日本松下、東芝及美國SanDisk公司于1999年8月共同開發(fā)研制。
- SD卡簡介
SD非常小巧,可以嵌入到設(shè)備中,在嵌入式開發(fā)中,產(chǎn)品需要存儲一些容量叫大的文件,就可能會運(yùn)用到SD卡。SD卡按容量分類,可以分為3類:SD卡、SDHC卡、SDXC卡,如下表所示。
容量大小不同的SD卡,其內(nèi)部的操作標(biāo)準(zhǔn)是不同的。很多外設(shè)會明確告訴用戶本設(shè)備最大能夠支持容量多大的外擴(kuò),不能無限制的擴(kuò)存,因為容量越大,操作不同,對控制器的要求比較高。當(dāng)前設(shè)備的控制器不足以支持大容量,所以有外擴(kuò)限制。
SD卡由9個引腳與外部通信,支持SPI和SDIO兩種模式,不同模式下,SD卡引腳功能描述如下表所示。
- SD卡的物理結(jié)構(gòu)
一張SD卡包括有存儲單元、存儲單元接口、電源檢測、卡及接口控制器和接口驅(qū)動器5個部分。
存儲單元:是存儲數(shù)據(jù)部件,存儲單元通過存儲單元接口與卡控制單元進(jìn)行數(shù)據(jù)傳輸;
電源檢測單元:保證SD卡工作在合適的電壓下,如出現(xiàn)掉電或上狀態(tài)時,它會使控制單元和存儲單元接口復(fù)位;
卡及接口控制單元:控制SD卡的運(yùn)行狀態(tài),它包括有8個寄存器;
接口驅(qū)動器:控制SD卡引腳的輸入輸出。
- SD卡內(nèi)部寄存器
SD卡總共有8個寄存器,用于設(shè)定或表示SD卡信息。這些寄存器只能通過對應(yīng)的命令訪問,程序控制中只需要發(fā)送組合命令就可以實(shí)現(xiàn)SD卡的控制以及讀寫操作。
- SDIO接口
SDIO全稱是安全數(shù)字輸入/輸出接口,多媒體卡(MMC)、SD卡、SD I/O卡都有SDIO接口。STM32F407系列控制器有一個SDIO主機(jī)接口,它可以與MMC卡、SD卡、SD I/O卡以及CE-ATA設(shè)備進(jìn)行數(shù)據(jù)傳輸。也就是說SDIO接口不僅僅只會操作SD卡,凡是符合SDIO接口通信的設(shè)備都可以被操作。
SDIO 具有以下特性:
完全兼容 多媒體卡系統(tǒng)規(guī)范版本 4.2??ㄖС秩N不同數(shù)據(jù)總線模式:1 位(默認(rèn))、4 位和 8 位
完全兼容先前版本的多媒體卡(向前兼容性)
完全兼容 SD 存儲卡規(guī)范版本2.0
完全兼容 SD I/O 卡規(guī)范版本 2.0 : 卡支持兩種不同數(shù)據(jù)總線模式:1 位(默認(rèn))和 4 位
完全支持 CE-ATA 功能(完全符合 CE-ATA 數(shù)字協(xié)議版本 1.1)
對于 8 位模式,數(shù)據(jù)傳輸高達(dá) 48 MHz
數(shù)據(jù)和命令輸出使能信號,控制外部雙向驅(qū)動程序。
SDIO 不具備兼容 SPI 的通信模式。
- SDIO組成
SDIO 適配器塊提供特定于 MMC/SD/SD I/O 卡的所有功能,如時鐘生成單元、命令和數(shù)據(jù)傳輸。
APB2 接口訪問 SDIO 適配器寄存器,并且生成中斷和 DMA 請求信號。
注:
1、默認(rèn)情況下,SDIO_D0用于數(shù)據(jù)傳輸。初始化后,主機(jī)可以更改數(shù)據(jù)總線寬度。
2、SD 卡連接到總線,主機(jī)可以將數(shù)據(jù)傳輸配置為SDIO_D[3:0]
3、SDIO使用兩個時鐘信號:SDIO適配器時鐘(SDIOCLK= 48 MHz)和APB2總線時鐘(PCLK2)。
4、卡時鐘(SDIO_CK):每個時鐘周期在命令和數(shù)據(jù)線上傳輸1位命令或數(shù)據(jù)。對于SD或SDI/O卡,時鐘頻率可以在0MHz至25MHz間變化,當(dāng)數(shù)據(jù)正式穩(wěn)定傳輸?shù)臅r候配置為24MHz。SDIO_CK計算公式:SDIO_CK=SDIOCLK/(2+CLKDIV)
5、SDIO適配器時鐘(SDIOCLK):該時鐘用于驅(qū)動SDIO適配器,可用于產(chǎn)生SDIO_CK時鐘。對F4來說,SDIOCLK來自PLL48CK(48Mhz)。
6、F4:APB2總線接口時鐘(PCLK2):該時鐘用于驅(qū)動SDIO的APB2總線接口,其頻率為PCLK2=84Mhz。
注意:在SD卡初始化時,SDIO_CK不可以超過400Khz,初始化完成后,可以設(shè)置為最大頻率(但不可以超過SD卡最大操作頻率)。
該適配器由五個子單元組成:
1.適配器寄存器塊 :適配器寄存器模塊包含所有系統(tǒng)寄存器。
2.控制單元 : 控制單元包含電源管理功能和存儲卡時鐘的時鐘分頻器。
3.命令路徑 :命令路徑單元向卡發(fā)送命令并從卡接收響應(yīng)。
4.數(shù)據(jù)路徑 :數(shù)據(jù)路徑子單元負(fù)責(zé)與卡相互傳輸數(shù)據(jù)。
5.數(shù)據(jù) FIFO :數(shù)據(jù) FIFO(先進(jìn)先出)子單元是一個數(shù)據(jù)緩沖器,帶發(fā)送和接收單元。FIFO 包含一個寬度為 32 位且深度為 32 字的數(shù)據(jù)緩沖器和發(fā)送/接收邏輯。(一共32 個單元,一個單元一個字)。所有的數(shù)據(jù)傳輸都要經(jīng)過FIFO,便于管理。
- SDIO 命令簡介
SD命令由主機(jī)發(fā)出,以廣播命令和尋址命令為例,廣播命令是針對與SD主機(jī)總線連接的所有從設(shè)備發(fā)送的,尋址命令是指定某個地址設(shè)備進(jìn)行命令傳輸。
SD命令格式固定為48bit,都是通過CMD線連續(xù)傳輸?shù)?,?shù)據(jù)線不參與。
SD命令的組成如下:
起始位和終止位:命令的主體包含在起始位與終止位之間,它們都只包含一個數(shù)據(jù)位,起始位為 0,終止位為 1。
傳輸標(biāo)志:用于區(qū)分傳輸方向,該位為 1 時表示命令,方向為主機(jī)傳輸?shù)?SD 卡,該位為 0時表示響應(yīng),方向為 SD卡傳輸?shù)街鳈C(jī)。
命令主體內(nèi)容包括命令、地址信息/參數(shù)和 CRC 校驗三個部分。
命令號:它固定占用 6bit,所以總共有 64個命令(代號:CMD0~CMD63),每個命令都有特定的用途,部分命令不適用于 SD 卡操作,只是專門用于 MMC卡或者SD I/O卡。
地址/參數(shù):每個命令有 32bit地址信息/參數(shù)用于命令附加內(nèi)容,例如,廣播命令沒有地址信息,這 32bit用于指定參數(shù),而尋址命令這 32bit用于指定目標(biāo) SD卡的地址。
CRC7 校驗:長度為 7bit的校驗位用于驗證命令傳輸內(nèi)容正確性,如果發(fā)生外部干擾導(dǎo)致傳輸數(shù)據(jù)個別位狀態(tài)改變將導(dǎo)致校準(zhǔn)失敗,也意味著命令傳輸失敗,SD卡不執(zhí)行命令。
SD命令有4種類型:
1.無響應(yīng)廣播命令(bc),發(fā)送到所有卡,不返回任務(wù)響應(yīng);
2.帶響應(yīng)廣播命令(bcr),發(fā)送到所有卡,同時接收來自所有卡響應(yīng);
3.尋址命令(ac),發(fā)送到選定卡,DAT線無數(shù)據(jù)傳輸;
5.尋址數(shù)據(jù)傳輸命令(adtc),發(fā)送到選定卡,DAT線有數(shù)據(jù)傳輸。
在標(biāo)準(zhǔn)中定義了兩種類型的通用命令:特定應(yīng)用命令(ACMD)和常規(guī)命令(GEN_CMD),也就是說在64個命令作為常規(guī)命令的基礎(chǔ)上加了特定的命令
要使用SD卡制造商特定的ACMD命令如ACMD6,需要在發(fā)送該命令之前無發(fā)送CMD55命令,告知SD卡接下來的命令為特定應(yīng)用命令。CMD55命令只對緊接的第一個命令有效,SD卡如果檢測到CMD55之后的第一條命令為ACMD則執(zhí)行其特定應(yīng)用功能,如果檢測發(fā)現(xiàn)不是ACMD命令,則執(zhí)行標(biāo)準(zhǔn)命令。
SD命令響應(yīng)由SD卡向主機(jī)發(fā)出,部分命令要求SD卡作出響應(yīng),這些響應(yīng)多用于反饋SD卡的狀態(tài)?;咎匦匀缦拢?/p>
lSDIO總共有7個響應(yīng)類型(代號:R1~R7),其中SD卡沒有R4、R5類型響應(yīng)。特定的命令對應(yīng)有特定的響應(yīng)類型,比如當(dāng)主機(jī)發(fā)送CMD3命令時,可以得到響應(yīng)R6。與命令一樣,SD卡的響應(yīng)也是通過CMD線連續(xù)傳輸?shù)摹8鶕?jù)響應(yīng)內(nèi)容大小可以分為短響應(yīng)和長響應(yīng)。短響應(yīng)是48bit長度,只有R2類型是長響應(yīng),其長度為136bit。
SDIO讀數(shù)據(jù)
單個塊讀操作與多個塊的讀操作除命令不同外,還體現(xiàn)在讀操作結(jié)束時,單個塊讀取一個塊自動結(jié)束,而多個塊還需要主機(jī)發(fā)送停止命令。寫操作類似,也要多發(fā)一個結(jié)束命令,只不過寫操作寫數(shù)據(jù)前需要檢查卡的狀態(tài)是否為忙狀態(tài)。
SDIO寫數(shù)據(jù)
- SD卡操作模式
SD卡有多個版本,STM32控制器目前最高支持《Physical Layer SimplifiedSpecification V2.0》定義的SD卡,STM32控制器對SD卡進(jìn)行數(shù)據(jù)讀寫之前需要識別卡的種類:V1.0標(biāo)準(zhǔn)卡、V2.0標(biāo)準(zhǔn)卡、V2.0高容量卡或者不被識別卡。
SD卡系統(tǒng)定義了兩種操作模式:卡識別模式和數(shù)據(jù)傳輸模式。
在系統(tǒng)復(fù)位后,主機(jī)處于卡識別模式,尋找總線上可用的SDIO設(shè)備;同時,SD卡也處于卡識別模式,直到被主機(jī)識別到,即當(dāng)SD卡接收到SEND_RCA(CMD3)命令后,SD卡就會進(jìn)入數(shù)據(jù)傳輸模式,而主機(jī)在總線上所有卡被識別后也進(jìn)入數(shù)據(jù)傳輸模式。
每個不同的操作模式下,SD卡都有不同狀態(tài),通過命令控制實(shí)現(xiàn)卡狀態(tài)的切換,在不同的狀態(tài)下做不同的事,比如在發(fā)送數(shù)據(jù)前需要SD卡處于傳輸狀態(tài),發(fā)送數(shù)據(jù)時,SD卡處于接收狀態(tài)。
- 卡識別模式
①上電后,主機(jī)發(fā)送CMD0讓所有卡軟復(fù)位從而進(jìn)入空閑狀態(tài)。
②主機(jī)發(fā)送CMD8確定卡的電壓范圍,并識別是否為2.0的卡
③主機(jī)發(fā)送ACMD41識別或拒絕不匹配它的電壓范圍的卡,SD卡需要工作在特定的電壓范圍之內(nèi)
④主機(jī)發(fā)送CMD2來控制所有卡返回它們的卡識別號CID(128位)
⑤主機(jī)發(fā)送CMD3命令,讓卡推薦一個RCA(16)地址作為以后通信的標(biāo)識,之后都以RCA值作為身份標(biāo)識進(jìn)行信息交互。
注:在卡識別過程中,要求SD卡工作在識別時鐘頻率FOD的狀態(tài)下,在SD卡初始化時,SDIO_CK不可以超過400Khz
- 數(shù)據(jù)傳輸模式
只有SD卡系統(tǒng)處于數(shù)據(jù)傳輸模式下才可以進(jìn)行數(shù)據(jù)讀寫操作。數(shù)據(jù)傳輸模式下可以將主機(jī)SD時鐘頻率設(shè)置為FPP,默認(rèn)最高為25MHz,頻率切換可以通過CMD4命令來實(shí)現(xiàn)。通過CMD7命令加上RCA值來選定指定的卡,選中后SD卡進(jìn)入數(shù)據(jù)傳輸狀態(tài),就可以發(fā)送CMD17讀單個塊,CMD18讀多個塊,讀多個塊時只有發(fā)送CMD12命令才會停止。SD卡再次進(jìn)入傳輸狀態(tài),若不想對卡有任何操作可以再次發(fā)送CMD7命令加上RCA值來取消指定的卡,寫操作與上述原理相同。
- SD卡普通模式操作實(shí)例
實(shí)驗內(nèi)容:向SD卡寫入數(shù)據(jù)后讀出
實(shí)驗步驟:
1.配置RCC,與以往不同的是SDIO適配器的時鐘是單獨(dú)配置的,需要專用的SDIOCLK,標(biāo)準(zhǔn)工作在48MHz
2.配置SDIO
3.編寫代碼
//mian.c
#include "main.h"
#include "stm32f4xx_hal.h"
#include "sdio.h"
#include "usart.h"
#include "gpio.h"
#define SDBUF_SIZE 1024
uint8_t SDBUF_TX[SDBUF_SIZE],SDBUF_RX[SDBUF_SIZE];//數(shù)據(jù)傳輸?shù)腷uf,一個用于傳輸,一個用于接收
//定義全局變量,最好不定義局部變量,防止因過大造成棧溢出
int main(void)
{
uint32_t i;
HAL_SD_CardInfoTypeDef pCardInfo;//定義結(jié)構(gòu)體用來接收卡信息
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SDIO_SD_Init();
MX_USART1_UART_Init();
printf("this is sd testn");
//卡識別結(jié)束后就可以調(diào)用HAL_SD_GetCardInfo()函數(shù)獲取卡信息并打印
HAL_SD_GetCardInfo(&hsd, &pCardInfo);
printf("pCardInfo.CardType = %un",pCardInfo.CardType);
printf("pCardInfo.CardVersion = %un",pCardInfo.CardVersion);//版本
printf("pCardInfo.BlockNbr = %un",pCardInfo.BlockNbr);//SD卡塊數(shù)
printf("pCardInfo.BlockSize = %un",pCardInfo.BlockSize);//每一塊大小
/*--------------------SD卡寫測試----------------------------------*/
memset(SDBUF_TX, 0x8, SDBUF_SIZE); /、填充TXbuf為0x8
/**
//函數(shù)功能及參數(shù)描述
*HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData,
*uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
* @param hsd Pointer to SD handle
* @param pData pointer to the buffer that will contain the data to transmit
* @param BlockAdd Block Address where data will be written,從哪一個塊開始寫
* @param NumberOfBlocks Number of SD blocks to write 寫幾個塊
* @param Timeout Specify timeout value 超時時間
* @retval HAL status
if( HAL_SD_WriteBlocks(&hsd, SDBUF_TX, 0 , 2, 1000) == HAL_OK)
{
while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER);//處于傳輸狀態(tài)退出
printf("WriteBlocks Successfullyn");
for(i=0; i< SDBUF_SIZE; i++)
{
printf("%d ",SDBUF_TX[i]);
}
printf("rn");
}
else
{
printf("WriteBlocks Failedn");
}
/*--------------------SD 卡讀測試----------------------------------*/
//與HAL_SD_WriteBlocks函數(shù)的參數(shù)功能相同
if( HAL_SD_ReadBlocks(&hsd, SDBUF_RX , 0, 2, 1000) == HAL_OK)
{
while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER);//返回到傳輸狀態(tài)退出
printf("ReadBlocks Successfullyn");
for(i=0; i< SDBUF_SIZE; i++)
{
printf("%d ",SDBUF_RX[i]);
}
printf("rn");
}
else
{
printf("ReadBlocks Failedn");
}
/*--------------------SD 擦除測試----------------------------------*/
if (HAL_SD_Erase(&hsd, 0, 1) == HAL_OK )
{
while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER);
printf("SD_Erase Successfullyn");
}
else
{
printf("SD_Erase Failedn");
}
/*--------------------SD 卡讀測試----------------------------------*/
if( HAL_SD_ReadBlocks(&hsd, SDBUF_RX , 0, 2, 1000) == HAL_OK)
{
while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER);
printf("ReadBlocks Successfullyn");
for(i=0; i< SDBUF_SIZE; i++)
{
printf("%d ",SDBUF_RX[i]);
}
printf("rn");
}
else
{
printf("ReadBlocks Failedn");
}
while (1)
{
}
}
//sdio.c
//此代碼為工程自動生成,非用戶編寫,這里只做分析
#include "sdio.h"
#include "gpio.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
SD_HandleTypeDef hsd;
/* SDIO init function */
void MX_SDIO_SD_Init(void) //初始化配置
{
hsd.Instance = SDIO; //SDIO句柄,整個系統(tǒng)中只有這一個
hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
hsd.Init.BusWide = SDIO_BUS_WIDE_1B; //初始化時設(shè)置數(shù)據(jù)寬度為1位
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 0;
//HAL_SD_Init()函數(shù)內(nèi)部做了很多事去識別SD卡,具體的卡識別代碼分析在下方
if (HAL_SD_Init(&hsd) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
//初始化結(jié)束后重新配置數(shù)據(jù)寬度為4位
if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
//卡識別代碼如下
HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd)
{
uint32_t errorstate = HAL_SD_ERROR_NONE;
SD_InitTypeDef Init;
/* Default SDIO peripheral configuration for SD card initialization */
//完成卡識別
Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
Init.BusWide = SDIO_BUS_WIDE_1B;
Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
Init.ClockDiv = SDIO_INIT_CLK_DIV;
//SDIO_CK卡識別階段要求時鐘小于400KHz,宏定義
//SDIO_CK計算公式:SDIO_CK=SDIOCLK/(2+CLKDIV)
/* SDIO Initialization Frequency (400KHz max) */
/*#define SDIO_INIT_CLK_DIV ((uint8_t)0x76)*/
/* Initialize SDIO peripheral interface with default configuration */
SDIO_Init(hsd- >Instance, Init);
/* Disable SDIO Clock */
__HAL_SD_DISABLE(hsd);
/* Set Power State to ON 對SD卡進(jìn)行上電 */
SDIO_PowerState_ON(hsd- >Instance);
/* Enable SDIO Clock */
__HAL_SD_ENABLE(hsd);
/* Required power up waiting time before starting the SD initialization
sequence */
HAL_Delay(2U);
/* Identify card operating voltage */
errorstate = SD_PowerON(hsd);
if(errorstate != HAL_SD_ERROR_NONE)
{
hsd- >State = HAL_SD_STATE_READY;
hsd- >ErrorCode |= errorstate;
return HAL_ERROR;
}
/* Card initialization */
errorstate = SD_InitCard(hsd);
if(errorstate != HAL_SD_ERROR_NONE)
{
hsd- >State = HAL_SD_STATE_READY;
hsd- >ErrorCode |= errorstate;
return HAL_ERROR;
}
return HAL_OK;
}
- SD卡DMA模式操作實(shí)例
當(dāng)SD卡中有大量的音視頻需要讀取時,整個過程需要CPU干預(yù),這樣CPU的利用率就會降低,因此大量數(shù)據(jù)的傳輸最好啟用DMA。
實(shí)驗內(nèi)容:向SD卡寫入數(shù)據(jù)后讀出。
實(shí)驗步驟:工程的時鐘配置和SDIO配置與普通模式相同,只有一點(diǎn)不同需要打開SDIO的全局中斷,因為SDIO發(fā)送與接收完成后都需要中斷去生成DMA請求。設(shè)置SDIO全局中斷優(yōu)先級更高一些,因為它內(nèi)部還有很多其他中斷,發(fā)生錯誤時更需要處理。
配置DMA
編寫代碼:
//mian.c
#include "main.h"
#include "stm32f4xx_hal.h"
#include "dma.h"
#include "sdio.h"
#include "usart.h"
#include "gpio.h"
#define SDBUF_SIZE 1024
uint8_t SDBUF_TX[SDBUF_SIZE],SDBUF_RX[SDBUF_SIZE];//數(shù)據(jù)傳輸?shù)腷uf,一個用于傳輸,一個用于接收
//定義全局變量,最好不定義局部變量,防止因過大造成棧溢出
uint8_t DMA_SEND_OK, DMA_RCV_OK;
int main(void)
{
uint32_t i;
HAL_SD_CardInfoTypeDef pCardInfo;//定義結(jié)構(gòu)體用來接收卡信息
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_SDIO_SD_Init();
MX_USART1_UART_Init();
printf("this is sd testn");
//卡識別結(jié)束后就可以調(diào)用HAL_SD_GetCardInfo()函數(shù)獲取卡信息并打印
HAL_SD_GetCardInfo(&hsd, &pCardInfo);
printf("pCardInfo.CardType = %un",pCardInfo.CardType);
printf("pCardInfo.CardVersion = %un",pCardInfo.CardVersion);//版本
printf("pCardInfo.BlockNbr = %un",pCardInfo.BlockNbr);//SD卡塊數(shù)
printf("pCardInfo.BlockSize = %un",pCardInfo.BlockSize);//每一塊大小
/*------------------- SD DMA 寫測試-------------------------------------*/
memset(SDBUF_TX, 0x2, SDBUF_SIZE );
DMA_SEND_OK = 0;//設(shè)置發(fā)送完成標(biāo)志位為0,完成時為1
/**
//函數(shù)原型
*HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData,
uint32_t BlockAdd, uint32_t NumberOfBlocks)
* @param hsd Pointer to SD handle
* @param pData Pointer to the buffer that will contain the data to transmit
* @param BlockAdd Block Address where data will be written 從哪個塊開始寫
* @param NumberOfBlocks Number of blocks to write寫幾個塊
* @retval HAL status
*/
if( HAL_SD_WriteBlocks_DMA(&hsd, SDBUF_TX, 0, 1) == HAL_OK )
{
//等待DMA傳輸完成,并且SD卡狀態(tài)為傳輸狀態(tài)
while( (DMA_SEND_OK ==0 ) || (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER));
printf("WriteBlocks Successfullyn");
for(i=0; i< SDBUF_SIZE; i++)
{
printf("%d ",SDBUF_TX[i]);
}
printf("rn");
}
else
{
printf("WriteBlocks Failedn");
}
/*------------------- SD DMA 讀測試-------------------------------------*/
DMA_RCV_OK = 0;//設(shè)置讀取完成標(biāo)志位為0,完成時為1
if(HAL_SD_ReadBlocks_DMA(&hsd, SDBUF_RX, 0, 1) == HAL_OK)
{
while( (DMA_RCV_OK ==0) || (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER));
printf("ReadBlocks Successfullyn");
for(i=0; i< SDBUF_SIZE; i++)
{
printf("%d ",SDBUF_RX[i]);
}
printf("rn");
}
else
{
printf("ReadBlocks Failedn");
}
while (1){}
}
//sdio.c
extern uint8_t DMA_SEND_OK, DMA_RCV_OK;
//發(fā)送完成中斷處理
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
{
DMA_SEND_OK = 1;
}
//接收完成中斷處理
void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
{
DMA_RCV_OK = 1;
}
-
控制器
+關(guān)注
關(guān)注
112文章
16382瀏覽量
178333 -
嵌入式系統(tǒng)
+關(guān)注
關(guān)注
41文章
3593瀏覽量
129527 -
適配器
+關(guān)注
關(guān)注
8文章
1956瀏覽量
68061 -
SD卡
+關(guān)注
關(guān)注
2文章
565瀏覽量
63931 -
FIFO存儲
+關(guān)注
關(guān)注
0文章
103瀏覽量
6000
發(fā)布評論請先 登錄
相關(guān)推薦
評論