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
基于 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);
}
参考资料
- [1] 零基础入门学用Arduino-智能应用篇-12 Arduino内存(2) EEPROM
- [2] arduino学习网站-太极创客
- [3] Arduino 官网 EEPROM Library