STM32L4新版HAL庫SDIO(DMA)、FatFs使用教程(二)
- 使用DMA控制SDIO
上一節已經成功使用普通SDIO模式驅動起SD卡了,但是使用FreeRtos時,CubeMX會強制要求使用DMA模式。下面介紹以DMA模式驅動SDIO的方法。
- 首先,開啟CubeMX配置好的檔案STM32L476RGT6_SDIO.ioc。
- 到configuration選項卡中,開啟SDMMC1,再到DMA Settings選項卡,這裡我們新增DMA通道。
這裡有三個選擇:SDMMC1、SDMMC1_RX、SDMMC1_TX。如圖所示,這裡要稍微說一下,不同系列的晶片這裡是不同的,例如F103系列,這裡就只有一個選項SDIO。F4系列有兩個選項SDMMC1_RX、SDMMC1_TX,這樣怎麼選呢?如果是F1系列,只有一個選項,代表這個DMA是傳送接收復用的。如果是F4系列,代表DMA是RX、TX分開通道的。本例中使用的是L4系列,經過測試,複用和收發分開使用均可以。
文中只介紹收發DMA通道分開使用的方式,複用方式是隻選SDMMC1這一個就夠了,注意的是如果是收發複用通道,每次使用DMA收發函式之前都要重新配置DMA引數並初始化,主要配置DMA資料方向記憶體到外設還是外設到記憶體,相關函式可參考第三節的SD_DMAConfigRx和SD_DMAConfigTx函式內容。
配置好DMA後如圖所示,注意紅框中的部分。
3、開啟SDMMC中斷。如圖所示。
4、開啟NVIC選項卡配置中斷。配置DMA通道低於SDIO的中斷優先順序。如圖,配置DMA為2。
5、生成程式碼,開啟工程。
開啟“main.c”,找到測試程式碼,將原來的SD_Write_Read_Test(void)函式刪除,替換為DMA模式,如下程式碼。也可以直接替換sd_status = HAL_SD_WriteBlocks_DMA(&hsd1,(uint8_t *)Buffer_Block_Tx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS);
和
sd_status = HAL_SD_ReadBlocks_DMA(&hsd1,(uint8_t *)Buffer_Block_Rx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS);語句。
/** * 函式功能: SD卡讀寫測試 * 輸入引數: 無 * 返 回 值: 無 * 說 明: 無 */ void SD_Write_Read_Test(void) { int i,j = 0; /* 填充資料到寫快取 */ Fill_Buffer(Buffer_Block_Tx,BLOCK_SIZE*NUMBER_OF_BLOCKS, 0x6666); /* 往SD卡寫入資料 */ sd_status = HAL_SD_WriteBlocks_DMA(&hsd1,(uint8_t *)Buffer_Block_Tx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS); printf("write status:%d\r\n",sd_status); HAL_Delay(500); /* 從SD卡讀取資料 */ sd_status = HAL_SD_ReadBlocks_DMA(&hsd1,(uint8_t *)Buffer_Block_Rx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS); printf("read status:%d\r\n",sd_status); /* 比較資料 */ test_status = Buffercmp(Buffer_Block_Tx, Buffer_Block_Rx, BLOCK_SIZE*NUMBER_OF_BLOCKS/4); //比較 if(test_status == PASSED) { printf("》讀寫測試成功!\r\n" ); for(i=0;i<BLOCK_SIZE*NUMBER_OF_BLOCKS/4;i++) { if(j==8) { printf("\r\n"); j=0; } printf("%08x ",Buffer_Block_Rx[i]); j++; } printf("\r\n"); } else printf("》讀寫測試失敗!\r\n " ); }
6、下載測試,實驗成功。