国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

STM32CubeMX教程27 SDIO - 讀寫SD卡

這篇具有很好參考價值的文章主要介紹了STM32CubeMX教程27 SDIO - 讀寫SD卡。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

1、準(zhǔn)備材料

正點(diǎn)原子stm32f407探索者開發(fā)板V2.4

STM32CubeMX軟件(Version 6.10.0)

keil μVision5 IDE(MDK-Arm)

ST-LINK/V2驅(qū)動

邏輯分析儀nanoDLA

野火DAP仿真器

XCOM V2.6串口助手

2、實(shí)驗(yàn)?zāi)繕?biāo)

使用STM32CubeMX軟件配置STM32F407開發(fā)板SDIO讀寫4線SD卡,實(shí)現(xiàn)輪詢方式讀寫SD卡、以中斷方式讀取SD卡和以DMA方式讀取SD卡

3、輪詢方式讀取SD卡流程

3.0、前提知識

安全數(shù)碼卡(Secure Digital Memory Card),簡稱SD卡,是嵌入式設(shè)備上常用的一種存儲介質(zhì),通??梢詫D卡分為標(biāo)準(zhǔn)SD卡、miniSD卡和microSD卡(TF卡)三種類型,每種卡形狀大小不一,除標(biāo)準(zhǔn)SD卡卡身上擁有一個寫保護(hù)開關(guān)外,其他的功能三張卡一致,如今miniSD卡正逐漸被microSD卡所取代,如下圖所示為三種不同類型SD卡形狀 (注釋1)

按照SD卡容量大小的不同可以將其分為SD、SDHC、SDXC等型號,按照SD卡讀寫機(jī)制速度的不同又可以將其分為Standard、High-speed、UHS-I等型號,具體如下表所示

STM32F407提供了一個SDIO接口可以直接通過HAL庫來驅(qū)動1/4位總線寬度的SD卡或1/4/8位總線寬度的多媒體卡,其完全兼容SD卡規(guī)范版本2.0,但只支持高速SD卡,也即與SD卡進(jìn)行數(shù)據(jù)傳輸最大速度為25MHz

SDIO由APB2接口和SDIO適配器兩部分組成,SDIO適配器提供了驅(qū)動SD/MMC卡的全部功能,APB2接口則可以訪問SDIO適配器寄存器在適當(dāng)時候向內(nèi)核發(fā)起中斷/DMA請求

SDIO適配器由48MHz的SDIOCLK驅(qū)動,根據(jù)SDIOCLK時鐘頻率、 SDIO Clock divider bypass 參數(shù)和 SDIOCLK clock divide factor 參數(shù)就可以確定與SD卡通信時SDIO_CLK的時鐘頻率,當(dāng)時鐘分頻器旁路使能時,SDIO_CLK=SDIOCLK;當(dāng)時鐘分頻器旁路不使能時,SDIO_CLK=SDIOCLK / (2+時鐘分頻因子);

根據(jù)上面的描述,由于STM32F407的SDIO只支持高速SD卡,因此時鐘分頻器旁路常常不使能,這樣當(dāng)時鐘分頻因子為0時,SDIO_CLK則達(dá)到最大速度48MHz / 2 = 24Mhz,但在實(shí)際的使用中往往稍微降低該時鐘頻率,否則可能會出現(xiàn)讀寫SD卡失敗的現(xiàn)象

另外值得提醒的是SD卡初始化的時候應(yīng)該以不超過400KHz的速率,1位總線寬度進(jìn)行初始化,否則將初始化失敗

如下圖所示為STM32F407內(nèi)部的SDIO接口結(jié)構(gòu)框圖 (注釋2)

筆者使用的開發(fā)板上SD卡槽設(shè)計為了4位總線寬度,在硬件設(shè)計時需要注意MCU與SD卡通信的1/4根數(shù)據(jù)線SDIO_D0/1/2/3和命令線SDIO_CMD均需外部上拉,硬件原理圖如下圖所示

3.1、CubeMX相關(guān)配置

3.1.0、工程基本配置

打開STM32CubeMX軟件,單擊ACCESS TO MCU SELECTOR選擇開發(fā)板MCU(選擇你使用開發(fā)板的主控MCU型號),選中MCU型號后單擊頁面右上角Start Project開始工程,具體如下圖所示

開始工程之后在配置主頁面System Core/RCC中配置HSE/LSE晶振,在System Core/SYS中配置Debug模式,具體如下圖所示

詳細(xì)工程建立內(nèi)容讀者可以閱讀“STM32CubeMX教程1 工程建立”

3.1.1、時鐘樹配置

當(dāng)在STM32CubeMX中啟用SDIO功能后,時鐘樹中48MHz時鐘便可以進(jìn)行調(diào)節(jié),該時鐘一般如其名字一樣配置為48MHz即可,也即將Main PLL(主鎖相環(huán))的Q參數(shù)調(diào)節(jié)為7即可,其他HCLK、PCLK1和PCLK2時鐘仍然設(shè)置為STM32F407能達(dá)到的最高時鐘頻率,具體如下圖所示

3.1.2、外設(shè)參數(shù)配置

本實(shí)驗(yàn)需要初始化開發(fā)板上WK_UP、KEY2、KEY1和KEY0用戶按鍵,具體配置步驟請閱讀“STM32CubeMX教程3 GPIO輸入 - 按鍵響應(yīng)”

本實(shí)驗(yàn)需要初始化USART1作為輸出信息渠道,具體配置步驟請閱讀“STM32CubeMX教程9 USART/UART 異步通信”

單擊Pinout & Configuration頁面左邊功能分類欄目Connectivity/SDIO,將其模式選擇為4位寬總線SD卡

Clock transition on which the bit capture is made (時鐘跳變沿捕獲數(shù)據(jù)配置):數(shù)據(jù)捕獲邊沿設(shè)置,可設(shè)置為上升沿/下降沿

SDIO Clock divider bypass (時鐘分頻器旁路使能):使能該參數(shù)時,SDIO_CLK=SDIOCLK;否則SDIO_CLK頻率由時鐘分頻因子決定

SDIO Clock output enable when the bus is idle (空閑模式時鐘輸出使能):節(jié)能模式,此實(shí)驗(yàn)不使能

SDIO hardware flow control (硬件流控):設(shè)置是否使能SDIO的硬件流控,此處不使能

SDIOCLK clock divide factor (時鐘分頻因子):當(dāng)不使能時鐘分頻器旁路時,SDIO_CLK=SDIOCLK / (2+時鐘分頻因子)

SDIO驅(qū)動4位寬總線SD卡的參數(shù)配置大多按照默認(rèn)參數(shù)配置即可,但是要注意SD卡讀寫頻率過高可能會導(dǎo)致讀寫失敗,因此這里設(shè)置SD_CLK頻率為8MHz,另外需要注意默認(rèn)的SDIO復(fù)用引腳和開發(fā)板上的實(shí)際控制SD的引腳是否一致,具體配置如下圖所示

3.1.3、外設(shè)中斷配置

輪詢方式讀寫SD卡無需配置中斷

3.2、生成代碼

3.2.0、配置Project Manager頁面

單擊進(jìn)入Project Manager頁面,在左邊Project分欄中修改工程名稱、工程目錄和工具鏈,然后在Code Generator中勾選“Gnerate peripheral initialization as a pair of 'c/h' files per peripheral”,最后單擊頁面右上角GENERATE CODE生成工程,具體如下圖所示

詳細(xì)Project Manager配置內(nèi)容讀者可以閱讀“STM32CubeMX教程1 工程建立”實(shí)驗(yàn)3.4.3小節(jié)

3.2.1、外設(shè)初始化調(diào)用流程

在main.c文件main()函數(shù)中調(diào)用MX_SDIO_SD_Init()對SDIO參數(shù)配置,并調(diào)用HAL_SD_Init()函數(shù)對SD卡初始化,最后將SD卡切換到4位寬總線模式

在stm32f4xx_hal_sd.c文件HAL_SD_Init()中調(diào)用HAL_SD_MspInit()函數(shù)對SDIO時鐘使能和所使用到的引腳功能復(fù)用,如果配置了中斷或DMA,該函數(shù)中還會相應(yīng)的出現(xiàn)NVIC/DMA相關(guān)配置,最后在真正的SD卡初始化函數(shù)HAL_SD_InitCard()中對SD卡初始化完畢

具體外設(shè)初始化函數(shù)調(diào)用流程如下圖所示

初始化配置中時鐘分頻因子為4,SD_CLK=8MHz,為什么SD卡還可以初始化成功?

這里讀者需要搞清楚真正對SD卡初始化時使用的參數(shù)配置是不是我們設(shè)置的參數(shù),上面提到真正的SD卡初始化函數(shù)為HAL_SD_InitCard(),進(jìn)入該函數(shù)發(fā)現(xiàn)實(shí)際初始化SD卡時用到的并不是用戶配置的參數(shù),而是使用的默認(rèn)初始化參數(shù),這里時鐘分頻因子被設(shè)置為了0x76,也即118,根據(jù)上面提到的公式計算可知48MHz / (118 + 2) = 400KHz,滿足SD卡的初始化頻率,具體如下圖所示

3.2.2、外設(shè)中斷調(diào)用流程

輪詢方式讀寫SD卡無配置中斷

3.2.3、添加其他必要代碼

筆者使用的STM32CubeMX版本為6.10.0,在生成的SDIO初始化函數(shù)MX_SDIO_SD_Init()中需要將參數(shù)配置中的SD卡數(shù)據(jù)總線寬度從默認(rèn)的4位手動修改為1位(STM32CubeMX軟件BUG?),在SD卡初始化時應(yīng)該以不超過400KHz的速率,1位總線寬度進(jìn)行初始化,如果不修改這里SD卡將無法成功初始化,如下圖所示

在sdio.c中添加SD卡讀、寫、擦除和輸出SD卡信息測試函數(shù)

/*顯示SD卡的信息*/
void SDCard_ShowInfo(void)
{
	//SD卡信息結(jié)構(gòu)體變量
	HAL_SD_CardInfoTypeDef cardInfo;  
	HAL_StatusTypeDef res = HAL_SD_GetCardInfo(&hsd, &cardInfo);

	if(res!=HAL_OK)
	{
		printf("HAL_SD_GetCardInfo() error\r\n");
		return;
	}

	printf("\r\n*** HAL_SD_GetCardInfo() info ***\r\n");
	printf("Card Type= %d\r\n", cardInfo.CardType);
	printf("Card Version= %d\r\n", cardInfo.CardVersion);
	printf("Card Class= %d\r\n", cardInfo.Class);
	printf("Relative Card Address= %d\r\n", cardInfo.RelCardAdd);
	printf("Block Count= %d\r\n", cardInfo.BlockNbr);
	printf("Block Size(Bytes)= %d\r\n", cardInfo.BlockSize);
	printf("LogiBlockCount= %d\r\n", cardInfo.LogBlockNbr);
	printf("LogiBlockSize(Bytes)= %d\r\n", cardInfo.LogBlockSize);
	printf("SD Card Capacity(MB)= %d\r\n", cardInfo.BlockNbr>>1>>10);
}

//獲取SD卡當(dāng)前狀態(tài)
void SDCard_ShowStatus(void)
{
	//SD卡狀態(tài)結(jié)構(gòu)體變量
	HAL_SD_CardStatusTypeDef cardStatus;
	HAL_StatusTypeDef res = HAL_SD_GetCardStatus(&hsd, &cardStatus);

	if(res!=HAL_OK)
	{
		printf("HAL_SD_GetCardStatus() error\r\n");
		return;
	}

	printf("\r\n*** HAL_SD_GetCardStatus() info ***\r\n");
	printf("DataBusWidth= %d\r\n", cardStatus.DataBusWidth);
	printf("CardType= %d\r\n", cardStatus.CardType);
	printf("SpeedClass= %d\r\n", cardStatus.SpeedClass);
	printf("AllocationUnitSize= %d\r\n", cardStatus.AllocationUnitSize);
	printf("EraseSize= %d\r\n", cardStatus.EraseSize);
	printf("EraseTimeout= %d\r\n", cardStatus.EraseTimeout);
}

/*SD卡擦除測試*/
void SDCard_EraseBlocks(void)
{
	uint32_t BlockAddrStart=0;
	uint32_t BlockAddrEnd=10;
	
	printf("\r\n*** Erasing blocks ***\r\n");

	if(HAL_SD_Erase(&hsd, BlockAddrStart, BlockAddrEnd)==HAL_OK)
		printf("Erasing blocks,OK\r\n");
	else
		printf("Erasing blocks,fail\r\n");

	HAL_SD_CardStateTypeDef cardState=HAL_SD_GetCardState(&hsd);
	printf("GetCardState()= %d\r\n", cardState);

	while(cardState != HAL_SD_CARD_TRANSFER)
	{
		HAL_Delay(1);
		cardState=HAL_SD_GetCardState(&hsd);
	}
	printf("Blocks 0-10 is erased.\r\n");
}

/*SD卡寫入測試函數(shù)*/
void SDCard_TestWrite(void)
{
	printf("\r\n*** Writing blocks ***\r\n");
	
	// BLOCKSIZE為512,在stm32f4xx_hal_sd.h中被定義
	uint8_t pData[BLOCKSIZE]="Hello, welcome to UPC\0";  
	uint32_t BlockAddr=5; 	
	uint32_t BlockCount=1; 
	uint32_t TimeOut=1000;	

	if(HAL_SD_WriteBlocks(&hsd,pData,BlockAddr,BlockCount,TimeOut) == HAL_OK)
	{
		printf("Write to block 5, OK\r\n");
		printf("The string is: %s\r\n", pData);
	}
	else
	{
		printf("Write to block 5, fail ***\r\n");
		return;
	}

	for(uint16_t i=0;i<BLOCKSIZE; i++)
		pData[i]=i; 	

	BlockAddr=6;
	if(HAL_SD_WriteBlocks(&hsd,pData,BlockAddr,BlockCount,TimeOut) == HAL_OK) 
	{
		printf("Write block 6, OK\r\n");
		printf("Data in [10:15] is: ");
		for (uint16_t j=11; j<=15;j++)
		{
			printf("%d,", pData[j]);
		}
		printf("\r\n");
	}
	else
		printf("Write to block 6, fail ***\r\n");
}

/*SD卡讀取測試函數(shù)*/
void SDCard_TestRead(void)	
{
	printf("\r\n*** Reading blocks ***\r\n");

	uint8_t pData[BLOCKSIZE];
	uint32_t BlockAddr=5;
	uint32_t BlockCount=1;
	uint32_t TimeOut=1000;

	if(HAL_SD_ReadBlocks(&hsd,pData,BlockAddr,BlockCount,TimeOut) == HAL_OK)
	//if(HAL_SD_ReadBlocks_IT(&hsd,pData,BlockAddr,BlockCount) == HAL_OK)
	{
		printf("Read block 5, OK\r\n");
		printf("The string is: %s\r\n", pData);
	}
	else
	{
		printf("Read block 5, fail ***\r\n");
		return;
	}

	BlockAddr=6;
	if(HAL_SD_ReadBlocks(&hsd,pData,BlockAddr,BlockCount,TimeOut)== HAL_OK)
	//if(HAL_SD_ReadBlocks_IT(&hsd,pData,BlockAddr,BlockCount) == HAL_OK)
	{
		printf("Read block 6, OK\r\n");
		printf("Data in [10:15] is: ");

		for (uint16_t j=11; j<=15;j++)
		{
			printf("%d,", pData[j]);
		}
		printf("\r\n");
	}
}

在sdio.h中聲明定義的這些測試函數(shù)

/*在sdio.h中聲明*/
void SDCard_TestRead(void);
void SDCard_TestWrite(void);
void SDCard_ShowInfo(void);
void SDCard_EraseBlocks(void);

在main.c文件主循環(huán)中添加按鍵邏輯控制程序,WK_UP按鍵按下輸出SD卡信息,KEY2按鍵按下擦除SD卡塊0-10,KEY1按鍵按下測試SD卡寫功能,KEY0按鍵按下測試SD卡讀功能

具體源代碼如下所示

/*WK_UP按鍵按下*/
if(HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin) == GPIO_PIN_SET)
{
	HAL_Delay(50);
	if(HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin) == GPIO_PIN_SET)
	{
		SDCard_ShowInfo();
		while(HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin));
	}
}

/*KEY2按鍵按下*/
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == GPIO_PIN_RESET)
{
	HAL_Delay(50);
	if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == GPIO_PIN_RESET)
	{
		SDCard_EraseBlocks();
		while(!HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin));
	}
}

/*KEY1按鍵按下*/
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_RESET)
{
	HAL_Delay(50);
	if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_RESET)
	{
		SDCard_TestWrite();
		while(!HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin));
	}
}

/*KEY0按鍵按下*/
if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == GPIO_PIN_RESET)
{
	HAL_Delay(50);
	if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == GPIO_PIN_RESET)
	{
		SDCard_TestRead();
		while(!HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin));
	}
}

4、燒錄驗(yàn)證

燒錄程序,開發(fā)板復(fù)位后按下WK_UP按鍵會輸出SD卡信息,按下KEY2按鍵會擦除SD卡的塊0-10數(shù)據(jù),按下KEY0按鍵會讀取SD卡塊5和塊6的數(shù)據(jù),按下KEY1按鍵會寫入一段字符串到SD卡塊5,寫入塊6從1-256整形數(shù)字,具體串口輸出信息如下圖所示

5、中斷方式讀取SD卡流程簡述

5.1、CubeMX相關(guān)配置

工程、時鐘樹、外設(shè)參數(shù)等配置與輪詢方式讀取SD卡一致,中斷方式讀取SD卡只需要在CubeMX軟件中啟動SDIO的全局中斷

在Pinout & Configuration頁面左邊System Core/NVIC中勾選SDIO全局中斷,然后選擇合適的中斷優(yōu)先級即可,如下圖所示

5.2、生成代碼

修改STM32CubeMX工程重新生成工程代碼后,讀者應(yīng)注意再次手動修改MX_SDIO_SD_Init()函數(shù)中SD卡數(shù)據(jù)總線寬度從默認(rèn)的4位手動修改為1位

在sdio.c中增加以中斷方式讀寫SD卡的測試函數(shù),具體代碼如下所示

/*SD卡中斷寫入測試函數(shù)*/
void SDCard_TestWrite_IT(void)
{
	printf("\r\n*** IT Writing blocks ***\r\n");
	uint32_t BlockCount=1; 
	uint16_t BlockAddr=5;
	
	HAL_SD_WriteBlocks_IT(&hsd, TX, BlockAddr, BlockCount);
}

/*SD卡中斷讀取測試函數(shù)*/
void SDCard_TestRead_IT(void)	
{
	printf("\r\n*** IT Reading blocks ***\r\n");
	uint32_t BlockCount=1;
	uint16_t BlockAddr=5;
	
	HAL_SD_ReadBlocks_IT(&hsd, RX, BlockAddr, BlockCount);
}

在sdio.c中新增加SD卡Tx/Rx傳輸完成回調(diào)函數(shù)HAL_SD_TxCpltCallback()和HAL_SD_RxCpltCallback(),具體代碼如下所示

/*SD Tx傳輸完成回調(diào)*/
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
{
	printf("IT Write to block 5, OK\r\n");
	printf("The string is: %s\r\n", TX);
}

/*SD Rx傳輸完成回調(diào)*/
void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
{
	printf("IT Read block 5, OK\r\n");
	printf("The string is: %s\r\n", RX);
}

在sdio.c中定義全部變量發(fā)送緩存數(shù)組TX和接收緩存數(shù)組RX,并在sdio.h中聲明修改后的中斷方式的SD卡寫入測試函數(shù)和SD卡讀取測試函數(shù),源代碼如下

/*sdio.c中定義的發(fā)送、接收緩存數(shù)組*/
uint8_t TX[BLOCKSIZE] = "Hello, welcome to UPC\0";  
uint8_t RX[BLOCKSIZE];  

/*sdio.h中對函數(shù)聲明*/
void SDCard_TestRead_IT(void);
void SDCard_TestWrite_IT(void);

最后在main.c文件主循環(huán)中實(shí)現(xiàn)與輪詢讀寫SD時一致的按鍵邏輯程序,并用修改后的以中斷方式讀寫SD卡的函數(shù)替換以輪詢方式讀寫SD卡的函數(shù)即可

5.3、燒錄驗(yàn)證

燒錄程序,開發(fā)板復(fù)位后按下WK_UP按鍵會輸出SD卡信息,按下KEY2按鍵會擦除SD卡的塊0-10數(shù)據(jù),與輪詢方式讀寫SD卡時現(xiàn)象一致

按下KEY0按鍵以中斷方式讀取SD卡的塊5數(shù)據(jù),讀取完成后會進(jìn)入Rx傳輸完成回調(diào)中,在該回調(diào)函數(shù)中會從串口輸出讀取到的SD卡塊5的數(shù)據(jù)

按下KEY1按鍵會以中斷方式寫入一段字符串到SD卡塊5,寫入完成后會進(jìn)入Tx傳輸完成回調(diào)中,在該回調(diào)函數(shù)中會從串口輸出寫入到SD卡塊5中的數(shù)據(jù)

具體串口輸出信息如下圖所示

6、DMA方式讀取SD卡流程簡述

6.1、CubeMX相關(guān)配置

工程、時鐘樹、外設(shè)參數(shù)等配置與輪詢方式讀取SD卡一致,以DMA方式讀取SD卡只需要在CubeMX軟件中增加SDIO的DMA請求即可

在Pinout & Configuration頁面單擊Connectivity/SDIO頁面,在Configuration配置頁面中點(diǎn)擊DMA Settings選項(xiàng)卡對SDIO的DMA進(jìn)行配置,單擊ADD增加SDIO的RX/TX兩個DMA請求,SDIO的兩個DMA請求除了內(nèi)存地址遞增可以設(shè)置外,其他的包括Mode、Use Fifo、Data Width和Burst Size等參數(shù)都不可以設(shè)置

對DMA參數(shù)不理解的可以閱讀”STM32CubeMX教程12 DMA 直接內(nèi)存讀取“實(shí)驗(yàn),SDIO的具體DMA配置參數(shù)如下圖所示

在System Core/NVIC中勾選SDIO全局中斷、DMA2 stream3 全局中斷和 DMA2 stream6 全局中斷,然后選擇合適的中斷優(yōu)先級即可,如下圖所示

6.2、生成代碼

修改STM32CubeMX工程重新生成工程代碼后,讀者應(yīng)注意再次手動修改MX_SDIO_SD_Init()函數(shù)中SD卡數(shù)據(jù)總線寬度從默認(rèn)的4位手動修改為1位

在sdio.c中增加以DMA方式讀寫SD卡的測試函數(shù),具體代碼如下所示

/*SD卡DMA寫入測試函數(shù)*/
void SDCard_TestWrite_DMA(void)
{
	printf("\r\n*** DMA Writing blocks ***\r\n");
	uint32_t BlockCount=1; 
	uint16_t BlockAddr=6;
	
	for(uint16_t i=0;i<BLOCKSIZE; i++)
		TX[i]=i; 
	
	HAL_SD_WriteBlocks_DMA(&hsd, TX, BlockAddr, BlockCount);
}

/*SD卡DMA讀取測試函數(shù)*/
void SDCard_TestRead_DMA(void)	
{
	printf("\r\n*** DMA Reading blocks ***\r\n");
	uint32_t BlockCount=1;
	uint16_t BlockAddr=6;
	
	HAL_SD_ReadBlocks_DMA(&hsd, RX, BlockAddr, BlockCount);
}

在sdio.h中對增加的函數(shù)聲明

/*sdio.h中對函數(shù)聲明*/
void SDCard_TestWrite_DMA(void);
void SDCard_TestRead_DMA(void);

DMA的回調(diào)函數(shù)使用的是外設(shè)的中斷回調(diào)函數(shù)

當(dāng)啟用了SDIO TX DMA請求和SDIO全局中斷,并以 HAL_SD_WriteBlocks_DMA() 寫入SD卡塊數(shù)據(jù)完成之后,會調(diào)用傳輸完成回調(diào) HAL_SD_TxCpltCallback()

當(dāng)啟用了SDIO RX DMA請求和SDIO全局中斷,并以 HAL_SD_ReadBlocks_DMA() 從SD卡塊讀取數(shù)據(jù)完畢之后,會調(diào)用讀取完成回調(diào)函數(shù) HAL_SD_RxCpltCallback()

故直接重新實(shí)現(xiàn)HAL_SD_RxCpltCallback/HAL_SD_TxCpltCallback兩個函數(shù)即可,源代碼如下所示

/*DMA Tx傳輸完成回調(diào)*/
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
{
		printf("DMA Write to block 6, OK\r\n");
		printf("Data in [10:15] is: ");

		for (uint16_t j=10; j<=15;j++)
		{
			printf("%d,", TX[j]);
		}
		printf("\r\n");
}

/*DMA Rx傳輸完成回調(diào)*/
void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
{
		printf("DMA Read block 6, OK\r\n");
		printf("Data in [10:15] is: ");

		for (uint16_t j=10; j<=15;j++)
		{
			printf("%d,", RX[j]);
		}
		printf("\r\n");
}

最后在main.c文件主循環(huán)中實(shí)現(xiàn)與輪詢讀寫SD時一致的按鍵邏輯程序,并用修改后的以DMA方式讀寫SD卡的函數(shù)替換以中斷方式讀寫SD卡的函數(shù)即可

6.3、實(shí)驗(yàn)現(xiàn)象

燒錄程序,開發(fā)板復(fù)位后按下WK_UP按鍵會輸出SD卡信息,按下KEY2按鍵會擦除SD卡的塊0-10數(shù)據(jù),與輪詢方式讀寫SD卡時現(xiàn)象一致

按下KEY0按鍵以DMA的方式讀取SD卡塊6數(shù)據(jù),讀取完成后會進(jìn)入Rx傳輸完成回調(diào)中,在該回調(diào)函數(shù)中會從串口輸出讀取到的SD卡塊6的數(shù)據(jù)

按下KEY1按鍵會以DMA的方式寫入1-256的數(shù)字到SD卡塊6(一個字節(jié)寫入一個數(shù)字),寫入完成后會進(jìn)入Tx傳輸完成回調(diào)中,在該回調(diào)函數(shù)中會從串口輸出寫入到SD卡塊6中的數(shù)據(jù)

具體串口輸出信息如下圖所示

7、常用函數(shù)

/*讀塊*/
HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)

/*寫塊*/
HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)

/*擦除塊*/
HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)

/*獲取SD卡信息*/
HAL_StatusTypeDef HAL_SD_GetCardInfo(SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypeDef *pCardInfo)

/*獲取SD卡狀態(tài)*/
HAL_StatusTypeDef HAL_SD_GetCardStatus(SD_HandleTypeDef *hsd, HAL_SD_CardStatusTypeDef *pStatus)

/*以中斷方式讀塊*/
HAL_StatusTypeDef HAL_SD_ReadBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)

/*以中斷方式寫塊*/
HAL_StatusTypeDef HAL_SD_WriteBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)

/*以DMA方式讀塊*/
HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)

/*以DMA方式寫塊*/
HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)

/*SD卡Tx傳輸完成回調(diào)*/
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)

/*SD卡Rx傳輸完成回調(diào)*/
void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)

8、注釋詳解

注釋1:圖片來源自 維基百科-SD卡

注釋2:圖片來源自 STM32F407中文參考手冊 RM009

參考資料

STM32Cube高效開發(fā)教程(高級篇)文章來源地址http://www.zghlxwxcb.cn/news/detail-825225.html

到了這里,關(guān)于STM32CubeMX教程27 SDIO - 讀寫SD卡的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • STM32——SDIO的學(xué)習(xí)(驅(qū)動SD卡)(理論篇)

    STM32——SDIO的學(xué)習(xí)(驅(qū)動SD卡)(理論篇)

    目錄 一、SD卡簡介 1.1歷史 1.2 tf卡和SD卡的區(qū)別 1.3 mmc,emmc,nand,flash的關(guān)系 1.4 SD卡的規(guī)格等級 1.4.1按容量分 1.4.2 class等級 1.4.3 UHS總線模式 1.4.4 UHS速度等級 1.4.5 VSC視頻速度等級 二、SD卡的內(nèi)部結(jié)構(gòu) 三、SDIO的學(xué)習(xí) 3.1 SDIO的主要功能 3.2 SDIO總線拓?fù)??3.3 SDIO功能描述? 3.3.1 SD

    2024年02月16日
    瀏覽(22)
  • stm32在SDIO模式下SD寫入錯誤的問題

    stm32在SDIO模式下SD寫入錯誤的問題

    1、問題描述 使用FAT32 f_write 多次執(zhí)行寫操作時,會報FR_DISK_ERR錯誤,而且是剛開始寫不報錯,寫幾次后會一直報錯。 設(shè)斷點(diǎn)跟蹤到HAL_SD_WriteBlocks中,在調(diào)用SDMMC_CmdWriteMultiBlock時,會報SDMMC_ERROR_TX_UNDERRUN,意思 是Transmit FIFO underrun 2、原因分析 如下圖所示,SDMMC開始寫操作時,首

    2023年04月24日
    瀏覽(31)
  • STM32用一線式驅(qū)動SD NAND,SDIO的一線式驅(qū)動

    STM32用一線式驅(qū)動SD NAND,SDIO的一線式驅(qū)動

    SDIO的一線式和四線式 SDIO(Secure Digital Input/Output)是一種用于在嵌入式系統(tǒng)中連接外部設(shè)備的標(biāo)準(zhǔn)接口。在SDIO標(biāo)準(zhǔn)中,一線式和四線式是指SDIO接口的不同工作模式。 一線式(Single-Line Mode): 工作原理: 在一線式模式下,SDIO接口僅使用單個數(shù)據(jù)線進(jìn)行通信。這個模式通常用

    2024年01月17日
    瀏覽(21)
  • STM32對SD卡的讀、寫、擦除操作(SDIO模式)(DMA)

    STM32對SD卡的讀、寫、擦除操作(SDIO模式)(DMA)

    對于STM32操作SD卡來說,最重要的就算 初始化 、 寫操作 、 讀操作 、 擦除 這幾個操作了。 對于初始化部分上一篇文章已經(jīng)分析,本篇就主要分析寫、讀、擦除操作。 本篇函數(shù)來自于 STM32提供的例程 。參考野火的程序進(jìn)行了解釋,與野火函數(shù)有些不同。 這幾種函數(shù)完成之后

    2023年04月08日
    瀏覽(20)
  • STM32F4X SDIO(七) 例程講解-SD_InitializeCards & SD_GetCardInfo

    STM32F4X SDIO(七) 例程講解-SD_InitializeCards & SD_GetCardInfo

    本節(jié)例程基于 野火電子的STM32F407的SD卡讀寫例程 進(jìn)行講解。上一節(jié)中講解了SD卡上電過程,這節(jié)將會講解一下SD卡的初始化過程,包括 獲取SD卡的CID、CSD和SD卡RCA地址 。 CMD2的作用是 通知所有卡通過CMD線返回CID值 ,CID值包括 SD卡的識別號、制造商ID、OEMID、產(chǎn)品名稱、版本號、

    2024年02月05日
    瀏覽(18)
  • STM32使用STM32CUBEMX配置FreeRTOS+SDIO4bit+FATFS注意事項(xiàng)

    STM32使用STM32CUBEMX配置FreeRTOS+SDIO4bit+FATFS注意事項(xiàng)

    以STM32F429為例: 1、SDIO配置 配置為4bit模式,此配置不是最終配置,后面會在代碼進(jìn)行修改。 2、Fatfs配置 Set Defines 選項(xiàng)中的配置可以默認(rèn),最重要注意Advanced Setting 選擇中的配置,如下 該界面配置默認(rèn)Use dma template是默認(rèn)使能的 ,并且不可以選擇,只能選擇使能,所以需要使

    2024年02月11日
    瀏覽(31)
  • STM32CubeMX教程26 FatFs 文件系統(tǒng) - W25Q128讀寫

    正點(diǎn)原子stm32f407探索者開發(fā)板V2.4 STM32CubeMX軟件(Version 6.10.0) keil μVision5 IDE(MDK-Arm) ST-LINK/V2驅(qū)動 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX軟件配置STM32F407開發(fā)板 使用FatFs中間件通過SPI通信協(xié)議對W25Q128芯片進(jìn)行讀寫等操作 關(guān)于STM32F407使用SPI通信協(xié)議對W25Q128 FLASH芯片讀寫

    2024年02月19日
    瀏覽(29)
  • STM32CubeMX教程29 USB_HOST - 使用FatFs文件系統(tǒng)讀寫U盤

    正點(diǎn)原子stm32f407探索者開發(fā)板V2.4 STM32CubeMX軟件(Version 6.10.0) keil μVision5 IDE(MDK-Arm) ST-LINK/V2驅(qū)動 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX軟件配置STM32F407開發(fā)板 USB_OTG_FS為工作在Mass Storage Host Class(大容量存儲主機(jī)類)模式下的USB_HOST(USB主機(jī)),并使用FatFs文件系統(tǒng)對

    2024年02月19日
    瀏覽(27)
  • SDIO讀寫SD卡速度有多快?

    SDIO讀寫SD卡速度有多快?

    前兩天測試了SPI方式讀寫SD卡的速度《SPI方式讀寫SD卡速度測試》,今天來測試一下SDIO方式的讀寫速度。 測試條件: 單片機(jī):STM32F407VET6 編譯環(huán)境:MDK 5.30+HAL庫 SD卡:閃迪32GB/64GB TF卡 文件系統(tǒng):FatFS R0.12c 之前測試中說過了,非DMA方式速度和資源利用率都不如DMA方式,所以今

    2024年02月02日
    瀏覽(34)
  • 【正點(diǎn)原子STM32連載】 第十章 STM32CubeMX簡介 摘自【正點(diǎn)原子】STM32F103 戰(zhàn)艦開發(fā)指南V1.2

    【正點(diǎn)原子STM32連載】 第十章 STM32CubeMX簡介 摘自【正點(diǎn)原子】STM32F103 戰(zhàn)艦開發(fā)指南V1.2

    1)實(shí)驗(yàn)平臺:正點(diǎn)原子stm32f103戰(zhàn)艦開發(fā)板V4 2)平臺購買地址:https://detail.tmall.com/item.htm?id=609294757420 3)全套實(shí)驗(yàn)源碼+手冊+視頻下載地址: http://www.openedv.com/thread-340252-1-1.html STM32CubeMX是由ST公司開發(fā)的圖形化代碼自動生成工具,能夠快速生成初始化代碼,如配置GPIO,時鐘樹

    2024年01月15日
    瀏覽(32)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包