当前位置: 首页 > news >正文

STM32G070CBT6读写FLASH中的数据

向FLASH中写入数据函数

/*
    函数说明:向FLASH中写数据
    形参:addr-要写入数据的起始地址 data-准备写入数据  len-数据大小
    返回值:1-成功,0-失败
*/
uint8_t FlashWriteData(uint64_t addr,uint8_t data[],size_t len)
{
    uint32_t FirstPage = 0, NbOfPages = 0;      //FirstPage:第一页,NbOfPages:Number of pages to be erased,需要被擦除的页数
    uint32_t Address = 0, PageError = 0;    //Address:要写入FLASH的地址
    
    
    //FLASH解锁
    HAL_FLASH_Unlock(); //FLASH解锁
    
    //获取要擦除的第一页
    FirstPage = GetPage(FLASH_USER_START_ADDR); //获取要擦除的第一页
    
    //设置要擦除多少页
    NbOfPages = 1;  //1页,擦除一页
    
    //对要擦除结构体中的内容赋值
    EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;    //仅擦除页面
    EraseInitStruct.Page        = FirstPage;    //要擦除的起始页面
    EraseInitStruct.NbPages     = NbOfPages;    //需要擦除的页数
    
    //擦除FLASH
    if(HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)//擦除FLASH
    {
        while (1)
        {
            
        }
    }
    
    if(PageError != 0xFFFFFFFF)
    {
        return FLASH_WRITE_FAIL;
    }
    
    //对要写入FLASH的初始地址赋值
    Address = addr;  //初始地址赋值
    
    //写入数据到FLASH中
    for(int i = 0 ; i < len;i ++ ,Address+=8) 
    {
        //写入数据,写入位置Address+=8,每次+8是因为存储的类型是uint64_t,占用64bit,8字节
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Address, data[i]);
    }
    HAL_FLASH_Lock(); //FLASH上锁
    return FLASH_READ_SUCCESS;
}

/**
  * @brief  Gets the page of a given address 获取给定地址的页面
  * @param  Addr: Address of the FLASH Memory   FLASH中的地址
  * @retval The page of a given address
  */
static uint32_t GetPage(uint32_t Addr)  
{
  return (Addr - FLASH_BASE) / FLASH_PAGE_SIZE;
}

读取FLASH中数据函数

/*
    函数说明:读取FLASH中的数据
    形参:addr-要读取数据的起始地址 data-读出数据存放的地址  len-数据大小
    
*/
void FalshReadData(uint64_t addr,uint8_t *data,size_t len)
{
    uint32_t Address = 0;   //要读取数据的地址
    Address = addr;  //起始地址
    for(int i = 0; i < len; i++, Address+=8)
    {
        data[i] = *(__IO uint32_t*)(Address);
    }
    
}

程序汇总在一起,.c和.h文件如下:

hal_falsh.c文件

#include "hal_flash.h"


static uint32_t GetPage(uint32_t Address);

static FLASH_EraseInitTypeDef EraseInitStruct;  //FLASH擦除结构体

/*
    函数说明:向FLASH中写数据
    形参:addr-要读取数据的起始地址 data-准备写入数据  len-数据大小
    返回值:1-成功,0-失败
*/
uint8_t FlashWriteData(uint64_t addr,uint8_t data[],size_t len)
{
    uint32_t FirstPage = 0, NbOfPages = 0;      //FirstPage:第一页,NbOfPages:Number of pages to be erased,需要被擦除的页数
    uint32_t Address = 0, PageError = 0;    //Address:要写入FLASH的地址
    
    
    //FLASH解锁
    HAL_FLASH_Unlock(); //FLASH解锁
    
    //获取要擦除的第一页
    FirstPage = GetPage(FLASH_USER_START_ADDR); //获取要擦除的第一页
    
    //设置要擦除多少页
    NbOfPages = 1;  //1页,擦除一页
    
    //对要擦除结构体中的内容赋值
    EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;    //仅擦除页面
    EraseInitStruct.Page        = FirstPage;    //要擦除的起始页面
    EraseInitStruct.NbPages     = NbOfPages;    //需要擦除的页数
    
    //擦除FLASH
    if(HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)//擦除FLASH
    {
        while (1)
        {
            
        }
    }
    
    if(PageError != 0xFFFFFFFF)
    {
        return FLASH_WRITE_FAIL;
    }
    
    //对要写入FLASH的初始地址赋值
    Address = addr;  //初始地址赋值
    
    //写入数据到FLASH中
    for(int i = 0 ; i < len;i ++ ,Address+=8) 
    {
        //写入数据,写入位置Address+=8,每次+8是因为存储的类型是uint64_t,占用64bit,8字节
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, Address, data[i]);
    }
    HAL_FLASH_Lock(); //FLASH上锁
    return FLASH_READ_SUCCESS;
}

/*
    函数说明:读取FLASH中的数据
    形参:addr-要读取数据的起始地址 data-读出数据存放的地址  len-数据大小
    
*/
void FalshReadData(uint64_t addr,uint8_t *data,size_t len)
{
    uint32_t Address = 0;   //要读取数据的地址
    Address = addr;  //起始地址
    for(int i = 0; i < len; i++, Address+=8)
    {
        data[i] = *(__IO uint32_t*)(Address);
    }
    
}


/**
  * @brief  Gets the page of a given address 获取给定地址的页面
  * @param  Addr: Address of the FLASH Memory   FLASH中的地址
  * @retval The page of a given address
  */
static uint32_t GetPage(uint32_t Addr)  
{
  return (Addr - FLASH_BASE) / FLASH_PAGE_SIZE;
}

hal_falsh.h文件

#ifndef _HAL_FLASH_H_
#define _HAL_FLASH_H_

#include "stm32g0xx_hal.h"


//FLASH写入状态
typedef enum
{
    FLASH_WRITE_FAIL,   //0,失败
    FLASH_READ_SUCCESS, //1,成功
}FLASH_WRITE_STATE;

uint8_t FlashWriteData(uint64_t addr,uint8_t data[],size_t len);
void FalshReadData(uint64_t addr,uint8_t *data,size_t len);


#endif

在主函数中,需要对FLASH写入或读取数据,直接调用这两个函数即可。

注意:

如果将串口接收到的数据直接通过这个FLASH写函数写入FALSH中的话,会出现每个数据之间间隔8个字节,如下图所示,因为串口是8位数据(1字节),而这个FLASH写函数一次性写入时64位(8字节)。

在读FLASH函数中,也是一次性读取64位(8字节)数据,所以如果串口接收数据不是特别多,间隔八个字节存储在FLASH中可以存储下,那么就可以直接调用上面的写函数和读函数进行数据的读写,最终可以得到正确的结果。

参考文章:

Keil5 HAL库操作 flash 存储数据(stm32f103c6t6),实现断电保存数据 - 耿明岩 - 博客园

相关文章:

  • 浅谈Mysql数据库事务操作 用mybatis操作mysql事务 再在Springboot中使用Spring事务控制mysql事务回滚
  • ‌RTSPtoWeb, 一个将rtsp转换成webrtc的开源项目
  • 银河麒麟V10SP3Server中离线安装Docker引擎与docker-compose
  • 电池预测 | 第23讲 基于CNN-BiLSTM的锂电池剩余寿命预测,附带PPT视频讲解
  • GB9706.1-2020附件J绝缘路径参考
  • Redis系列:深入理解缓存穿透、缓存击穿、缓存雪崩及其解决方案
  • 如何用AI轻松制作完美PPT,节省时间又提升效率
  • 数据结构——查找
  • 背包问题——多重背包(C语言)
  • [免费]直接整篇翻译pdf工具-支持多种语言
  • Unity导出WebGL
  • 【GPT入门】第23课 langchain serve介绍
  • 【网页】CSS原子化+变量尝试
  • test skills
  • openai 标准化协议 Structured Outputs 具体示例教程
  • Django settings.py 文件全解析
  • 案例:图书管理
  • 如何保证消息不被重复消费?(如何保证消息消费的幂等性)
  • golang-嵌套结构体
  • Unity利用噪声生成动态地形
  • 豆神教育:2024年净利润1.37亿元,同比增长334%
  • 烟花、美食和购物优惠都安排上了,上海多区开启热闹模式
  • 总书记考察的上海“模速空间”,是一个怎样的空间?
  • 企业取消“大小周”引热议,半月谈:不能将显性加班变为隐性加班
  • 走访中广核风电基地:701台风机如何乘风化电,点亮3000万人绿色生活
  • 第五届全国医院人文管理路演在昆山举办:患者体验才是温度计