1. 程式人生 > >STM32L4新版HAL庫SDIO(DMA)、FatFs使用教程(二)

STM32L4新版HAL庫SDIO(DMA)、FatFs使用教程(二)

  • 使用DMA控制SDIO

上一節已經成功使用普通SDIO模式驅動起SD卡了,但是使用FreeRtos時,CubeMX會強制要求使用DMA模式。下面介紹以DMA模式驅動SDIO的方法。

  1. 首先,開啟CubeMX配置好的檔案STM32L476RGT6_SDIO.ioc。
  2. 到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、下載測試,實驗成功。