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;系统需要处理库存…