STM32读写内部FLASH读取芯片id
文章目录
- 读写内部Flash
- 接线
- 程序编写
- 测试效果
- 补充
- 读取芯片id
- 代码编写
读写内部Flash
接线

程序编写
首先使用ThisFlash.c来写入flash的基本操作,写入、读取、擦除,然后使用Store.c配合数组来进行主存与flash的交互
ThisFlash.c
#include "stm32f10x.h" // Device header
/*** @brief 读取此地址一个字的数据* @param Address,页地址* @retval 此地址的一个字的数据*/
uint32_t ThisFlash_ReadWord(uint32_t Address){return *((__IO uint32_t *)(Address));
}
/*** @brief 读取此地址的半字数据* @param Address,页地址* @retval 此地址的半字数据*/
uint16_t ThisFlash_ReadHalfWord(uint32_t Address){return *((__IO uint16_t *)(Address));
}
/*** @brief 读取此地址一个字节的数据* @param Address,页地址* @retval 此地址的一个字节的数据*/
uint8_t ThisFlash_ReadByte(uint32_t Address){return *((__IO uint8_t *)(Address));
}
/*** @brief 擦除整页数据* @param 无* @retval 无*/
void ThisFlash_EraseAllPages(void){FLASH_Unlock(); // 解锁FLASH_EraseAllPages(); // 擦除所有页FLASH_Lock(); // 重新上锁
}
/*** @brief 擦除指定页数据* @param 无* @retval 无*/
void ThisFlash_ErasePage(uint32_t PageAddress){FLASH_Unlock(); // 解锁FLASH_ErasePage(PageAddress); // 擦除指定页FLASH_Lock(); // 重新上锁
}
/*** @brief 指定地址写入一个字的数据* @param Address,页地址 Data,数据* @retval 无*/
void ThisFlash_PragramWord(uint32_t Address,uint32_t Data){FLASH_Unlock(); // 解锁FLASH_ProgramWord(Address,Data); // 指定地址写入一个字的数据FLASH_Lock(); // 重新上锁
}
/*** @brief 指定地址写入半字数据* @param Address,页地址 Data,数据* @retval 无*/
void ThisFlash_PragramHalfWord(uint32_t Address,uint16_t Data){FLASH_Unlock(); // 解锁FLASH_ProgramHalfWord(Address,Data); // 指定地址写入一个字的数据FLASH_Lock(); // 重新上锁
}
ThisFlash.h
#ifndef __THISFLASH_H
#define __THISFLASH_H
uint32_t ThisFlash_ReadWord(uint32_t Address);
uint16_t ThisFlash_ReadHalfWord(uint32_t Address);
uint8_t ThisFlash_ReadByte(uint32_t Address);
void ThisFlash_EraseAllPages(void);
void ThisFlash_ErasePage(uint32_t PageAddress);
void ThisFlash_PragramWord(uint32_t Address,uint32_t Data);
void ThisFlash_PragramHalfWord(uint32_t Address,uint16_t Data);#endif
store.c
#include "stm32f10x.h" // Device header
#include "ThisFlash.h"// 用于与flash交互的数组,存储与ram中
uint16_t Store_Data[512];/*** @brief 初始化最后一页* @param 无* @retval 无*/
void Store_Init(void){// 使用最后一页第一个半字作为是否为第一次写入的标志位if(ThisFlash_ReadHalfWord(0x0800fc00) != 0xa5a5){ThisFlash_ErasePage(0x0800fc00); // 第一次写入,擦掉此页数据ThisFlash_PragramHalfWord(0x0800fc00,0xa5a5); // 写入标志位for(uint16_t i=1;i<512;i++){ThisFlash_PragramHalfWord(0x0800fc00+i*2,0x0000); }}for(uint16_t i=0;i<512;i++){Store_Data[i] = ThisFlash_ReadHalfWord(0x0800fc00+i*2); // 写入标志位}
}
/*** @brief 备份Store_Data到flash* @param 无* @retval 无*/
void Store_Backup(void){ThisFlash_ErasePage(0x0800fc00);for(uint16_t i=0;i<512;i++){ThisFlash_PragramHalfWord(0x0800fc00+i*2,Store_Data[i]); // 写入标志位}
}
/*** @brief 擦除Store_Data并备份到flash* @param 无* @retval 无*/
void Store_Clear(void){for(uint16_t i=0;i<512;i++){Store_Data[i] = 0x0000; // 写入标志位}Store_Backup(); // flash同步清空
}
store.h
#ifndef __STORE_H
#define __STORE_H
extern uint16_t Store_Data[512];
void Store_Init(void);
void Store_Backup(void);
void Store_Clear(void);#endif
button.c
#include "stm32f10x.h" // Device header
#include "Delay.h"/*** @brief 初始化Button相关端口* @param 无* @retval 无*/
void Button_Init(void){// 初始化时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/*** @brief 返回所按按键值* @param 无* @retval KeyNum 按键值*/
uint8_t Key_Num(void){uint8_t KeyNum = 0;if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)==0);Delay_ms(20);KeyNum = 1;}if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)==0);Delay_ms(20);KeyNum = 11;}return KeyNum;
}
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Store.h"
#include "button.h"uint8_t KeyNum;int main(void)
{OLED_Init();Button_Init();Store_Init();// 为了不影响芯片的其他功能,在flash最后一页写入数据来测试while (1){KeyNum = Key_Num();if(KeyNum == 1){Store_Data[1] = 0x1314;Store_Data[3] = 0X3344;Store_Backup();}if(KeyNum == 11){Store_Clear();}OLED_ShowHexNum(1,1,Store_Data[1],4);OLED_ShowHexNum(2,1,Store_Data[3],4); OLED_ShowString(3,1,"Flag:");OLED_ShowHexNum(3,7,Store_Data[0],4);}
}
测试效果
下载程序后按下b11的按键最后一页数据清零,使用ST-LINK Utility查看

然后按下复位键,初始化函数执行,标志位置a5a5(为小端对齐反式)

然后按下b1按键,写入数据到数组并备份到flash,并且掉电不丢失

补充
还可以根据所需要的闪存空间来设置留给程序的闪存大小

读取芯片id
代码编写
根据手册给出的器件id地址一一使用指针读取
- 显示闪存大小

显示uid


main.c内容如下:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"int main(void)
{OLED_Init();OLED_ShowString(1,1,"F_Size:");OLED_ShowHexNum(1,8,*((__IO uint16_t *)(0x1FFFF7E0)),4);OLED_ShowString(2,1,"U_ID:");OLED_ShowHexNum(2,8,*((__IO uint16_t *)(0x1FFFF7E8)),4);OLED_ShowHexNum(2,11,*((__IO uint16_t *)(0x1FFFF7E8+0x02)),4);OLED_ShowHexNum(3,1,*((__IO uint32_t *)(0x1FFFF7E8+0x04)),8);OLED_ShowHexNum(3,1,*((__IO uint32_t *)(0x1FFFF7E8+0x08)),8);while (1){}
}

相关文章:
STM32读写内部FLASH读取芯片id
文章目录 读写内部Flash接线程序编写测试效果补充 读取芯片id代码编写 读写内部Flash 接线 程序编写 首先使用ThisFlash.c来写入flash的基本操作,写入、读取、擦除,然后使用Store.c配合数组来进行主存与flash的交互 ThisFlash.c #include "stm32…...
前端npm打包及报错解决
前端npm install 安装node 下载地址 https://nodejs.org/en/download/prebuilt-binaries 配置环境变量 wget https://nodejs.org/dist/v14.21.3/node-v14.21.3-linux-x64.tar.xz tar xf node-v14.21.3-linux-x64.tar.xz -C /data/ vim /etc/profile export NODE_HOME/data/n…...
vbs执行报错vbs没有文件拓展,双击无法打开
如果看不到文件扩展名需要设置: 无法双击打开vbs 一般为注册表问题 解决办法 将下方代码保存为xxx.reg Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\.VBS] "VBSFile" [HKEY_CLASSES_ROOT.VBS\PersistentHandler] "{5e941d80-bf96-…...
超详细的前后端实战项目(Spring系列加上vue3)前端篇(二)(一步步实现+源码)
好了,兄弟们,继昨天的项目之后,开始继续敲前端代码,完成前端部分 昨天完成了全局页面的代码,和登录页面的代码,不过昨天的代码还有一些需要补充的,这里添加一下 内容补充:在调用登…...
【国产中颖】SH79F9202U单片机驱动LCD段码液晶学习笔记
1. 引言 因新公司之前液晶数显表产品单片机一直用的是 C51单片机(SH79F9202U9),本人之前没有接触过这款单片机,为了维护老产品不得不重新研究研究这款单片机。 10位ADC LCD的增强型8051微控制器 SH79F9202是一种高速高效率8051可兼容单片机。在同样振…...
人工智能初识
🌞欢迎来到人工智能基础的世界 🌈博客主页:卿云阁 💌欢迎关注🎉点赞👍收藏⭐️留言📝 🌟本文由卿云阁原创! 📆首发时间:🌹2024年5月1…...
【算法刷题day60】Leetcode:84. 柱状图中最大的矩形
文章目录 Leetcode 84. 柱状图中最大的矩形解题思路代码总结 草稿图网站 java的Deque Leetcode 84. 柱状图中最大的矩形 题目:84. 柱状图中最大的矩形 解析:代码随想录解析 解题思路 反方向接雨水。见上一篇文章 代码 class Solution {public int la…...
ThingsBoard物联网网关在智慧城市数据采集中的应用
智慧城市由监控中心、采集网关、前端采集设备、前端感应执行器组成。 为何选用ThingsBoard作为平台 监控中心为物联网平台,该平台包含云计算、大数据、人工智能、物联网、GIS、云安全等主要模块,具备数据采集、数据交换、超大规模计算、数据分析、数据应…...
Java中的打印流PrintStream 和 PrintWriter
PrintStream和PrintWriter在Java中都是用于打印输出的类,但它们之间存在一些明显的区别。以下是关于这两个类的详细解释和比较: PrintStream 基本特性 PrintStream是一个字节打印流,它继承自FilterOutputStream。 主要操作byte流࿰…...
【MATLAB源码-第217期】基于matlab的16QAM系统相位偏移估计HOS算法仿真,对比补偿前后的星座图误码率。
操作环境: MATLAB 2022a 1、算法描述 高阶统计量(HOS)频偏估计算法 高阶统计量(Higher Order Statistics, HOS)频偏估计算法是一种先进的信号处理技术,广泛应用于现代数字通信系统中,以应对…...
C# CryptoStream流的详解与示例
在当今数字时代,数据安全变得越来越重要。保护敏感信息免受未授权访问是每个开发者的责任。在C#中,使用CryptoStream流可以方便地对数据进行加密和解密。本文将详细介绍C# CryptoStream库的用法、功能以及它如何对数据进行加密和解密。 一、CryptoStrea…...
Kubernetes 之 ReplicaSet
Kubernetes 之 ReplicaSet ReplicaSet 定义 ReplicaSet 是 Kubernetes 中的一种副本控制器,其主要作用是控制其管理的 Pod 的预设副本数量。它会持续监听这些 Pod 的运行状态,在Pod发生故障时执行重启策略,当 Pod 数量减少时会重新启动新的…...
转发和重定向
目录 是什么 转发(Forwarding) 概念 特点 实现方式 重定向(Redirecting) 概念 特点 实现方式 转发和重定向区别整理 转发和重定向的适用场景 转发(Forwarding) 重定向(Redirect&am…...
源码部署ELK
目录 资源列表 基础环境 关闭防护墙 关闭内核安全机制 修改主机名 添加hosts映射 一、部署elasticsearch 修改limit限制 部署elasticsearch 修改配置文件 单节点 集群(3台节点集群为例) 启动 二、部署logstash 部署logstash 添加配置文件 启动 三、部署kiban…...
构造+模拟,CF1148C. Crazy Diamond
一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 1148C - Codeforces 二、解题报告 1、思路分析 题目提示O(5n)的解法了,事实上我们O(3n)就能解决,关键在于1,n的处理 我们读入数据a[],代表初始数组…...
CAD二次开发(2)-将直线对象添加到CAD图形文件
1. 准备工作 创建一个类库项目,如下: 2. 分析Line对象 Line类的初始化方法和参数 using Autodesk.AutoCAD.DatabaseServices; Line line new Line();Line 继承Curve 继承Entity 继承DBObject 继承Drawable 继承RXObject 初始化方法有两个…...
代码随想录二刷 Day05 | 242.有效的字母异位词,349. 两个数组的交集,202. 快乐数,1. 两数之和,454.四数相加II,383. 赎金信
题目与题解 参考资料:哈希表理论基础 Tips: 一般哈希表都是用来快速判断一个元素是否出现集合里哈希表生成原理:先通过哈希函数将变量映射为hashcode,如果二者hashcode相同,再通过哈希碰撞方法(拉链法&…...
2024年四川省三支一扶报名流程图解✅
2024年四川省三支一扶报名流程图解✅ 🔴时间安排 1、报名时间:5月31日—6月4日17:00 2、资格初审时间:5月31日—6月5日17:00 3、准考证打印时间:6月25日—6月29日 4、笔试时间:6月30日 5、笔试成绩:7…...
js Dom基础
获取元素 1、getElementById() 通过id属性获取一个元素节点对象 <div id"div1"></div> <script> var div1 document.getElementById(div1) </script> 2、 getElementsByTagName()可以根据标签名来获取一组元素节点对象 这个方法会给我们返…...
pytest识别测试用例的机制以及和unittest的区别
pytest识别测试用例的机制 文件 以test_开头或以_test结尾的python文件,即test_xxx.py或xxx_test.py类,在第一点识别到的文件中的类,且满足一下任一条件: 1)以Test_开头,且没有__init__()初始化函数的类&a…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...
软件工程 期末复习
瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...
Vue3中的computer和watch
computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...
