Arduino环境下对NodeMCU ESP8266的闪存flash系统使用

news2024/12/26 10:48:02

flash存储简答介绍

参考:https://www.elecfans.com/consume/572040.html
flash存储器又称闪存(快闪存储器),就其本质而言,flash存储器属于EEPROM(电擦除可编程只读存储器)类型。是一种长寿命的非易失性(在断电情况下仍能保持所存储的数据信息)的存储器。

SPIFFS(Serial Peripheral Interface Flash File System)

但是这个模块在vs code 的platformIO中编写时显示被丢弃不再进行更改。
对flash对象的操作方式就和文件的读写方式很类似,可参考:https://blog.csdn.net/weixin_43794311/article/details/104224924
https://blog.csdn.net/weixin_43794311/article/details/128322954
常用:w:写入会把旧的数据清空;r:从开始只读;a:在文件末尾添加
功能:对flash内存的写入。

想要开启使用SPIFFS需要准备

1,MCU的完好性,且有FLASH空间
2,在Arduino的IDE中,分配有flash空间(如下图所示)

下图中的FS大小就是分配的flash空间,OTA(on-the-air technologe)指的是用于固件升级分配的空间
可参考:https://blog.csdn.net/bulebin/article/details/108428643
在这里插入图片描述

在这里插入图片描述

对文件的读写

简单的写w入实例,但w方式写入会将文件中的内容清空再重新写入

主要起作用的几句程序

 SPIFFS.format(); //格式化flash也是很有用的
File dataFile = SPIFFS.open(file_name, "w");// 先清空文件中旧数据,再写入,如果是
  //File dataFile = SPIFFS.open(file_name, "a");  //这种方式就不会清楚旧数据,而是在文件最后添加内容
  dataFile.println("Hello IOT World.");       // 向dataFile写入字符串信息
  dataFile.close();                           // 完成文件写入后关闭文件
#include <FS.h>  
 
String file_name = "/MAR/notes.txt"; //被读取的文件位置和名称
 
void setup() {

  Serial.begin(9600);
  Serial.println("");
  Serial.println("SPIFFS format start");
  SPIFFS.format();    // 格式化SPIFFS。先清空了flash,
  Serial.println("SPIFFS format finish");
  
  if(SPIFFS.begin()){ // 启动SPIFFS
    Serial.println("SPIFFS Started.");
  } else {
    Serial.println("SPIFFS Failed to Start.");
  }
  //起主要作用的就是下面的四句,相当于将文件打开和写入,关闭的过程
  File dataFile = SPIFFS.open(file_name, "w");// 先清空文件中旧数据,再写入,如果是
  //File dataFile = SPIFFS.open(file_name, "a");  //这种方式就不会清楚旧数据,而是在文件最后添加内容
  dataFile.println("Hello IOT World.");       // 向dataFile写入字符串信息
  dataFile.close();                           // 完成文件写入后关闭文件
  Serial.println("Finished Writing data to SPIFFS");
}
 
void loop() {
}

读取(r)写入的内容

由于flash是断电后也不会丢失数据的存储,所以在上面程序写入内容后。即使断电后,再插上下载下面的读取程序,数据也会被读取出来。
主要起作用的程序

  //建立File对象用于从SPIFFS中读取文件
  File dataFile = SPIFFS.open(file_name, "r");   //这是r模式,表示只读

  //读取文件内容并且通过串口监视器输出文件信息
  for(int i=0; i<dataFile.size(); i++){
    Serial.print((char)dataFile.read());       
  }
#include <FS.h>

String file_name = "/MAR/notes.txt";              //被读取的文件位置和名称

void setup() {
  Serial.begin(9600);
  Serial.println("");
  
  if(SPIFFS.begin()){ // 启动闪存文件系统
    Serial.println("SPIFFS Started.");
  } else {
    Serial.println("SPIFFS Failed to Start.");
  }

  //确认闪存中是否有file_name文件
  if (SPIFFS.exists(file_name)){
    Serial.print(file_name);
    Serial.println(" FOUND.");
  } else {
    Serial.print(file_name);
    Serial.print(" NOT FOUND.");
  }

  //建立File对象用于从SPIFFS中读取文件
  File dataFile = SPIFFS.open(file_name, "r");   //这是r模式,表示只读

  //读取文件内容并且通过串口监视器输出文件信息
  for(int i=0; i<dataFile.size(); i++){
    Serial.print((char)dataFile.read());       
  }
  //完成文件读取后关闭文件
  dataFile.close();                           
}

void loop() {
}

对目录下文件的显示

主要起作用的一段

  File dataFile = SPIFFS.open(file_name, "w");// 建立File对象用于向SPIFFS中的file对象(即myFile.txt)写入信息
  dataFile.println("Hello MAR.");    // 向dataFile写入字符串信息
  dataFile.close();                           // 完成文件写入后关闭文件
  Serial.println(F("Finished Writing data to SPIFFS"));
 
  // 显示目录中文件内容以及文件大小
  Dir dir = SPIFFS.openDir(folder_name);  // 建立“目录”对象
  
  while (dir.next()) {  // dir.next()用于检查目录中是否还有“下一个文件”
    Serial.println(dir.fileName()); // 输出文件名
  }
}
#include <FS.h>
 
String file_name = "/MAR/myFile.txt"; //被读取的文件位置和名称
String folder_name = "/MAR";         //被读取的文件夹
 
void setup() {
  Serial.begin(9600);
  Serial.println("");
  
  if(SPIFFS.begin()){ // 启动闪存文件系统
    Serial.println("SPIFFS Started.");
  } else {
    Serial.println("SPIFFS Failed to Start.");
  }
 
  File dataFile = SPIFFS.open(file_name, "w");// 建立File对象用于向SPIFFS中的file对象(即myFile.txt)写入信息
  dataFile.println("Hello MAR.");    // 向dataFile写入字符串信息
  dataFile.close();                           // 完成文件写入后关闭文件
  Serial.println(F("Finished Writing data to SPIFFS"));
 
  // 显示目录中文件内容以及文件大小
  Dir dir = SPIFFS.openDir(folder_name);  // 建立“目录”对象
  
  while (dir.next()) {  // dir.next()用于检查目录中是否还有“下一个文件”
    Serial.println(dir.fileName()); // 输出文件名
  }
}
 
void loop() {
}

串口结果显示及分析,上面程序只是建立了一个/MAR/myFile.txt文件,但会出现两个,是因为flash的保持功能,就像U盘复制文件后还能在不同设备上查看。程序的下载不会处理flash部分的内存文件
在这里插入图片描述

移除文件操作

主要作用的代码

SPIFFS.remove(file_name)
#include <FS.h>

String file_name = "/MAR/notes.txt";              //被读取的文件位置和名称

void setup() {
  Serial.begin(9600);
  Serial.println("");
  
  if(SPIFFS.begin()){ // 启动闪存文件系统
    Serial.println("SPIFFS Started.");
  } else {
    Serial.println("SPIFFS Failed to Start.");
  }
  
  //从闪存中删除file_name文件
  if (SPIFFS.remove(file_name)){
    Serial.print(file_name);
    Serial.println(" remove sucess");
  } 
  else {
    Serial.print(file_name);
    Serial.println(" remove fail");
  }                       
}

void loop() {
}

显示flash的系统信息

#include <FS.h>

FSInfo fs_info;

void setup() {
  Serial.begin(9600);

  SPIFFS.begin();       //启动SPIFFS
  Serial.println("");
  Serial.println("SPIFFS Started.");

  // 闪存文件系统信息
  SPIFFS.info(fs_info);

  // 可用空间总和(单位:字节)
  Serial.print("totalBytes: ");     
  Serial.print(fs_info.totalBytes); 
  Serial.println(" Bytes"); 

  // 已用空间(单位:字节)
  Serial.print("usedBytes: "); 
  Serial.print(fs_info.usedBytes);
  Serial.println(" Bytes"); 

  // 最大文件名字符限制(含路径和'\0')
  Serial.print("maxPathLength: "); 
  Serial.println(fs_info.maxPathLength);

  // 最多允许打开文件数量
  Serial.print("maxOpenFiles: "); 
  Serial.println(fs_info.maxOpenFiles);

  // 存储块大小
  Serial.print("blockSize: "); 
  Serial.println(fs_info.blockSize);

  // 存储页大小
  Serial.print("pageSize: ");
  Serial.println(fs_info.pageSize);
}

void loop() {
}

直接向开发板的flash传入文件(2.0.3版本测试不行)

Arduino的1.x版本的可以尝试使用下面方式

旧版本的ide可以参考这个
http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/spiffs/upload-files/
在这里插入图片描述

Arduino2.x版本暂时没发现什么好的方法

可以使用vs code和插件platformIO完成

参考:https://blog.csdn.net/weixin_43794311/article/details/128736410

一个小网址的传入,和访问

参考:https://blog.csdn.net/weixin_43794311/article/details/128736410
需要使用其中修改的程序,但图片网页资源需要参考http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/spiffs/spiffs-web-server/load-imagecsss-javascript/

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

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

相关文章

矩阵求导学习

布局 分子布局 ∂y∂x(∂y∂x1∂y∂x2⋯∂y∂xn)\frac{\partial y}{\partial \mathbf{x}} \begin{pmatrix} \frac{\partial y}{\partial x_1} & \frac{\partial y}{\partial x_2} &\cdots & \frac{\partial y}{\partial x_n} \end{pmatrix} ∂x∂y​(∂x1​∂y​​…

tkinter绘制组件(38)——状态开关按钮

tkinter绘制组件&#xff08;38&#xff09;——状态开关按钮引言布局函数结构按钮主体渐变色处理颜色处理基础渐变色列表形成列表样式绑定完整函数代码效果测试代码最终效果github项目pip下载结语引言 TinUI里的状态开关按钮&#xff08;togglebutton&#xff09;和开关&…

DPU网络开发SDK—DPDK(五)

rte_eal_init 接上次内容继续对rte_eal_init()所做的工作进行分析。 18. 检查是否允许直接物理地址访问 rte_eal_using_phys_addrs()会去检查当前系统是否允许在进程虚拟地址空间直接访问物理地址。需要有两个支持条件&#xff1a;存在大页内存和能够进行虚拟地址到物理地址…

智云通CRM:如何把握拓客成交的三种时间?

在我们邀约、拜访及展示产品之后&#xff0c;客户就一定会成为你的客户吗&#xff1f;当然不尽然&#xff0c;这取决于众多因素。任何事情都不是一蹴而就的&#xff0c;我们不能刚到某个场合认识了一个人&#xff0c;就一定要立即成交&#xff0c;或者反过来因为对方此时没有需…

Pytorch实战笔记(2)——CNN实现情感分析

本文展示的是使用 Pytorch 构建一个 TextCNN 来实现情感分析。本文的架构是第一章详细介绍 TextCNN&#xff08;不带公式版&#xff09;&#xff0c;第二章是核心代码部分。 目录1. TextCNN2. TextCNN 实现情感分析参考1. TextCNN 相较于 LSTM 而言&#xff0c;我个人其实是没…

手把手教你学51单片机-C语言基础

二进制、十进制和十六进制 对于二进制来说,8 位二进制我们称之为一个字节。 我们在进行 C 语言编程的时候,我们只写十进制和十六进制,那么不带 0x 的就 是十进制,带了 0x 符号的就是十六进制。 C 语言变量类型和范围 C 语言的数据基本类型分为字符型、整型、长整型以及…

【算法题解】12. 删除链表中的节点

文章目录题目题解Java 代码实现Go 代码实现复杂度分析这是一道简单题&#xff0c;题目来自 leetcode 题目 给定一个单链表的 head&#xff0c;我们想删除它其中的一个节点 node。 只给你一个需要删除的节点 node 。你将 无法访问 第一个节点 head。 链表的所有值都是 唯一的&…

1.吴恩达机器学习课程笔记:多元梯度下降法

1.吴恩达机器学习课程笔记&#xff1a;多元梯度下降法 笔记来源&#xff1a;吴恩达机器学习课程笔记&#xff1a;多元梯度下降法 仅作为个人学习笔记&#xff0c;若各位大佬发现错误请指正 1.1 多元特征&#xff08;变量&#xff09; 每一列代表一个特征&#xff0c;例如&…

FMC子卡设计资料原理图:FMC550-基于ADRV9002双窄带宽带射频收发器FMC子卡

FMC550-基于ADRV9002双窄带宽带射频收发器FMC子卡一、产品概述 ADRV9002 是一款高性能、高线性度、高动态范围收发器&#xff0c;旨在针对性能与功耗系统进行优化。该设备是可配置的&#xff0c;非常适合要求苛刻、低功耗、便携式和电池供电的设备。ADRV9002 的工作频率为 …

计算机基础——无处不网络(2)

作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​​ 目录 前言 一.计算机网络的接入方式 1

青龙脚本-稳定阅读

稳定阅读积分 查看请求头的cookie 变量 export zzbhd 多号或换行 */ 脚本附后 /* 查看请求头的cookie 变量 export zzbhd 多号或换行*/const $ new Env(至尊宝阅读); const axios require(axios); let request require("request"); request request.defaults(…

纯手工模拟Vue中的数据劫持和代理

为什么要实现数据劫持和代理 举一个场景&#xff1a;比如在小程序开发中&#xff0c;我们需要逻辑层修改的数据能同步响应更新到视图层的页面上&#xff0c;那么底层框架在实现这种效果的时候&#xff0c;机制是什么样的呢&#xff1f; 其实这里的底层原理类似于Vue中的数据劫…

基于蜣螂算法优化的BP神经网络(预测应用) - 附代码

基于蜣螂算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录基于蜣螂算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍3.蜣螂优化BP神经网络3.1 BP神经网络参数设置3.2 蜣螂算法应用4.测试结果&#xff1a;5.Matlab代码摘要&am…

ClickHouse快速复习

ClickHouse​一.特性​1.列式数据库管理系统​2.数据压缩​3.数据的磁盘存储​4.支持SQL​5.索引​6.适合在线查询​7.支持数据复制和数据完整性​8.实时的数据更新​9.处理大量短查询的吞吐量​10.处理大量短查询的吞吐量​11.限制​二.数据类型​1.数字类型​2.浮点数(float)…

前端都在聊什么 - 第 1 期

Hello 小伙伴们早上、中午、下午、晚上、深夜好&#xff0c;我是爱折腾的 jsliang~「前端都在聊什么」是 jsliang 日常写文章/做视频/搞直播过程中&#xff0c;小伙伴们的提问以及我的解疑整理。本期对应 2023 年的 01.01-01.15 这个时间段。本期针对「工作」「学习」「规划」「…

迭代器、可迭代对象、生成器的区别和联系

目录1 迭代器2 可迭代对象3 生成器1 迭代器 迭代器是一种可以更新迭代的工具&#xff0c;迭代器对象从集合的第一个元素开始访问&#xff0c;直到所有的元素被访问完结束。但是他不能像列表一样使用下标来获取数据&#xff0c;也就是说迭代器是不能返回的。迭代器只能往前不会…

Universal Links方式:私有化部署服务器来托管apple-app-site-association文件创建通用链接

Universal Links方式:私有化部署服务器来托管apple-app-site-association第一步&#xff1a;开启Associated Domains服务第二步&#xff1a;配置Associated Domains&#xff08;域名&#xff09;第三步&#xff1a;服务器配置apple-app-site-association文件第四步&#xff1a;…

java的数据类型:引用数据类型(String、数组、枚举)

2.3.3 引用数据类型 引用数据类型大致包括&#xff1a;类、 接口、 数组、 枚举、 注解、 字符串等 它和基本数据类型的最大区别就是&#xff1a; 基本数据类型是直接保存在栈中的引用数据类型在栈中保存的是一个地址引用&#xff0c;这个地址指向的是其在堆内存中的实际位置…

四旋翼无人机学习第22节--padstack editor创建过孔

1 首先打开padstack editor软件。 2、选择过孔&#xff0c;注意与前面的博客不同&#xff0c;这里的单位最好使用mil。 在小马哥的教程中&#xff0c;过孔可以分为几类&#xff0c;下面主要对下图的五种过孔进行设置。 3、接着对过孔的孔径进行设置。 4、不做修改。 5、修…

网络交换机常见故障及解决方法

在日常的网络故障维护中我们接触最多的设备就是交换机&#xff0c;特别是接入层交换机&#xff0c;它是连接用户和交换路由设备的桥梁。但是交换机设备无论性能多么好&#xff0c;都会存在潜在故障问题&#xff0c;就像人一样&#xff0c;无论多么健康&#xff0c;也总会出现一…