Программирование Arduino — EEPROM


11. Энергонезависимая память EEPROM

EEPROM — (Electrically Erasable Programmable Read-Only Memory) электрически стираемое перепрограммируемое ПЗУ, ЭСППЗУ). Память такого типа может стираться и заполняться данными несколько десятков тысяч раз. Используется в твердотельных накопителях. Одной из разновидностей EEPROM является флеш-память (Flash Memory).

Микроконтроллеры Atmega8 и Atmega168, работающие в Arduino имеют на борту 512 байт EEPROM – энергонезависимой памяти, в которой можно сохранять какие-либо данные, которые будут доступны после отключения питания.

Это может пригодиться для хранения каких-нибудь данных или значений.

Для работы с данной памятью в составе Arduino IDE уже есть удобная библиотека EEPROM (\hardware\libraries\EEPROM\).

Библиотека содержит всего две функции – чтения и записи данных 🙂

class EEPROMClass
{
  public:
    uint8_t read(int);
    void write(int, uint8_t);
};

extern EEPROMClass EEPROM;

byte EEPROM.read(address)

Описание:
Считывает байт из энергонезависимой памяти EEPROM. Если байт до этого никогда не перезаписывался – вернёт значение 255.

Параметры:
address: порядковый номер ячейки памяти для чтения — от 0 до 511 (int)

Возвращаемое значение:
Байт, хранимый в ячейке памяти.

Пример (File-Examples-EEPROM-eeprom_read):

/*
 * Чтение EEPROM
 *
 * Считывает значения всех байтов энергонезависимой памяти  
 * EEPROM и выводит их в COM-порт
 */

#include <EEPROM.h>

// начальный адрес памяти EEPROM
int address = 0;
byte value;

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

void loop()
{
  // считываем значение по текущему адресу EEPROM
  value = EEPROM.read(address);
  
  Serial.print(address);
  Serial.print("\t");
  Serial.print(value, DEC);
  Serial.println();
  
  // устанавливаем следующую ячейку памяти
  address = address + 1;
  
  // EEPROM содержит всего 512 байт: от 0 до 511, поэтому
  // если адрес достиг 512, то снова переходим на 0
  if (address == 512)
    address = 0;
    
  delay(500);
}

void EEPROM.write(address, value)

Описание:
Записывает байт в энергонезависимую память

Параметры:
address: порядковый номер ячейки памяти для записи — от 0 до 511 (int)
value: байт для записи – от 0 до 255 (byte)

Возвращаемое значение:
ничего

Примечание:
Документация (datasheet) на микроконтроллеры Atmega8/168 говорит, что возможное количество циклов перезаписи данных в памяти ограничено 100000 раз (Write/Erase Cycles). Это следует учитывать при использовании данной памяти.
Так же документация указывает, что время, требуемое для завершения цикла записи составляет 3.3 ms. Если в это время попытаться что-либо считать/записать в EEPROM, то такая попытка окончится неудачей 🙁
Однако, данная задержка уже учитывается библиотекой EEPROM, поэтому в дополнительном вызове delay() нет необходимости.

Пример (File-Examples-EEPROM-eeprom_write):

/*
 * EEPROM Write
 *
 * Сохраняет в энергонезависимой памяти EEPROM значения,
 * считанные с аналогового входа analog input 0.
 * Данные значения останутся в памяти и после отключения питания 
 * от платы и в будущем могут быть доступны для 
 * другого скетча.
*/

#include <EEPROM.h>

// текущее значение адреса EEPROM
int addr = 0;

void setup()
{
}

void loop()
{
  // деление на 4 необходимо, чтобы перевести значение от
  // 0-1023 к одному байту, т.к. EEPROM может хранить только 
  // значения от 0 до 255.
  int val = analogRead(0) / 4;
  
  // записываем значение в энергонезависимую память
  EEPROM.write(addr, val);
  
  // устанавливаем следующую ячейку памяти. 
  // т.к. EEPROM содержит всего 512 ячеек – при достижении 
  // конца памяти – возвращаемся на начало :)
  addr = addr + 1;
  if (addr == 512)
    addr = 0;
  
  delay(100);
}

В примере eeprom_clear (File-Examples-EEPROM-eeprom_clear)
показано, как произвести очистку памяти – просто заполнить её нулями:

// записываем 0 во все 512 байт памяти EEPROM
  for (int i = 0; i < 512; i++)
    EEPROM.write(i, 0);

Пример. EEPROM - чтение/запись int

#include <EEPROM.h> //Needed to access the eeprom read write functions

//This function will write a 2 byte integer to the eeprom at the specified address and address + 1
void EEPROMWriteInt(int p_address, int p_value)
	{
	byte lowByte = ((p_value >> 0) & 0xFF);
	byte highByte = ((p_value >> 8) & 0xFF);

	EEPROM.write(p_address, lowByte);
	EEPROM.write(p_address + 1, highByte);
	}

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int EEPROMReadInt(int p_address)
	{
	byte lowByte = EEPROM.read(p_address);
	byte highByte = EEPROM.read(p_address + 1);

	return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
	}

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

	EEPROMWriteInt(0, 0xABCD);

	Serial.print("Read the following int at the eeprom address 0: ");
	Serial.println(EEPROMReadInt(0), HEX);
	}

void loop()
	{
	}

читать далее: 12. Создание своей библиотеки

Ссылки
http://www.arduino.cc/en/Reference/EEPROM
http://ru.wikipedia.org/wiki/EEPROM
Implementation of an eeprom integer read / write


5 комментариев на «“Программирование Arduino — EEPROM”»

    • Это понятно. Просто этот пример хорошо бы сразу в статью )

  1. есть ли способ записи, чтобы уменьшить износ ячеек памяти?
    программа пишет нужное значение в ПЗУ в ячейку 0, потом оттуда при необходимости считывает остальная пзу свободна. можно сделать так: ищем ячейку где не нулевое значение, считываем. когда нужно записать число, то в предыдущую пишем 0, адрес для чтения сдвигаем на 1.

  2. Объясните пожалуйста, зачем в данном случае

    return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);

    нужны битовые маски 0xFF и 0xFF00? разве без них не получится то же самое?

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Arduino Bluetooth CraftDuino DIY Google IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение