硬件设备:stm32h743 emmc存储芯片(FEMDME004G-A8A39 )
注意:
emmc采用4bit数据传输模式 本文详细展示cubemx配置以及驱动代码实例 项目中已经成功使用
一、MCU与emmc接线原理图
上图是文中MCU的部分连接 详细参考自己的原理图
eMMc支持1、4、8bit数据传输 本文只使用了4bit数据传输模式
二、CubeMX配置
在cubemx SDMMC1 中选择4位数据传输模式 并启动中断 其他配置默认
注意:一定要根据MCU上连接emmc的引脚接线来配置
连接4位就配置4位 连接8位就配置8位 否则会导致数据读写出错
三、驱动代码
直接附上驱动代码,调用HAL库中的函数就行
SDMMC1初始化
void MX_SDMMC1_MMC_Init(void)
{
/* USER CODE BEGIN SDMMC1_Init 0 */
/* USER CODE END SDMMC1_Init 0 */
/* USER CODE BEGIN SDMMC1_Init 1 */
/* USER CODE END SDMMC1_Init 1 */
hmmc1.Instance = SDMMC1;
hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
hmmc1.Init.BusWide = SDMMC_BUS_WIDE_4B;
hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
hmmc1.Init.ClockDiv = 1;
if (HAL_MMC_Init(&hmmc1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SDMMC1_Init 2 */
/* USER CODE END SDMMC1_Init 2 */
}
eMMC_BGA169.c
#include "eMMC_BGA169.h"
//******************************************************************************/
// 函 数 名 : 写数据
// 功 能 : 向指定地址写入数据
// 输入参数 : 数据指针 地址 写块数
// 返回参数 :
// 说 明 :
//
//
//******************************************************************************/
HAL_StatusTypeDef eMMC_WriteBlocks(uint8_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
{
return HAL_MMC_WriteBlocks(&hmmc1, (uint8_t *)pData, WriteAddr, NumOfBlocks, HAL_MAX_DELAY);
}
//******************************************************************************/
// 函 数 名 : 读数据
// 功 能 : 从指定地址读出数据
// 输入参数 : 数据指针 地址 读块数
// 返回参数 :
// 说 明 :
//
//
//******************************************************************************/
HAL_StatusTypeDef eMMC_ReadBlocks(uint8_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
{
return HAL_MMC_ReadBlocks(&hmmc1, (uint8_t *)pData, ReadAddr, NumOfBlocks, HAL_MAX_DELAY);
}
//******************************************************************************/
// 函 数 名 : 检查状态
// 功 能 :
// 输入参数 :
// 返回参数 :
// 说 明 :
//
//
//******************************************************************************/
HAL_StatusTypeDef eMMC_CheckState(void)
{
return HAL_MMC_GetCardState(&hmmc1);
}
eMMC_BGA169.h
#ifndef __EMMC_BGA169_H__
#define __EMMC_BGA169_H__
#include "sdmmc.h"
HAL_StatusTypeDef eMMC_ReadBlocks(uint8_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks);
HAL_StatusTypeDef eMMC_WriteBlocks(uint8_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) ;
HAL_StatusTypeDef eMMC_CheckState(void);
#endif
注意:在使用读写函数前,先检查卡的状态
四、函数实际使用示例
写入数据
temp: 数组 存放要写入的数据的指针
解释:将temp数组的内容写进指定地址从第1000001块开始,写入一块(通常一块的大小为512个字节)
eMMC_WriteBlocks(temp, 1000001, 1);
eMMC_WriteBlocks(SAVE_buffer,ad_save.AD_write_block*4,4);
读出数据
解释:将指定地址从1000002块开始读取一块的数据到MM_DATA中
eMMC_ReadBlocks(MM_DATA, 1000002, 1);
eMMC_ReadBlocks(SAVE1_buffer,ad_save.AD_read_block*4,4);
擦除数据
解释:擦除从第0块到第100000块的数据
HAL_MMC_Erase(&hmmc1, 0, 100000);
解释:擦除从第1000001块到第1000001块共一块的数据
HAL_MMC_Erase(&hmmc1, 1000001, 1000001);
按照以上配置及代码成功驱动emmc存储芯片读写。
五、分享心得
网上绝大部分是使用8bit数据传输模式,首次驱动此款存储芯片,虽说与SD卡的驱动差别不大,但是还是踩了很多坑。本文使用的是4bit数据传输模式,配置的内容一定要和MCU接线方式一样。主要的是代码,参考过网上驱动代码在我的项目中有点问题,后面详细看了emmc的数据手册以及资料,里面提到emmc的读写都要返回一个状态才能进行下一步。所以我的代码封装直接返回的是一个状态。本人小菜,分享工作中遇到并成功解决的问题,欢迎一起技术交流~