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){}
}

在这里插入图片描述


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

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

相关文章

为什么工控现场会用到Profinet转Modbus网关设备

一、背景&#xff1a; 工控现场之所以需要使用Profinet转Modbus网关&#xff0c;是因为工控系统中常常存在不同厂家设备之间通讯协议不一致的问题。而Modbus和Profinet分别代表着两种不同的通信协议&#xff0c;Profinet通常用于较新的设备&#xff0c;而Modbus则是比较老的通…

思科防火墙ASA Version 9.1(1) 怎么配置静态NAT,把内网ip192.168.1.10 端口1000映射到公网端口1000上?

环境: 思科防火墙5520 ASA Version 9.1(1) 问题描述: 思科防火墙ASA Version 9.1(1) 怎么配置静态NAT,把内网ip192.168.1.10 端口1000映射到公网端口1000上? 解决方案: 旧版本8.0 1.做之前要先查一下有没有端口被占用,要和业务确认2.sh Xlate | in 10011 端口 这条…

ch2应用层--计算机网络期末复习

2.1应用层协议原理 网络应用程序位于应用层 开发网络应用程序: 写出能够在不同的端系统上通过网络彼此通信的程序 2.1.1网络应用程序体系结构分类: 客户机/服务器结构 服务器: 总是打开(always-on)具有固定的、众所周知的IP地址 主机群集常被用于创建强大的虚拟服务器 客…

MongoDB CRUD操作:快照查询

MongoDB CRUD操作&#xff1a;快照查询 文章目录 MongoDB CRUD操作&#xff1a;快照查询对比本地和快照的读关注举例从相同的时间点运行查询从过去某个时刻读取数据的一致状态 配置快照保留时间磁盘空间和历史记录 使用快照查询可以读取最近某个时间点的数据&#xff0c;而且从…

基于51单片机的温控风扇的设计–仿真设计

可实现通过DS18B20测量当前环境温度 可实现通过温度自动控制风扇转速 可实现通过按键设置不同风速对应的温度 可实现通过按键切换自动、手动模式 可实现在手动模式下通过按键调整风扇转速 可实现通过LCD1602显示温度、风扇转速挡位、自动/手动模式

【C++】模拟实现string类

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:C ⚙️操作环境:Visual Studio 2022 目录 一.了解项目功能 二.逐步实现项目功能模块及其逻辑详解 &#x1f38f;构建成员变量 &#x1f38f;实现string类默认成员函数 &#x1f4cc;构造函数 &#x1f4cc;析构函数…

k8s 全面掌控日志系统

概述 为了提高系统运维和故障排查的效率&#xff0c; 日志系统采用 ELK&#xff08;Elasticsearch、Logstash、Kibana&#xff09;技术栈&#xff0c;通过 FileBeats 作为日志收集器&#xff0c;将来自不同节点的日志数据汇总并存储在 Elasticsearch 中&#xff0c;最终通过 K…

创建一个新的Spring Security应用程序,并使用JDBC连接数据库

创建一个新的Spring Security应用程序&#xff0c;并使用JDBC连接数据库 在这个教程中&#xff0c;我们将学习如何创建一个新的Spring Security应用程序&#xff0c;使用JDBC连接数据库以获取用户信息并进行认证。我们还将学习如何配置Spring Security以从数据库中获取用户和权…

Vue3使用Composition API实现响应式

title: Vue3使用Composition API实现响应式 date: 2024/5/29 下午8:10:24 updated: 2024/5/29 下午8:10:24 categories: 前端开发 tags: Vue3CompositionRefsReactiveWatchLifecycleDebugging 1. 介绍 Composition API是Vue.js 3中新增的一组API&#xff0c;用于在组件中组…

SQL 语言:嵌入式 SQL 和动态 SQL

文章目录 基本概述嵌入式 SQL动态 SQL总结 基本概述 嵌入式SQL和动态SQL是两种在应用程序中嵌入和使用SQL语句的方法。它们都允许开发人员在编程语言中编写SQL语句&#xff0c;以便在应用程序中执行数据库操作。然而&#xff0c;这两种方法在实现方式、性能和灵活性方面存在一…

Java数据结构与算法(红黑树)

前言 红黑树是一种自平衡二叉搜索树&#xff0c;确保在插入和删除操作后&#xff0c;树的高度保持平衡&#xff0c;从而保证基本操作&#xff08;插入、删除、查找&#xff09;的时间复杂度为O(log n)。 实现原理 红黑树具有以下性质&#xff1a; 每个节点要么是红色&#…

go语言学习之旅之Go结构体

在Go语言中&#xff0c;结构体&#xff08;struct&#xff09;是一种用户定义的数据类型&#xff0c;用于组合不同类型的数据项。结构体可以包含其他结构体或基本数据类型的字段。以下是关于Go语言结构体的基本知识&#xff1a; 定义结构体&#xff1a; package mainimport &…

Python 之微信指数小程序数据抓取

Fiddler安装和设置 安装 Fiddler 安装包可以从这里获取&#xff0c;如果失效了可以自己网上找一个安装。 链接&#xff1a;https://pan.baidu.com/s/1N30BoDWm2_dBL8i8GRzK5g?pwd1znv 提取码&#xff1a;1znv 然后就是点击安装就好了&#xff0c;没什么好多说的。 启用…

刷代码随想录有感(83):贪心算法——最大子数组和

题干&#xff1a; 代码&#xff1a; class Solution { public:int maxSubArray(vector<int>& nums) {int res INT_MIN;int count 0;for(int i 0; i < nums.size(); i){count nums[i];if(count > res) res count;if(count < 0)count 0;}return res;} …

【创作活动】探索 GPT-4o:下一代语言模型的技术革命

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

HTTP报文

HTTP报文 报文流 HTTP报文是在HTTP引用程序之间发送的数据块&#xff0c;这些数据块以一种文本形式的元信息开头&#xff0c;这些信息描述了报文的内容和含义&#xff0c;后面跟着可选的数据部分&#xff0c;这些报文在客户端&#xff0c;服务器和代理之间流动。 报文流入源…

git更改本地项目关联到新仓库

删除现在远程关联的仓库 git remote rm origin链接新仓库 git remote add origin url(需要关联的新仓库地址)代码提交到远程仓库master分支 git push --set-upstream origin master本地分支更新同步至远程仓库 比如本地有dev分支 git push origin dev:dev

前端项目开发,3个HTTP请求工具

这一小节&#xff0c;我们介绍一下前端项目开发中&#xff0c;HTTP请求会用到的3个工具&#xff0c;分别是fetch、axios和js-tool-big-box中的jsonp请求。那么他们都有哪些小区别呢&#xff1f;我们一起来看一下。 目录 1 fetch 2 axios 3 js-tool-big-box 的 jsonp 请求 …

拷贝构造、移动构造、拷贝赋值、移动赋值

最近在学习C的拷贝构造函数时发现一个问题&#xff1a;在函数中返回局部的类对象时&#xff0c;并没有调用拷贝构造函数。针对这个问题&#xff0c;查阅了一些资料&#xff0c;这里记录整理一下。 调用拷贝构造函数的三种情况&#xff1a; ① 用一个类去初始化另一个对象时&a…

【数据结构与算法 | 基础篇 | 队列篇】力扣102, 107

1. 力扣102 : 二叉树的层序遍历 (1). 题 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3]…