1.Cubemx
SDIO
USART
使用串口輸出調試信息
FATFS
Clock Configuration
防止堆棧溢出
2.Keil5
新建自定義文件夾及文件
將文件夾添加進工程
新建.c與.h文件,保存到自定義的文件夾,并添加到工程中
bsp_emmc.c
#include "bsp_emmc.h"
#include "ff.h"
#include <stdio.h>
//全局變量
extern MMC_HandleTypeDef hmmc;
extern DMA_HandleTypeDef hdma_sdio_rx;
extern DMA_HandleTypeDef hdma_sdio_tx;//emmc 大小信息結構體
HAL_MMC_CardInfoTypeDef emmc_info;//等待emmc狀態
HAL_StatusTypeDef wait_EMMC_Ready(void)
{
?? ?uint16_t count = EMMC_TIMEOUT; //.h
?? ?while(count--)
?? ?{
?? ??? ?if(HAL_MMC_GetCardState(&hmmc) == HAL_MMC_CARD_TRANSFER)
?? ??? ?{
?? ??? ??? ?return HAL_OK;
?? ??? ?}
?? ??? ?HAL_Delay(1);
?? ?
?? ?}
?? ?return HAL_ERROR;
?? ?
}
//emmc DMA 讀取數據
HAL_StatusTypeDef ?EMMC_ReadBlock_DMA(uint8_t *pData, uint32_t BlockAdd ,uint32_t NumberOfBlocks)
{
?? ?HAL_StatusTypeDef Status = HAL_OK;
?? ?if(HAL_MMC_ReadBlocks_DMA(&hmmc,pData,BlockAdd,NumberOfBlocks) == HAL_OK)
?? ?{
?? ??? ?while(wait_EMMC_Ready() != HAL_OK){} //等待emmc狀態
?? ??? ?Status =HAL_OK;
?? ?}
?? ?return Status;
}//emmc DMA寫入
HAL_StatusTypeDef EMMC_WriteBlock_DMA(uint8_t *pData,uint32_t BlockAdd,uint32_t NumberOfBlocks)
{
?? ?HAL_StatusTypeDef Status = HAL_OK;
?? ?if(wait_EMMC_Ready() != HAL_OK)
?? ?{
?? ??? ?Status = HAL_BUSY;
?? ?}
?? ?if(HAL_MMC_WriteBlocks_DMA(&hmmc,pData,BlockAdd,NumberOfBlocks) != HAL_OK)
?? ?{
?? ??? ?Status = HAL_ERROR;
?? ?}
?? ?return Status;}
//emmc 擦除
HAL_StatusTypeDef EMMC_Erase(uint32_t BlockAdd ,uint32_t NumberOfBlocks)
{
?? ?HAL_StatusTypeDef Status = HAL_ERROR;
?? ?if(HAL_MMC_Erase(&hmmc,BlockAdd,BlockAdd*NumberOfBlocks) == HAL_OK)
?? ?{
?? ??? ?while(wait_EMMC_Ready() != HAL_OK){};
?? ??? ?Status = HAL_OK;
?? ?}
?? ?return Status;
}HAL_StatusTypeDef EMMC_GetInfo(HAL_MMC_CardInfoTypeDef *pData)
{
?? ?HAL_StatusTypeDef Status = HAL_ERROR;
?? ?if(HAL_OK == HAL_MMC_GetCardInfo(&hmmc,pData))
?? ?{
?? ??? ?Status = HAL_OK;
?? ?}
?? ?return Status;
?? ?
}
void EMMC_Getinfo_TEST()
{
?? ?HAL_StatusTypeDef ret =HAL_OK;
?? ?printf("\r\n ---EMMC_Getinfo_Test\r\n");
?? ?ret= EMMC_GetInfo(&emmc_info);
?? ?if(ret == HAL_OK)
?? ?{
?? ??? ?printf("---EMMC_Info: \r\n");
?? ??? ?printf("---CardType: %d\r\n",emmc_info.CardType);
?? ??? ?printf("---Class: %d\r\n",emmc_info.Class);
?? ??? ?printf("---RelCardAdd: %d\r\n",emmc_info.RelCardAdd);
?? ??? ?printf("---BlockNbr: %d\r\n",emmc_info.BlockNbr);
?? ??? ?printf("---BlockSize: %d\r\n",emmc_info.BlockSize);
?? ??? ?printf("---LogBlockNbr: %d\r\n",emmc_info.LogBlockNbr);
?? ??? ?printf("---LogoBlockSize: %d\r\n",emmc_info.LogBlockSize);
?? ?}
?? ?else
?? ?{
?? ??? ?printf("\r\n --- EMMC_GetInfo_ERROR(%d) \r\n",ret);
?? ?}}
//接收數據
uint8_t recvbuf[512];
//發送數據
uint8_t sendbuf[512]={0x22, 0xaa};//讀寫
void EMMC_TEST()
{
?? ?HAL_StatusTypeDef ret = HAL_OK;
?? ?
?? ?printf("\r\n ----EMMC DMA Test \r\n");
?? ?ret=EMMC_ReadBlock_DMA(recvbuf,0,1);
?? ?if(ret ==HAL_OK)
?? ?{
?? ??? ?for(uint16_t i=0;i<hmmc.MmcCard.BlockSize;i++)
?? ??? ?{
?? ??? ??? ?printf("0x%02x",recvbuf[i]);
?? ??? ??? ?if((i%16) == 0&& i!=0)
?? ??? ??? ?{
?? ??? ??? ??? ?printf("EMMC_TEST ?read end\r\n");?? ?
?? ??? ??? ?}?? ?
?? ??? ?}
?? ?}
?? ?//EMMC_WriteBlock_DMA ?燒錄后,注釋這一段?
?? ?//注釋begin
//?? ?ret=EMMC_WriteBlock_DMA(sendbuf,0,1);
//?? ?if(ret ==HAL_OK)
//?? ?{
//?? ??? ?printf("\r\n -----EMMC write_source");
//?? ?}
//?? ?ret= EMMC_ReadBlock_DMA(recvbuf,0,1);
//?? ?printf("\r\n -----ret:%d \r\n",ret);
//?? ?if(ret ==HAL_OK)
//?? ?{
//?? ??? ?for(uint16_t i=0;i<hmmc.MmcCard.BlockSize;i++)
//?? ??? ?{
//?? ??? ??? ?printf("0x%02x",recvbuf[i]);
//?? ??? ??? ?if((i%16) == 0 && i!=0)
//?? ??? ??? ?{
//?? ??? ??? ??? ?printf("\r\n");//?? ??? ??? ?}
//?? ??? ?}
//?? ?
//?? ?}
?? ?//注釋end
?? ?
}
//EMMC 擦除
void Erase_Test()
{
?? ?HAL_StatusTypeDef ret = HAL_OK;
?? ?
?? ?printf("\r\n ----EMMC Read1 \r\n");
?? ?ret=EMMC_ReadBlock_DMA(recvbuf,0,1);
?? ?
?? ?if(ret == HAL_OK)
?? ?{
?? ??? ?for(uint16_t i=0;i<hmmc.MmcCard.BlockSize;i++)
?? ??? ?{
?? ??? ??? ?printf("0x%02x",recvbuf[i]);
?? ??? ??? ?if((i%16) == 0 && i!=0)
?? ??? ??? ?{
?? ??? ??? ??? ?printf("---\r\n");
?? ??? ??? ?}
?? ??? ?}
?? ?}
?? ?printf("\r\n ---Erase_Test\r\n");
?? ?if(HAL_OK == EMMC_Erase(0x00,1))
?? ?{
?? ??? ?printf("\r\n -----EMMC_OK\r\n");
?? ?}
?? ?else
?? ?{
?? ??? ?printf("\r\n ------EMMC_Error");
?? ?}
?? ?
?? ?if(ret ==HAL_OK)
?? ?{
?? ??? ?for(uint16_t i=0;i<hmmc.MmcCard.LogBlockSize;i++)
?? ??? ?{
?? ??? ??? ?printf("0x%02x",recvbuf[i]);
?? ??? ??? ?if(i%16 == 0 && i!=0)
?? ??? ??? ?{
?? ??? ??? ??? ?printf("\r\n");
?? ??? ??? ?}
?? ??? ?}
?? ?}
}FATFS fs; //Fatfs系統對象
FIL fnew; //文件對象
FRESULT res_sd; //文件操作結果
UINT fnum; //文件成功讀寫數量
BYTE ReadBuffer[1024]={0}; //讀緩沖區
BYTE WriteBuffer[]="123456\r\n"; //寫緩沖區
BYTE work[_MAX_SS];//文件系統讀寫測試函數
void EMMC_FATFS_TEST(void)
{
?? ?printf("\r\n讀寫測試\r\n");
?? ?
?? ?res_sd=f_mount(&fs,"0",1);
//格式化測試
?? ?//若沒有文件系統就格式化 創建文件系統
?? ?if(res_sd == FR_NO_FILESYSTEM)
?? ?{
?? ??? ?printf("\r\n ?無文件系統,即將格式化");
?? ??? ?//格式化
?? ??? ?res_sd=f_mkfs("0:",FS_FAT32,0,work,sizeof(work));
?? ??? ?if(res_sd == FR_OK)
?? ??? ?{
?? ??? ??? ?printf("\r\n 格式化成功\r\n");
?? ??? ??? ?//取消掛載
?? ??? ??? ?res_sd =f_mount(NULL ,"0:",1);
?? ??? ??? ?//重新掛載
?? ??? ??? ?res_sd = f_mount(&fs,"0",1);
?? ??? ?}
?? ??? ?else
?? ??? ?{
?? ??? ??? ?printf("\r\n--格式化失敗--\r\n");
?? ??? ??? ?return;
?? ??? ?}
?? ?}?? ?else if(res_sd != FR_OK)
?? ?{
?? ??? ?printf("掛載文件系統失敗,(%d)\r\n",res_sd);
?? ??? ?printf("可能原因:初始化失敗,\r\n");
?? ??? ?return;
?? ?
?? ?}
?? ?else
?? ?{
?? ??? ?printf("\r\n文件系統掛載成功,可進行讀寫測試\r\n");
?? ?}
//--------------------文件系統測試:寫測試--------------
?? ?//打開文件,若文件不存在就創建它
?? ?printf("\r\n--- 即將進入文件寫入測試");
?? ?res_sd = f_open(&fnew ,"0:FatFs.txt",FA_OPEN_ALWAYS|FA_WRITE);
?? ?if(res_sd ==FR_OK)
?? ?{
?? ??? ?printf("打開/創建Fatfs讀寫測試文件.txt文件成功,向文件寫入數據,\r\n");
?? ??? ?//指定存儲區內容寫入到文件
?? ??? ?printf("the fire size is %d",(int)f_size(&fnew));
?? ??? ?f_lseek(&fnew,f_size(&fnew));
?? ??? ?res_sd=f_write(&fnew,WriteBuffer,sizeof(WriteBuffer),&fnum);
?? ?
?? ??? ?if(res_sd == FR_OK)
?? ??? ?{
?? ??? ??? ?printf("--文件寫入成功,寫入字節數據 :%d\n",fnum);
?? ??? ??? ?printf("--寫入數據為:\r\n %s \r\n",WriteBuffer);
?? ??? ?}
?? ??? ?else
?? ??? ?{
?? ??? ??? ?printf("---!!寫入文件失敗:(%d)\n",res_sd);
?? ??? ?}
?? ??? ?//不讀寫了,關閉文件
?? ??? ?f_close(&fnew);
?? ?}
?? ?else
?? ?{
?? ??? ?printf("!!打開文件失敗:(%d)\n",res_sd);
?? ?
?? ?}//--------------文件系統測試:讀測試---------------
?? ?printf("---即將進行文件讀取測試...\r\n");
?? ?res_sd = f_open(&fnew,"0:FatFs.txt",FA_OPEN_ALWAYS|FA_READ);
?? ?if(res_sd == FR_OK)
?? ?{
?? ??? ?printf("----打開文件成功,\r\n");
?? ??? ?res_sd = f_read(&fnew , ReadBuffer,sizeof(ReadBuffer),&fnum);
?? ??? ?if(res_sd ==FR_OK)
?? ??? ?{
?? ??? ??? ?printf("---文件讀取成功,讀取到字節數據: %d\r\n",fnum);
?? ??? ??? ?printf("---d讀取的文件數據為:\r\n %s \r\n",ReadBuffer);
?? ??? ?}
?? ??? ?else
?? ??? ?{
?? ??? ??? ?printf("讀取文件失敗(%d)\r\n",res_sd);
?? ??? ?}
?? ?}
?? ?//不再讀寫,關閉文件
?? ?f_close(&fnew);
?? ?f_mount(NULL,"0:",1);
?? ?printf("取消掛載");
?? ?
}
bsp_emmc.h
#ifndef __BSP_EMMC_H_
#define __BSP_EMMC_H_#include "main.h"
#define EMMC_TIMEOUT 0xffffHAL_StatusTypeDef ?EMMC_ReadBlock_DMA(uint8_t *pData, uint32_t BlockAdd ,uint32_t NumberOfBlocks);
HAL_StatusTypeDef EMMC_WriteBlock_DMA(uint8_t *pData,uint32_t BlockAdd,uint32_t NumberOfBlocks);
HAL_StatusTypeDef EMMC_Erase(uint32_t BlockAdd ,uint32_t NumberOfBlocks);
HAL_StatusTypeDef EMMC_GetInfo(HAL_MMC_CardInfoTypeDef *pData);void EMMC_Getinfo_TEST();
void EMMC_TEST(void);
void Erase_Test(void);
void EMMC_FATFS_TEST(void);#endif
重定義printf
打開Cubemx生成的USART.c
添加
#include <stdio.h>
void _sys_exit(int x)
{
?? ?x=x;
}//重定義fputc函數
int fputc(int ch ,FILE *f)
{
?? ?while((USART1->SR&0x40) == 0){}//滿足此條件循環發送直到發送完畢 ,不滿足則跳轉至下面
?? ??? ?USART1->DR = (uint8_t)ch;
?? ??? ?return ch;
?? ?};
main.c
添加
? ?? ? HAL_Delay(1000);
?? ?EMMC_Getinfo_TEST();
//?? ?EMMC_FATFS_TEST();
使用串口助手查看信息
計算總容量的方法如下:
- 塊數量:
BlockNbr = 61079552
- 每塊大小:
BlockSize = 512
字節
總容量 = 塊數量 × 每塊大小
計算:
61079552×512= = 31268536064 字節
將字節轉換為千字節 (KB):
容量?(KB)=31268536064/1024= 30539776KB
將千字節轉換為兆字節 (MB):
容量?(MB)=30539776/1024} = 29813.5MB
將兆字節轉換為千兆字節 (GB):
容量?(GB)=29813.5/1024≈29.1?GB
因此,總容量約為 29.1 GB。
參考
STM32使用HAL庫驅動EMMC掛載FATFS文件系統_stm32 emmc-CSDN博客