Arduino - EEPROM 断电存储 (读取写入和清除)


Arduino内存结构

在这里插入图片描述

Arduino EEPROM

EEPROM ( Electrically Erasable Programmable Read Only Memory ) 全称是 电气可擦除可编程只读存储器

Arduino Uno开发板的EEPROM存储容量为:1Byte x 1024 =1KB,每一个字节存储 0~255整型数据。

知识扩展:

''B”不是最小的单位,“B”是Byte的意思 ,1Byte = 8bit(位);bit 才是最小的单位)。

bit 一般用于网络速度的描述和各种通信速度中;Byte 用于计算硬盘、内存的大小。

1B = 8bit (or1Byte=8bit )

1KB=1024B

1MB=1024KB

1GB=1024M

1TB=1024GB

在这里插入图片描述

EEPROM 库的官网说明

基于 Arduino 和 Genuino AVR 的电路板上的微控制器具有 EEPROM:当电路板关闭时其值仍会保留的存储器(如微型硬盘驱动器)。该库使您能够读取和写入这些字节。

各种 Arduino 和 Genuino 板上支持的微控制器具有不同数量的 EEPROM:ATmega328P上为 1024 字节,ATmega168和ATmega8上为 512 字节,ATmega1280和ATmega2560上为 4 KB(4096 字节)。Arduino 和 Genuino 101 板具有 1024 字节的模拟 EEPROM 空间。

使用这个库

#include <EEPROM.h>

函 数

  • EEPROM.clear清除 EEPROM 中的字节。

清除EEPROM的内容,其实就是把EEPROM中每一个字节写入0

EEPROM.write(i, 0);
  • EEPROM.read取 EEPROM 并将其值发送到计算机。
EEPROM.read(address)
  • EEPROM.write:将来自模拟入的值存储到 EEPROM。
EEPROM.write(address,value);
  • EEPROM.crc:计算 EEPROM 内容的 CRC,就像它是一个数组一样。
  • EEPROM.get:从 EEPROM 获取值并在串行上打印为浮点数。
  • EEPROM.iteration:了解如何遍历 EEPROM 内存位置。
  • EEPROM.put:使用变量语义将值放入 EEPROM。
  • EEPROM.update:将从 A0 读取的值存储到 EEPROM 中,仅在不同时写入值,以增加 EEPROM 的使用寿命。

Arduino EEPROM示例代码

EEPROM.Write()

描述:向 EEPROM 写入一个字节。

语法:EEPROM.write(address,value)

参数:

  • address:要写入的位置,从 0 ( int ) 开始

  • value:要写入的值,从 0 到 255(字节)

返回值:无

注意: EEPROM 写入需要 3.3 ms 才能完成。EEPROM 存储器的指定寿命为 10万次 写入/擦除 周期,因此您可能需要注意写入的频率。

#include <EEPROM.h>
int addr = 0; 

void setup(){

}
void loop()
{
  int val = analogRead(0) / 4;  // analog range is 0~1023 ,但是eeprom 每一个字节只能存储 0~255整型数据
  EEPROM.write(addr, val);//写入eeprom

  /***
    - Arduno Duemilanove: 512b EEPROM storage.
    - Arduino Uno:        1kb EEPROM storage.
    - Arduino Mega:       4kb EEPROM storage.    
  ***/
  
  addr = addr + 1;    //写过的地址之上+1
  
  //如果存储满了,地址清零   addr = 0;不同板子型号的EEPROM存储容量不一样
  if(addr == EEPROM.length(){
      addr = 0;
  }
  
  delay(100);
}

EEPROM.Read()

语法:EEPROM.read(address)

参数 - address:从地址下标为 0 (int) 开始读取

返回值:存储在该地址的值 value(字节)

示例代码:

#include <EEPROM.h>

int a = 0;
int value;

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

void loop()
{
  value = EEPROM.read(a);

  Serial.print(a);
  Serial.print("\t");
  Serial.print(value);
  Serial.println();

  a = a + 1;

  if (a == 512)  // 512字节
    a = 0;

  delay(500);
}

测试1 :

将计数累加的数据值写入EEPROM中,计数器数值 等于 写入的值,然后分别打印出对应的地址和值。


#include <EEPROM.h>

int addr = 0; 
int w_value;
void setup(){
  Serial.begin(9600);
}
void loop()
{
  w_value = int(millis() / 1000);
//  int val = analogRead(0) / 4;     //每一个字节存储0~255整型数据  
  Serial.print("计数器:");
  Serial.println(w_value);
  
  EEPROM.write(addr, w_value);        //写入eeprom
  
  int r_val = EEPROM.read(addr);    // 读取eeprom
  Serial.print("地址为:");
  Serial.print(addr);
  Serial.print("\t值为:");
  Serial.println(r_val);

  addr = addr + 1;                   //写过的地址之上+1
  
  //如果存储满了,地址清零   addr = 0    不同板子型号的EEPROM存储容量不一样
  if(addr == EEPROM.length()){
    addr = 0;}
    
  delay(1000);
}

一开始对EEPROM 读写数据还挺正常的,一直到计数器到 237 的时候,开始异常混乱。

但是到后面数值有恢复正常,但地址的下标编号不同步了,应该是内部计数器有误差导致的。

在这里插入图片描述

从下图可以看出,内存中的每一个字节确实只能存储 0~255 范围的数据。
在这里插入图片描述

注释掉计数器和写入的代码,用 EEPROM.read() 读取内存地址的数据。

咦,这是什么情况?

在这里插入图片描述

原来是 EEPROM.write() 写入时的数据就是这样的。

在这里插入图片描述


测试2:

#include <EEPROM.h>

int addr = 0; 
int w_value;
int a;

void (* resetFunc)(void) = 0;

void setup(){
  Serial.begin(9600);
 
  R_EROM_Init();   // 读取    
  Serial.println();
  Serial.println("清空EEPROM内存…");
  for(a = 0; a <= 512; a++){
    EEPROM.write(a, 0);   // 将EEPROM内存清空
  }
}

void R_EROM_Init(){
  int i = 0;
  int addr_value = EEPROM.read(0);
  while(1){
    Serial.print("EEPROM 中 addr[0] = ");
    Serial.println(addr_value);
    
    if(0 <= addr_value && addr_value <= 10){
      Serial.println("A");
      Serial.print("倒计时:");
      for(i = 4; i > 0; i--){
        Serial.print(i);
        Serial.print("\t");
        delay(1000);
        }
      break;
      }
    else if(11 <= addr_value && addr_value <= 21){
      Serial.println("B");
        Serial.print("倒计时:");
      for(i = 5; i > 0; i--){
        Serial.print(i);
        Serial.print("\t");
        delay(1000);
        }
      break;
      }
    else if(22 <= addr_value && addr_value <= 32){
      Serial.println("C");
      Serial.print("倒计时:");
      for(i = 6; i > 0; i--){
        Serial.print(i);
        Serial.print("\t");
        delay(1000);
        }
      break;
      }
    else{
        Serial.println("D");
        Serial.print("倒计时:");
      for(i = 3; i > 0; i--){
        Serial.print(i);
        Serial.print("\t");
        delay(1000);
        }
      break;}
    }
  
//  addr = addr + 1; //写过的地址之上+1
//  //存储满 地址清零 不同型号的板子EEPROM存储容量不一样
//  //  if(addr == EEPROM.length())
//  if(addr == 50){
//    addr = 0;
//    }
  }
void loop()
{
  w_value = int(millis() / 1000) - 5;
//  int val = analogRead(0) / 4;       // 每一个字节存储0~255整型数据  
  Serial.print("将计数器的值:");
  Serial.print(w_value);
  Serial.println(" 写入EEPROM adrr[0]");

  
//  EEPROM.write(addr, w_value);        //写入EEPROM
  EEPROM.write(0, 0);                      //内存清零
  EEPROM.write(0, w_value);            //地址0 写入EEPROM

  
//  int r_val = EEPROM.read(addr);      // 读取EEPROM
//  Serial.print("地址为:");
//  Serial.print(addr);
//  Serial.print("\t值为:");
//  Serial.println(r_val);

    
//  addr = addr + 1; //写过的地址之上+1
// 
//  //  if(addr == EEPROM.length())
//  if(addr == 50){
//    addr = 0;                    //存储满 地址归零 数据清零 不同型号的板子EEPROM存储容量不一样
//    EEPROM.clear();
//    }
    if(w_value == 50){
      resetFunc();// 重启
      }
  delay(1000);
}

在这里插入图片描述

测试3:

#include <EEPROM.h>

unsigned int addr = 0; 
unsigned int w_value;
unsigned int a;

void (* resetFunc)(void) = 0;

void setup(){
  Serial.begin(9600);
 
  R_EROM_Init();   // 读取    
  Serial.println();
  Serial.println("清空EEPROM内存…");
  for(a = 0; a <= 512; a++){
    EEPROM.write(a, 0);   // 将EEPROM内存清空
  }
}

void R_EROM_Init(){
  int i = 0;
  int addr_value = EEPROM.read(0);
  while(1){
    Serial.print("EEPROM 中 addr[0] = ");
    Serial.println(addr_value);
    
    if(0 <= addr_value && addr_value <= 10){
      Serial.println("A");
      Serial.print("倒计时:");
      for(i = 4; i > 0; i--){
        Serial.print(i);
        Serial.print("\t");
        delay(1000);
        }
      break;
      }
    else if(11 <= addr_value && addr_value <= 21){
      Serial.println("B");
        Serial.print("倒计时:");
      for(i = 5; i > 0; i--){
        Serial.print(i);
        Serial.print("\t");
        delay(1000);
        }
      break;
      }
    else if(22 <= addr_value && addr_value <= 32){
      Serial.println("C");
      Serial.print("倒计时:");
      for(i = 6; i > 0; i--){
        Serial.print(i);
        Serial.print("\t");
        delay(1000);
        }
      break;
      }
    else{
        Serial.println("D");
        Serial.print("倒计时:");
      for(i = 3; i > 0; i--){
        Serial.print(i);
        Serial.print("\t");
        delay(1000);
        }
      break;}
    }
  }
void loop()
{
  w_value = int(millis()/1000)-5;  // 每一个字节存储0~255整型数据 
  if(w_value > 50){
//    w_value = w_value % 5;  // 控制写入EEPROM adrr[0]的值始终保持在0~50范围内
    resetFunc();// 重启
  }
     
  Serial.print("将计数器的值:");
  Serial.print(w_value);
  Serial.println(" 写入EEPROM adrr[0]");

  
//  EEPROM.write(addr, w_value);        //写入EEPROM
  EEPROM.write(0, 0);                  //内存地址[0] 清零
  EEPROM.write(0, w_value);            //内存地址[0] 写 入  w_value 


  delay(1000);
}


参考资料


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Naiva

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值