FLASH读写数据

目录

嵌入式 Flash大概了解

数据手册2.3.2章节

结构图f407

等待周期

 Flash 控制寄存器解锁

编程/擦除并行位数

 擦除

 编程(写入)

工程程序


嵌入式 Flash大概了解

可以从flash区域启动程序;大概是程序区可以在flash,所以是可以直接读取数据的

数据手册2.3.2章节

Flash 接口可管理 CPU 通过 AHB I-Code 和 D-Code 对 Flash 进行的访问。该接口可针对 
Flash 执行擦除和编程操作,并实施读写保护机制。Flash 接口通过指令预取和缓存机制加速 
代码执行。
Flash 结构如下:
● 主存储器块分为多个扇区。
● 系统存储器,器件在系统存储器自举模式下从该存储器启动
● 512 OTP(一次性可编程)字节,用于存储用户数据。
● 选项字节,用于配置读写保护、BOR 级别、软件/硬件看门狗以及器件处于待机或停止 
模式下的复位。

可以知道flash是存储程序用的,可以用来做主存储

结构图f407

主存储器大概有12个扇区:主要的数据程序都在这里;

当使用时要注意程序的大小,在程序大小之外使用。不然会影响,擦除原来存储的程序;造成死机;

等待周期

为了准确读取 Flash 数据,必须根据 CPU 时钟 (HCLK) 频率和器件电源电压在 Flash 存取控 
制寄存器 (FLASH_ACR) 中正确地编程等待周期数 (LATENCY)

所以一句话:读取数据需要时间,并且根据HCLK和电压范围得到的CPU周期;

168M 的HCLK 和 3.3V的电压 可以知道等待周期大概6个CPU时间;

 Flash 控制寄存器解锁

 复位后,Flash 控制寄存器 (FLASH_CR) 不允许执行写操作,以防因电气干扰等原因出现对 
Flash 的意外操作。此寄存器的解锁顺序如下:
1. 在 Flash 密钥寄存器 (FLASH_KEYR) 中写入 KEY1 = 0x45670123
2. 在 Flash 密钥寄存器 (FLASH_KEYR) 中写入 KEY2 = 0xCDEF89AB
如果顺序出现错误,将返回总线错误并锁定 FLASH_CR 寄存器,直到下一次复位。

所以操作配置的时候必须要先解锁;

编程/擦除并行位数


通过 FLASH_CR 寄存器中的 PSIZE 字段配置并行位数。并行位数表示每次对 Flash 进行写 
操作时将编程的字节数。

可以从手册知道位宽128,即32字节;所以配置应该32字节即可;

 擦除

Flash 擦除操作可针对扇区或整个 Flash(批量擦除)执行。执行批量擦除时,不会影响 
OTP 扇区或配置扇区。

扇区擦除
扇区擦除的具体步骤如下:
1. 检查 FLASH_SR 寄存器中的 BSY 位,以确认当前未执行任何 Flash 操作
2. 在 FLASH_CR 寄存器中,将 SER 位置 1,并从主存储块的 12 个 (STM32F405xx/07xx 
和 STM32F415xx/17xx) 或 24 个 (STM32F42xxx 和 STM32F43xxx) 扇区中选择要擦除
的扇区 (SNB)
3. 将 FLASH_CR 寄存器中的 STRT 位置 1
4. 等待 BSY 位清零

 编程(写入)


标准编程
Flash 编程顺序如下:
1. 检查 FLASH_SR 中的 BSY 位,以确认当前未执行任何主要 Flash 操作。
2. 将 FLASH_CR 寄存器中的 PG 位置 1。
3. 针对所需存储器地址(主存储器块或 OTP 区域内)执行数据写入操作:
— 并行位数为 x8 时按字节写入
— 并行位数为 x16 时按半字写入
— 并行位数为 x32 时按字写入
— 并行位数为 x64 时按双字写入
4. 等待 BSY 位清零。

工程程序

不懂地址谨慎使用,会破坏原来的程序;

文件C

#include"flash_eeprom.h"/***** 读取字 *******/uint32_t flash_read_word(  uint32_t *addr   )
{return *addr;
}uint32_t flash_read( uint32_t addr,uint32_t *buff ,uint32_t cnt  )
{uint32_t i;for(i=0 ;i<cnt ;i++){*buff++=flash_read_word(  (uint32_t *)addr  );addr+=4;}}
/*用地址来确定是flash的哪一个扇区addr flash的地址*/uint16_t 	flash_get_sector_x(  uint32_t addr     ) 
{if(addr<FLASH_SECTOR1_ADDR   ) return  FLASH_Sector_0;else if( addr<FLASH_SECTOR2_ADDR ) return  FLASH_Sector_1;else if( addr<FLASH_SECTOR3_ADDR ) return  FLASH_Sector_2;else if( addr<FLASH_SECTOR4_ADDR ) return  FLASH_Sector_3;else if( addr<FLASH_SECTOR5_ADDR ) return  FLASH_Sector_4;else if( addr<FLASH_SECTOR6_ADDR ) return  FLASH_Sector_5;else if( addr<FLASH_SECTOR7_ADDR ) return  FLASH_Sector_6;else if( addr<FLASH_SECTOR8_ADDR ) return  FLASH_Sector_7;else if( addr<FLASH_SECTOR9_ADDR ) return  FLASH_Sector_8;else if( addr<FLASH_SECTOR10_ADDR ) return  FLASH_Sector_9;else if( addr<FLASH_SECTOR11_ADDR ) return  FLASH_Sector_10;else  return  FLASH_Sector_11;}void flash_write( uint32_t addr ,uint32_t *buff ,uint32_t cnt    )
{FLASH_Status state=FLASH_COMPLETE; uint32_t start_addr=addr;uint32_t end_addr=start_addr+cnt*4;FLASH_Unlock();//解锁FLASH_DataCacheCmd(DISABLE);//禁止数据缓存if(  (addr < FLASH_START_ADDR  && addr >  FLASH_END_ADDR ) || addr%4 !=0  ) return; //确保地址在主储存区域while( start_addr < end_addr){if( flash_read_word(  (uint32_t * )start_addr   ) != 0xffffffff) {state=FLASH_EraseSector(  flash_get_sector_x(start_addr), VoltageRange_3 );//擦除需要电压相关,得到周期时间if( state != FLASH_COMPLETE ){break;   }}start_addr+=4;}start_addr=addr;if(state== FLASH_COMPLETE){while(start_addr< end_addr)//写数据进flash{if(FLASH_ProgramWord( start_addr , *buff++) !=FLASH_COMPLETE ){break;} start_addr+=4;						 }}FLASH_DataCacheCmd(ENABLE);//使能数据缓存FLASH_Lock();//锁上
}

文件H

#ifndef FLASH_EEPROM_H
#define FLASH_EEPROM_H#include "main.h"#define FLASH_START_ADDR 0x08000000#define FLASH_SECTOR0_ADDR  0X08000000    //16k
#define FLASH_SECTOR1_ADDR  0X08004000    //16k
#define FLASH_SECTOR2_ADDR  0X08008000   //16k
#define FLASH_SECTOR3_ADDR  0X0800C000   //16k#define FLASH_SECTOR4_ADDR  0X08010000  //64k#define FLASH_SECTOR5_ADDR  0X08020000  //128k
#define FLASH_SECTOR6_ADDR  0X08040000  //128k
#define FLASH_SECTOR7_ADDR  0X08060000  //128k
#define FLASH_SECTOR8_ADDR  0X08080000  //128k
#define FLASH_SECTOR9_ADDR  0X080A0000  //128k
#define FLASH_SECTOR10_ADDR  0X080C0000  //128k
#define FLASH_SECTOR11_ADDR  0X080E0000  //128k#define FLASH_END_ADDR 0x080EFFFF
#define FLASH_USER_ADDR 0X080E0000  //uint32_t flash_read( uint32_t addr,uint32_t *buff ,uint32_t cnt  );
void flash_write( uint32_t addr ,uint32_t *buff ,uint32_t cnt    );#endif


#include "main.h"
#define tmep_len 30
uint8_t temp_buf[tmep_len]={0};void test();
uint8_t *mian_temp;
double time_us;
int main(void)
{ u8 key,flag ,i,n=5;           //保存键值static bool cnt;
//	delay_init(168);  //初始化延时函数software_times_base_init( 168 );uart_init(115200);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);LED_Init();				//初始化LED端口 BEEP_Init();      //初始化蜂鸣器端口KEY_Init();       //初始化与按键连接的硬件接口LED1=!LED1;LED0=!LED0;while(1){key=KEY_Scan(0);if(key==1){mian_temp=temp_buf;memset( mian_temp, 0 ,tmep_len );flash_read( FLASH_USER_ADDR,(uint32_t *)mian_temp ,tmep_len  );//读取 tmep_len 长的数据 ,并且要地址在程序区之外for(i=0;i< tmep_len;i++){printf( "%d " ,mian_temp[i]);}printf( "\r\n");}if(key==2){mian_temp=temp_buf;memset( mian_temp, n++ ,tmep_len );flash_write( FLASH_USER_ADDR ,(uint32_t *)mian_temp ,tmep_len  );//写入 tmep_len 长的数据 ,并且要地址在程序区之外mian_temp=temp_buf;memset( mian_temp, 0 ,tmep_len );flash_read( FLASH_USER_ADDR,(uint32_t *)mian_temp ,tmep_len  );for(i=0;i< tmep_len;i++){printf( "%d " ,mian_temp[i]);}printf( "\r\n");}}}

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

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

相关文章

JavaScript实现系统级别的取色器、EyeDropper、try、catch、finally

文章目录 效果图htmlJavaScript关键代码EyeDroppertry...catch颜色值相减(色差)的传送门 效果图 html <div class"d_f fd_c ai_c"><button id"idBtn" class"cursor_pointer">开始取色</button><div id"idBox" c…

PocketMiner:基于深度学习发现蛋白的隐式口袋

文章目录 1. 文章简介2. 前言3. 方法3.1 模型框架 4. 结果4.1 已知隐式口袋在分子动力学模拟分析迅速打开4.2 图神经网络模型能够准确预测模拟中口袋的动态变化4.3 隐式口袋数据集数据集揭示了新的隐式口袋形成的模式4.4 PocketMiner能够从无配体的蛋白结构中精准预测预测口袋4…

TBOX开发需求说明

TBOX功能需求&#xff1a; 支持4G上网功能&#xff0c;可获取外网IP&#xff0c;可和云端平台连通支持路由功能&#xff0c;支持计算平台、网关和云端平台建立网络连接支持USB转网口&#xff0c;智能座舱会通过USB连接AG35建立网络连接&#xff08;类似IVI通过USB口连接TBOX&a…

linux中dmesg命令用法

在Linux系统中&#xff0c;dmesg&#xff08;diagnostic message&#xff09;是一个非常有用的命令行工具&#xff0c;用于显示和控制内核环形缓冲区中的消息。这些消息通常包含系统启动时的内核生成的信息&#xff0c;例如硬件设备的状态&#xff0c;驱动程序的加载&#xff0…

浅析Linux SCSI子系统:错误恢复

文章目录 概述SCSI错误恢复处理添加错误恢复命令错误恢复线程scsi_eh_ready_devs IO超时处理相关参考 概述 IO路径是一个漫长的过程&#xff0c;从SCSI命令请求下发到请求完成返回&#xff0c;中间的任何一个环节出现问题都会导致IO请求的失败。从SCSI子系统到低层驱动&#x…

【云原生】Ansible自动化批量操作工具playbook剧本

目录 1.playbook相关知识 1.1 playbook 的简介 1.2 playbook的 各部分组成 2. 基础的playbook剧本编写实例 2.1 playbook编写Apache安装剧本&#xff08;yum方式安装&#xff09; 报错集&#xff1a; 实例2&#xff1a;playbook编写nginx 的yum安装并且能修改其监听端口的…

认识JVM的内存模型

从上一节了解到整个JVM大的内存区域&#xff0c;分为线程共享的heap&#xff08;堆&#xff09;&#xff0c;MethodArea&#xff08;方法区&#xff09;&#xff0c;和线程独享的 The pc Register&#xff08;程序计数器&#xff09;、Java Virtual Machine Stacks&#xff08;…

MVC,MVP,MVVM的理解和区别

MVC MVC &#xff0c;早期的开发架构&#xff0c;在安卓里&#xff0c;用res代表V&#xff0c;activity代表Controller层&#xff0c;Model层完成数据请求&#xff0c;更新操作&#xff0c;activity完成view的绑定&#xff0c;以及业务逻辑的编写&#xff0c;更新view&#xf…

Jenkins java8安装版本安装

一、首先准备Jenkins、Jdk8、Tomcat9安装包 根据Jenkins官网介绍&#xff0c;Jenkins支持Java8的版本如下&#xff1a; 我们选择2.164版本进行安装&#xff0c;根据版本号支持输入下载地址&#xff1a;https://archives.jenkins.io/war/2.164/jenkins.war&#xff0c;进行下载…

Mybatis 插入、修改、删除

前面几篇我们介绍了使用Mybatis查询数据&#xff0c;并且也了解了如何在Mybatis中使用JDK的日志系统打印日志&#xff1b;本篇我们继续介绍如何使用Mybatis完成数据的插入、修改和删除。 如果您对查询数据和Mybatis集成JDK日志系统不太了解&#xff0c;建议您先进行了解后再阅…

【Vue CLI】

node.js安装 https://nodejs.org/download/release/v15.14.0/ 管理员运行cmd node -v 安装npm npm install -g cnpm --registryhttps://registry.npm.taobao.org 查看是否安装成功 npm -v 注册淘宝镜像加速器 npm config set registry https://registry.npm.taobao.org/ 查看…

Vue2项目练手——通用后台管理项目第二节

Vue2项目练手——通用后台管理项目 路由限制重复跳转CommonAside.vue 顶部header组件搭建与样式修改右边用户菜单栏使用的组件图片CommonHeader.vue Vuex实现左侧折叠文件目录store/index.jsstore/tab.jsmain.jsCommonHeader.vueCommonAside.vueMain.vue 路由限制重复跳转 路由…

Qt使用Json

包含目录&#xff1a; #include <QJsonObject> #include <QJsonDocument> #include <QByteArray> #include <QFile> #include <QJsonArray>基本结构&#xff1a; 写json QJsonObject studentobj;QJsonArray arrarydata;QJsonObject subdata;…

50ETF期权开户平台(0门槛期权开户指南)

50ETF期权开户平台比较好的有&#xff1a;期权馆&#xff0c;期权科普馆&#xff0c;小熊期权&#xff0c;期权酱&#xff0c;财顺财经&#xff0c;财顺期权等&#xff0c;都是国内前十的期权分仓平台&#xff0c;下文为大家结算50ETF期权开户平台&#xff08;0门槛期权开户指南…

HTTP介绍:一文了解什么是HTTP

前言&#xff1a; 在当今数字时代&#xff0c;互联网已经成为人们生活中不可或缺的一部分。无论是浏览网页、发送电子邮件还是在线购物&#xff0c;我们都离不开超文本传输协议&#xff08;HTTP&#xff09;。HTTP作为一种通信协议&#xff0c;扮演着连接客户端和服务器的重要角…

微信小程序新版隐私协议弹窗实现最新版

1. 微信小程序又双叒叕更新了 2023.08.22更新&#xff1a; 以下指南中涉及的 getPrivacySetting、onNeedPrivacyAuthorization、requirePrivacyAuthorize 等接口目前可以正常接入调试。调试说明&#xff1a; 在 2023年9月15号之前&#xff0c;在 app.json 中配置 __usePriva…

SpringCloudAlibaba Gateway(三)-整合Sentinel功能路由维度、API维度进行流控

Gateway整合Sentinel ​ 前面使用过Sentinel组件对服务提供者、服务消费者进行流控、限流等操作。除此之外&#xff0c;Sentinel还支持对Gateway、Zuul等主流网关进行限流。 ​ 自sentinel1.6.0版开始&#xff0c;Sentinel提供了Gateway的适配模块&#xff0c;能针对路由(rou…

kaggle赛后总结

1. 宽表 2.缺失值的处理方法 最简单粗暴的就是删除&#xff0c;这种情况是凡是有缺失值行数很少。均值替代。缺失值的行数比较多一点儿的时候&#xff0c;直接删除会影响样本数量&#xff0c;那就均值替代&#xff0c;或者中位数替代等方法。还有复杂的方法&#xff0c;把有缺…

机器学习笔记之最优化理论与方法(四) 凸函数:定义与基本性质

机器学习笔记之最优化理论与方法——再回首&#xff1a;凸函数定义与基本性质 引言凸函数的定义严格凸函数凸函数的推论&#xff1a;凹函数 常见凸函数凸函数的基本性质几种保持函数凸性的运算凸集与凸函数之间的关联关系 引言 本节将介绍凸函数定义及其基本性质。 本文是关于…

设计模式—简单工厂

目录 一、前言 二、简单工厂模式 1、计算器例子 2、优化后版本 3、结合面向对象进行优化&#xff08;封装&#xff09; 3.1、Operation运算类 3.2、客户端 4、利用面向对象三大特性&#xff08;继承和多态&#xff09; 4.1、Operation类 4.2、加法类 4.3、减法类 4…