stm32F4掛載emmc以及重定義printf

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 0xffff

HAL_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();

使用串口助手查看信息

計算總容量的方法如下:

  1. 塊數量BlockNbr = 61079552
  2. 每塊大小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博客

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/94932.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/94932.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/94932.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于AI的大模型在S2B2C商城小程序中的應用與定價策略自我評估

摘要&#xff1a;本文聚焦電商行業&#xff0c;結合開源AI大模型與AI智能名片S2B2C商城小程序的技術特性&#xff0c;提出基于行業數據挖掘與自我評估的定價策略。通過分析行業價格分布與銷量占比&#xff0c;結合商品設計、品牌創意度、商品豐富度及內功等評估指標&#xff0c…

中國移動云電腦一體機-創維LB2004_瑞芯微RK3566_2G+32G_開ADB安裝軟件教程

中國移動云電腦一體機-創維LB2004_瑞芯微RK3566_2G32G_開ADB安裝軟件教程簡介&#xff1a;中國移動云電腦一體機-創維LB2004&#xff0c;顯示器是23.8英寸1920x1080分辨率&#xff0c;安卓盒子配置是瑞芯微RK3566-四核-1.8GHz處理器-2G32G&#xff0c;預裝Android11系統。具體操…

普藍自研AutoTrack-4X導航套件平臺適配高校機器人實操應用

在當前高校機器人工程、人工智能、自動化等專業的教學與科研中&#xff0c;師生們常常面臨一個核心痛點&#xff1a;缺乏一套 “開箱即用、可深研、能落地” 的自主移動導航平臺 —— 要么是純仿真環境脫離實際硬件&#xff0c;要么是硬件零散需大量時間搭建&#xff0c;要么是…

2025年工會證考試題庫及答案

一、單選題1.工會法人資格審查登記機關自收到申請登記表之日起(??)日內對有關申請文件進行審查&#xff0c;對審查合格者&#xff0c;辦理登記手續&#xff0c;發放《工會法人資格證書》及其副本和《工會法人法定代表人證書》。A.二十B.十五C.六十D.三十答案:D 解析:第七條基…

【OpenGL】LearnOpenGL學習筆記17 - Cubemap、Skybox、環境映射(反射、折射)

上接&#xff1a;https://blog.csdn.net/weixin_44506615/article/details/150935025?spm1001.2014.3001.5501 完整代碼&#xff1a;https://gitee.com/Duo1J/learn-open-gl | https://github.com/Duo1J/LearnOpenGL 一、立方體貼圖 (Cubemap) 立方體貼圖就是一個包含了6張2…

第十七章 ESP32S3 SW_PWM 實驗

本章將介紹使用 ESP32-S3 LED 控制器(LEDC)。 LEDC 主要用于控制 LED&#xff0c;也可產生PWM信號用于其他設備的控制。該控制器有 8 路通道&#xff0c;可以產生獨立的波形&#xff0c;驅動 RGB LED 等設備。 LED PWM 控制器可在無需 CPU 干預的情況下自動改變占空比&#xff…

Flink CDC如何保障數據的一致性

Flink CDC如何保障數據的一致性 前言 在大規模流處理中&#xff0c;故障是無可避免的。機器會宕機&#xff0c;網絡會抖動。一個可靠的流處理引擎不僅要能高效地處理數據&#xff0c;更要在遇到這些故障時&#xff0c;保證計算結果的正確性。Apache Flink 正是因其強大的容錯機…

Spring Boot 定時任務入門

1. 概述 在產品的色彩斑斕的黑的需求中&#xff0c;有存在一類需求&#xff0c;是需要去定時執行的&#xff0c;此時就需要使用到定時任務。例如說&#xff0c;每分鐘掃描超時支付的訂單&#xff0c;每小時清理一次日志文件&#xff0c;每天統計前一天的數據并生成報表&#x…

學習:uniapp全棧微信小程序vue3后臺(6)

26.實現描述評分標簽的雙向數據綁定 /pages/wallpaper/picadd Array.prototype.splice() splice() 方法就地移除或者替換已存在的元素和/或添加新的元素。 二次確認 展現 確認標簽 刪除標簽 溫故知新&#xff1a; 標簽&#xff1a; 關閉標簽 27.uni-data-select調用云端分類…

Azure Marketplace 和 Microsoft AppSource的區別

微軟的商業應用生態中&#xff0c;Azure Marketplace 和 Microsoft AppSource 是微軟并行的兩個主要“應用市場”&#xff08;Marketplace&#xff09;&#xff0c;它們共同構成了微軟的“商業市場”&#xff08;Commercial Marketplace&#xff09;計劃&#xff0c;但服務的目…

完整實驗命令解析:從集群搭建到負載均衡配置(2)

一、環境準備與基礎網絡配置1.1 節點角色與網絡規劃節點角色主機名所屬網段IP 地址網關核心功能Web 服務器web110.1.8.0/2410.1.8.1110.1.8.10&#xff08;后期調整為 10.1.8.20&#xff09;部署 Nginx/HTTPD&#xff0c;提供 Web 服務Web 服務器web210.1.8.0/2410.1.8.1210.1.…

uniapp H5禁止微信瀏覽器長按出菜單,只針對圖片

一、問題描述 如圖&#xff1a;uni-image>img,img {pointer-events: none;-webkit-pointer-events: none;-ms-pointer-events: none;-moz-pointer-events: none; }uni-image::before {content: ;position: absolute;top: 0;bottom: 0;left: 0;right: 0;background: transpa…

【機器學習】 15 Gaussian processes

本章目錄 15 Gaussian processes 515 15.1 Introduction 515 15.2 GPs for regression 516 15.2.1 Predictions using noise-free observations 517 15.2.2 Predictions using noisy observations 518 15.2.3 Effect of the kernel parameters 519 15.2.4 Estimating the kern…

Vue加載速度優化,verder.js和element.js加載速度慢解決方法

1. 使用CDN 這里把常用的vue、vuex、elementui、echarts、axios都引入成cdn的方式 1、在index.html引入CDN 找到public/index.html在上方引入下邊的cdn。 [!NOTE] 引入script的時候&#xff0c;一定要把vue.js放到最上邊&#xff0c;最先引入&#xff0c;不然后邊的js加載會…

49.【.NET8 實戰--孢子記賬--從單體到微服務--轉向微服務】--擴展功能--集成網關--Refit跨服務調用

Refit是一個用于.NET平臺的REST庫,它可以將REST API轉換為實時類型安全的接口。通過Refit,我們可以輕松實現微服務之間的跨服務調用,使服務間通信變得更加簡單和類型安全。本文將介紹如何在我們的項目中使用Refit來實現微服務間的通信。 一、什么是Refit Refit是一個強大的REST…

日志ELK、ELFK、EFK

一.ELK架構Elasticsearch Logstash Kibana 數據庫日志處理日志顯示1.logstash的使用&#xff08;1&#xff09;input&#xff1a;輸入&#xff08;2&#xff09;filter&#xff1a;處理&#xff08;3&#xff09;output&#xff1a;輸出2.ELFK架構Filebeat-->Elasticsearc…

【CUDA進階】MMA分析Bank Conflict與Swizzle(下)

目錄前言1. bank conflict 分析2. 通過 padding 解決 bank conflict3. mma 搭配 wmma 實現矩陣乘法計算3.1 代碼實現3.2 補充&#xff1a;stmatrix_sync 函數分析3.3 補充&#xff1a;__shfl_sync 函數詳解4. swizzle 原理講解5. swizzle 實現思路講解結語下載鏈接參考前言 學習…

天氣查詢系統

項目要求 項目知識點 問題與解決 代碼分部 結果展示 項目要求 1.顯示天氣預報系統界面 2.系統可以通過選擇城市配置獲取不同城市天氣信息 3.查看實時的天氣信息 &#xff08;當前溫度、最高溫度、最低溫度、當前濕度、最高濕度、最低濕度、風向、風力、風級等信息&#x…

三重積分的對稱性

文章目錄前言柱面球面前言 規律作息 柱面 太牛了。我完全看不懂。實際上就類似于極坐標系。 球面 看到這么多東西&#xff0c;我真害怕。今天是 8.30 &#xff0c;不管 9.10 有沒有復習完概率的強化&#xff0c;我都一定要開始套卷&#xff0c;還有專業課的復習。?\phi?…

深入理解 RabbitMQ:從底層原理到實戰落地的全維度指南

引言&#xff1a; 本文總字數&#xff1a;約 18500 字預計閱讀時間&#xff1a;45 分鐘 為什么我們需要 RabbitMQ&#xff1f; 在當今分布式系統架構中&#xff0c;消息隊列已成為不可或缺的核心組件。想象一下&#xff0c;當你在電商平臺下單時&#xff0c;系統需要處理庫存…