stm32内部flash在线读写操作

news2025/1/3 21:38:48

stm32内部flash在线读写操作


  • 📍相关开源库文章介绍《STM32 利用FlashDB库实现在线扇区数据管理不丢失》

✨不同系列,内部flash编程有所区别。例如stm32f1是按照页擦除,半字(16bit)或全字(32bit)数据写入;stm32f4系列按照扇区擦除,可以字节(8bit)、半字(16bit)、字(32bit)和双字(64bit)数据写入.其他系列可以参考对应的参考手册内容说明。

📗stm32内部flash划分

  • 📍STM32F10xxx闪存编程手册:https://picture.iczhiku.com/resource/eetop/WhkWowqdUaYYwcnv.pdf
  • 不同型号的MCU内部flash容量是不同的。STM32F1为例:按照页划分
  • 🌿flash容量低于256KB的,页大小为:1KB=0x400;
    在这里插入图片描述
  • 🌿flash容量等于或大于256KB的,页大小为:2KB=0x800;
    在这里插入图片描述
  • 🧨stm32f4xx系列基于扇区操作,含 4 个 16 KB 扇区、1 个 64 KB 扇区 和 7 个 128 KB 扇区。(PM0081编程手册)
    在这里插入图片描述

📘闪存编程

  • 标准的闪存编程顺序:
  • 检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的编程操作;
  • 设置FLASH_CR寄存器的PG位为1;
  • 写入要编程的半字到指定的地址;
  • 等待BSY位变为0;
  • 读出写入的地址并验证数据。
  • 注意: 当FLASH_SR寄存器的BSY位为1时,不能对任何寄存器执行写操作。
  • 编程过程流程图:
    在这里插入图片描述
  • stm32标准库,FLASH编程操作:
/**
  * 函    数:FLASH编程字
  * 参    数:Address 要写入数据的字地址
  * 参    数:Data 要写入的32位数据
  * 返 回 值:无
  */
void MyFLASH_ProgramWord(uint32_t Address, uint32_t Data)
{
	FLASH_Unlock();							//解锁
	FLASH_ProgramWord(Address, Data);		//编程字
	FLASH_Lock();							//加锁
}

/**
  * 函    数:FLASH编程半字
  * 参    数:Address 要写入数据的半字地址
  * 参    数:Data 要写入的16位数据
  * 返 回 值:无
  */
void MyFLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
{
	FLASH_Unlock();							//解锁
	FLASH_ProgramHalfWord(Address, Data);	//编程半字
	FLASH_Lock();							//加锁
}

  • HAL库,FLASH编程实现:
/**
 * @brief 将16位数据写入FLASH
 *
 * @param data 指向要写入的数据的指针
 * @param len 要写入的数据长度(以半字为单位)
 * @param address 写入数据的起始地址
 * @return HAL_StatusTypeDef 返回HAL状态,表示操作是否成功
 */
HAL_StatusTypeDef FLASH_HALFWORD_Write(uint16_t *data, uint16_t len, uint32_t address)
{
    // 解锁FLASH,以便进行写操作
    HAL_FLASH_Unlock();

    // 初始化循环变量
    uint16_t i = 0;

    // 循环写入数据
    for (i = 0; i < len; i++)
    {
        // 对FLASH进行编程,使用HAL_FLASH_Program函数以半字(16位)为单位写入数据
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address, *data) == HAL_OK)
        {
            // 如果写入成功,更新地址和数据指针
            address = address + i * 2; // 地址每次增加2字节(16位)
            data = data + 1;          // 数据指针指向下一个半字
        }
        else
        {
            // 如果写入失败,锁定FLASH并返回错误状态
            HAL_FLASH_Lock();
            return HAL_ERROR;
        }
    }

    // 所有数据写入成功后,锁定FLASH并返回成功状态
    HAL_FLASH_Lock();
    return HAL_OK;
}
/**
 * @brief 将32位数据写入FLASH
 *
 * @param data 指向要写入的数据的指针
 * @param len 要写入的数据长度(以字为单位)
 * @param address 写入数据的起始地址
 * @return HAL_StatusTypeDef 返回HAL状态,表示操作是否成功
 */
HAL_StatusTypeDef FLASH_WORD_Write(uint32_t *data, uint16_t len, uint32_t address)
{
    // 解锁FLASH,以便进行写操作
    HAL_FLASH_Unlock();

    // 初始化循环变量
    uint16_t i = 0;

    // 循环写入数据
    for (i = 0; i < len; i++)
    {
        // 对FLASH进行编程,使用HAL_FLASH_Program函数以字(32位)为单位写入数据
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, *data) == HAL_OK)
        {
            // 如果写入成功,更新地址和数据指针
            address = address + i * 4; // 地址每次增加4字节(32位)
            data = data + 1;          // 数据指针指向下一个字
        }
        else
        {
            // 如果写入失败,锁定FLASH并返回错误状态
            HAL_FLASH_Lock();
            return HAL_ERROR;
        }
    }

    // 所有数据写入成功后,锁定FLASH并返回成功状态
    HAL_FLASH_Lock();
    return HAL_OK;
}
信息块的编程
  • 选项字节编程流程::
  • 检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的编程操作;
  • 设置FLASH_CR寄存器的OPTWRE位为1;
  • 设置FLASH_CR寄存器的OPTPG位为1;
  • 写入要编程的半字到指定的地址;
  • 等待BSY位变为0;
  • 读出写入的地址并验证数据

📒闪存擦除

闪存可以按页擦除,也可以全部擦除。

页擦除

闪存的任何一页都可以通过FPEC的页擦除功能擦除;擦除一页应遵守下述过程:

  • 检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的闪存操作;
  • 用FLASH_AR寄存器选择要擦除的页;
  • 设置FLASH_CR寄存器的PER位为1;
  • 设置FLASH_CR寄存器的STRT位为1;
  • 等待BSY位变为0;
  • 读出被擦除的页并做验证。
  • 闪存页擦除过程流程图:
    在这里插入图片描述
  • stm32标准库,FLASH页擦除操作:
/**
  * 函    数:FLASH页擦除
  * 参    数:PageAddress 要擦除页的页地址
  * 返 回 值:无
  */
void MyFLASH_ErasePage(uint32_t PageAddress)
{
	FLASH_Unlock();					//解锁
	FLASH_ErasePage(PageAddress);	//页擦除
	FLASH_Lock();					//加锁
}
  • HAL库 页擦除操作
HAL_StatusTypeDef  FLASH_Erase_Page(uint32_t Page_Addr,uint32_t Page_Num)
{
	FLASH_EraseInitTypeDef EraseInitStruct;
	uint32_t PageError = 0;
	HAL_FLASH_Unlock(); //解锁内部flash
	EraseInitStruct.TypeErase     = FLASH_TYPEERASE_PAGES;//标明Flash执行页面只做擦除操作
	EraseInitStruct.PageAddress        = Page_Addr;  //声明要擦除的地址
	EraseInitStruct.NbPages     = Page_Num; //要擦除的页数,此参数必须是Min_Data = 1和Max_Data =(最大页数-初始页的值)之间的值

	if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
	{
		HAL_FLASH_Lock();
		return HAL_ERROR;
	}
	HAL_FLASH_Lock();
	return HAL_OK;
}
全部擦除

可以用全部擦除功能擦除所有用户区的闪存,信息块不受此操作影响。建议使用下述过程:

  • 检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的闪存操作;
  • 设置FLASH_CR寄存器的MER位为1;
  • 设置FLASH_CR寄存器的STRT位为1;
  • 等待BSY位变为0;
  • 读出所有页并做验证。
  • 闪存全擦除过程流程图:
    在这里插入图片描述
  • stm32标准库,FLASH全擦除操作:
/**
  * 函    数:FLASH全擦除
  * 参    数:无
  * 返 回 值:无
  * 说    明:调用此函数后,FLASH的所有页都会被擦除,包括程序文件本身,擦除后,程序将不复存在
  */
void MyFLASH_EraseAllPages(void)
{
	FLASH_Unlock();					//解锁
	FLASH_EraseAllPages();			//全擦除
	FLASH_Lock();					//加锁
}
  • ⚡需要注意,全擦除,会对内部整个flash进行擦除,擦除后,整个mcu成为空片,原来所烧录的程序将不复存在。如需再使用,需要重新烧录程序。

📙读取操作

内置闪存模块可以在通用地址空间直接寻址,任何32位数据的读操作都能访问闪存模块的内容并得到相应的数据。

  • 代码实现:
/**
  * 函    数:FLASH读取一个32位的字
  * 参    数:Address 要读取数据的字地址
  * 返 回 值:指定地址下的数据
  */
uint32_t MyFLASH_ReadWord(uint32_t Address)
{
	return *((__IO uint32_t *)(Address));	//使用指针访问指定地址下的数据并返回
}

/**
  * 函    数:FLASH读取一个16位的半字
  * 参    数:Address 要读取数据的半字地址
  * 返 回 值:指定地址下的数据
  */
uint16_t MyFLASH_ReadHalfWord(uint32_t Address)
{
	return *((__IO uint16_t *)(Address));	//使用指针访问指定地址下的数据并返回
}

/**
  * 函    数:FLASH读取一个8位的字节
  * 参    数:Address 要读取数据的字节地址
  * 返 回 值:指定地址下的数据
  */
uint8_t MyFLASH_ReadByte(uint32_t Address)
{
	return *((__IO uint8_t *)(Address));	//使用指针访问指定地址下的数据并返回
}

📚相关测试代码

  • 基于STM32F103VC,大容量芯片,页容量2K
  • 🔖HAL库
通过网盘分享的文件:STM32F103VC_FLASH_Program.rar
链接: https://pan.baidu.com/s/1BrxBfByBddTfv4BUbFdZlA?pwd=3qry 提取码: 3qry
  • 🔖std标准库,基于STM32F103VC,大容量芯片,页容量2K。(参考江协科技代码)
通过网盘分享的文件:15-1 读写内部FLASH.rar
链接: https://pan.baidu.com/s/115JvFfDWzdurpzlsaiWl6Q?pwd=vepn 提取码: vepn

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2268800.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IDEA | SpringBoot 项目中使用 Apifox 上传接口

目录 1 安装 Apifox Helper 插件2 获取 Apifox 的 API 访问令牌3 IDEA 中设置 API 访问令牌4 IDEA 中上传接口5 常见问题5.1 如何自动设置目录名5.2 如何自动设置接口名5.3 如何更改上传位置 Apifox 官方指南&#xff1a; https://apifox.com/help/applications-and-p…

Leetcode 10-正则表达式匹配/ 剑指 Offer 19. 正则表达式匹配

给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。 ‘.’ 匹配任意单个字符 ‘*’ 匹配零个或多个前面的那一个元素 所谓匹配&#xff0c;是要涵盖 整个 字符串 s 的&#xff0c;而不是部分字符串。 题解 字符串匹配多…

学习vue3的笔记

一、vue和react的对比 1、基础介绍 vue&#xff1a;https://cn.vuejs.org/ vue3是2020年创建的 react&#xff1a;https://react.dev/ react是一个2013年开源的JavaScript库&#xff0c;严格意义上来说不是一个框架 2、diff算法 两个框架采用的都是同级对比策略 两节点对…

基于STM32的智能家居环境监控系统设计

目录 引言系统设计 硬件设计软件设计系统功能模块 环境监控模块控制模块显示模块系统实现 硬件实现软件实现系统调试与优化结论与展望 1. 引言 随着智能家居技术的发展&#xff0c;环境监控系统已经成为家居管理的重要组成部分。智能家居环境监控系统通过实时监测室内温度、湿…

【MySQL】搞懂mvcc、read view:MySQL事务原理深度剖析

前言&#xff1a;本节内容是事务里面最难的一部分&#xff0c; 就是理解mvcc快照读和read view。这两个部分需要了解隔离性里面的四种隔离级别。 博主之前讲过&#xff0c;但是担心友友们不了解&#xff0c; 所以这里开头进行了复习。 下面开始我们的学习吧&#xff01; ps&…

jmeter设置tps、响应时间监测时间间隔

jmeter设置tps、响应时间监测时间间隔 思路&#xff1a; 1、设置tps和响应时间插件的采集时间间隔&#xff0c;然后运行jmeter脚本&#xff1b; 2、先按默认配置跑出jtl文件保存下来&#xff0c;再添加tps和响应时间插件&#xff0c;设置采集时间间隔后&#xff0c;导入jtl文件…

Qt 12.30 day5

day5_testppp.proQT core gui texttospeech widget.h#ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimerEvent>//定时器事件类 #include <QTimer>//时间事件类 #include <QTime>//时间类 #include <QTextToSpeech>//…

玩转OCR | 腾讯云智能结构化OCR初体验

随着数字化进程的加速&#xff0c;光学字符识别&#xff08;OCR&#xff09;技术已逐渐成为提高企业生产力、优化工作流的重要工具。腾讯云智能结构化OCR凭借其领先的技术、广泛的应用场景和灵活的定制化能力&#xff0c;正在帮助各行业客户更高效地进行文档处理与数据提取。本…

Spring Boot教程之三十九: 使用 Maven 将 Spring Boot 应用程序 Docker 化

如何使用 Maven 将 Spring Boot 应用程序 Docker 化&#xff1f; Docker是一个开源容器化工具&#xff0c;用于在隔离环境中构建、运行和管理应用程序。它方便开发人员捆绑其软件、库和配置文件。Docker 有助于将一个容器与另一个容器隔离。在本文中&#xff0c;为了将Spring B…

模仿微信小程序wx.showModal自定义弹窗,内容可以修改

实现以下弹框样式功能 1.在components新建一个文件showModel.wpy作为组件&#xff0c;复制下面代码 <style lang"less" scoped> .bg_model {display: flex;justify-content: center;align-items: center;// 弹框背景.bg_hui {width: 100%;height: 100%;posi…

缓存管理自动化:JuiceFS 企业版 Cache Group Operator 新特性发布

近期&#xff0c;JuiceFS 企业版推出了 Cache Group Operator&#xff0c;用于自动化创建和管理缓存组集群。Operator 是一种简化 Kubernetes 应用管理的工具&#xff0c;它能够自动化应用程序的生命周期管理任务&#xff0c;使部署、扩展和运维更加高效。 在推出 Operator 之前…

零基础微信小程序开发——小程序的宿主环境(保姆级教程+超详细)

&#x1f3a5; 作者简介&#xff1a; CSDN\阿里云\腾讯云\华为云开发社区优质创作者&#xff0c;专注分享大数据、Python、数据库、人工智能等领域的优质内容 &#x1f338;个人主页&#xff1a; 长风清留杨的博客 &#x1f343;形式准则&#xff1a; 无论成就大小&#xff0c;…

GPU 进阶笔记(二):华为昇腾 910B GPU

大家读完觉得有意义记得关注和点赞&#xff01;&#xff01;&#xff01; 1 术语 1.1 与 NVIDIA 术语对应关系1.2 缩写2 产品与机器 2.1 GPU 产品2.2 训练机器 底座 CPU功耗操作系统2.3 性能3 实探&#xff1a;鲲鹏底座 8*910B GPU 主机 3.1 CPU3.2 网卡和网络3.3 GPU 信息 3.3…

微服务SpringCloud分布式事务之Seata

视频教程&#xff1a;https://www.bilibili.com/video/BV16P63Y3ESq 效果演示 准备的微服务项目调用的链路如下&#xff1a; 文字描述&#xff1a; gateway模块接收到请求&#xff0c;并发送到order订单模块order订单模块接收到请求&#xff0c;新增一个订单数据后发送一个…

HTML——13.超链接

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>超链接</title></head><body><!--超链接:从一个网页链接到另一个网页--><!--语法&#xff1a;<a href"淘宝网链接的地址"> 淘宝…

STM32 高级 WIFi案例1:测试AT指令

需求描述 测试AT指令是否能够正常控制ESP32的wifi&#xff0c;比如重启、读取设备信息等。 思路&#xff1a; stm32通过串口usart2向ESP32发布命令。ESP32通过串口1返回信息。 配置&#xff1a; 第一步&#xff1a;对ESP32芯片烧录可以读取stm32命令的固件&#xff08;fac…

GXUOJ-算法-第四次作业(圆排列、连续邮资、n皇后、符号三角形)

1.圆排列 问题描述 GXUOJ | 圆排列 代码解答 #include<bits/stdc.h>using namespace std;int n; int r[1000]; double x[1000]; double ans 0x3f3f3f3f;double calculate(){memset(x, 0, sizeof x);for(int i 0; i < n; i){for(int j 0; j < i; j)x[i] max(…

[创业之路-225]:《华为闭环战略管理》-4-华为的商业智慧:在价值链中探索取舍之道与企业边界

目录 一、在价值链中探索取舍之道与企业边界 价值链的深刻洞察 取舍之道&#xff1a;有所为&#xff0c;有所不为 垂直整合与横向整合的平衡 企业边界与活动边界的界定 采购与外包的智慧运用 结语 二、企业外部价值流&#xff1a;上游、中游、下游、终端 上游&#xf…

【从零开始入门unity游戏开发之——C#篇33】C#委托(`Delegate`)和事件(`event` )、事件与委托的区别、Invoke()的解释

文章目录 一、委托&#xff08;Delegate&#xff09;1、什么是委托&#xff1f;2、委托的基本语法3、定义自定义委托4、如何使用自定义委托5、多播委托6、C# 中的系统委托7、GetInvocationList 获取多个函数返回值8、总结 二、事件&#xff08;event &#xff09;1、事件是什么…

大模型—Ollama 结构化输出

Ollama 结构化输出 Ollama现在支持结构化输出,使得可以按照由JSON模式定义的特定格式来约束模型的输出。Ollama的Python和JavaScript库已经更新,以支持结构化输出。 结构化输出的用例包括: 从文档中解析数据从图像中提取数据结构化所有语言模型响应比JSON模式更可靠和一致开…