Reading and writing serial eeproms

Single Type Method Sketch1

The Idea here is to store a set of simple type variables sequentially in the EEPROM at a specific EEPROM address.

Just attach a push button connected to ground and pin 5 of the
Arduino. On start up the EEPROM values are retrieved from the EEPROM and
sent to serial Monitor.

When you push the button random values are saved to the EEPROM. To
retrieve the values simply press the reset button on the Arduino and
these same numbers are displayed (having been read from the EEPROM).

When you hit the button you can also see write execution time.

Copy Sketch

Here’s an example of the output from the serial monitor:

Press button to write to EEPROM
EEPROM Written
MIN x 58478
MAX x 58479
MIN y 58480
MAX y 58481
EEPROM Write time  (us) 23300
EEPROM Write time per byte (us) 2912
Press button to write to EEPROM
Press button to write to EEPROM
Press button to write to EEPROM
Press button to write to EEPROM
EEPROM variable read and write.
MIN x 58478
MAX x 58479
MIN y 58480
MAX y 58481
Press button to write to EEPROM

Другие полезные функции

Есть и другие полезные функции для работы с SD картой. Некоторые из них мы приведем ниже:

  • Если вы хотите проверить наличие файла на носителе, используйте функцию SD.exists(«имя_файла.txt»), которая вернет значение true или false.
  • Удалить файл можно с помощью функции SD.remove(«имя_файла.txt»). Но будьте аккуратны! Файл удалиться полностью. Никакой «корзины» или резервной копии для восстановления не останется.
  • Создать подпапку можно с помощью функции SD.mkdir(«/имя_новой_папки»). Очень удобно для структуризации ваших данных на начальном уровне. Если папка с таким именем уже существует, ничего не произойдет. Не забывайте, что вы можете воспользоваться функцией SD.exists() перед созданием папки для проверки.

Несколько полезных функций для работы с файлами:

Arduino Hardware Hookup

Okay, now that we know what EEPROM is, let’s hook one up and see what it can do! In order to get our device talking we’ll need to connect power as well as I²C serial lines. This device in particular runs at 5VDC so we’ll connect it to the 5V output of our Arduino UNO. Also, the I²C lines will need pullup resistors for communication to happen correctly. The value of these resistors depends on the capacitance of the lines and frequency you want to communicate at, but a good rule of thumb for non-critical applications is just keep it in the kΩ range. In this example, we’ll use 4.7kΩ pullup resistors.

There are three pins on this device to select the I²C address, this way you can have more than one EEPROM on the bus and address them each differently. You could just ground them all, but we’ll be wiring them so that we can drop in a higher-capacity device later in the tutorial.

We’ll use a breadboard to connect everything together. The diagram below shows the correct hookup for most I²C EEPROM devices, including the Microchip 24-series EEPROM that we sell.

Higher Capacity EEPROMs

So what if the thing that we want to store is bigger than complete text of the Ghostbusters theme as written and performed by Ray Parker Jr? As it happens, you can get EEPROM devices with much larger storage. For instance, the Microchip 24LC1025 can store up to 1025 Kbits! That’s 128KB, enough space to have some real fun with!

Using the Microchip 24LC1025 is almost exactly like using the smaller EEPROM devices but with one minor tweak. Because the memory space is so much larger, two bytes is no longer enough to represent the memory address that we want to modify. To get around this problem, the 24LC1025 splits up the memory addresses into two separate blocks. When you address the chip, you send the block selector for the block that you want to manipulate in place of where you’d usually send the first bit of the chip address. Because of this, pin A2 on the EEPROM isn’t used and needs to be tied to 5V in order for the device to work. You’ll notice that we’ve already tied A2 to 5V in our previous example, so you could use the same example circuit to hook it up!

Arduino Sketch Example Write Something in a Higher Capacity EEPROM

Along with that change to our Arduino hookup, we’ll also need to add to our code in order to switch the block select when we reach above a certain memory address. Here’s what that operation looks like when we’re writing:

Arduino Sketch Example Read Something in a Higher Capacity EEPROM

…and here it is when we’re reading:

It’s just that easy! You can get the complete Arduino example sketches here if you want to play with it yourself:

Heads up!

If you have an EEPROM device that already has data on it, running the «Write an EEPROM» code will write over the existing data and make it irretrievable. If you think there’s interesting information on your device, try reading from it first!

Шаг 4: чтение и письмо

В большинстве случаев, когда вы используете EEPROM вместе с микроконтроллером, вам не нужно сразу видеть все содержимое памяти. Вы просто будете читать и писать байты здесь и там по мере необходимости. В этом примере, однако, мы собираемся записать весь файл в EEPROM, а затем прочитать его обратно, чтобы мы могли просмотреть его на нашем компьютере. Это должно нас освоить с идеей использования EEPROM, а также дать нам представление о том, сколько данных действительно может поместиться на маленьком устройстве.

Напиши что-нибудь

Наш примерный скетч просто возьмет любой байт, поступающий через последовательный порт, и запишет его в EEPROM, отслеживая, сколько байтов мы записали в память.

Запись байта памяти в EEPROM обычно происходит в три этапа:

  1. Отправьте старший байт адреса памяти, в который вы хотите записать.
  2. Отправьте младший байт адреса памяти, в который вы хотите записать.
  3. Отправьте байт данных, который вы хотите сохранить в этом месте.

Вероятно, здесь есть несколько ключевых слов, которые просто объясняют:

Адреса памяти

Если вы представите себе, что все байты в EEPROM 512 Кбит стоят в строке от 0 до 64000 — потому что в байте 8 бит, и, следовательно, вы можете уместить 64000 байтов в EEPROM 512 Кбит — тогда адрес памяти — это место в строка, в которой вы найдете конкретный байт. Нам нужно отправить этот адрес в EEPROM, чтобы он знал, куда поместить байт, который мы отправляем.

Старшие и младшие байты

Поскольку существует 32000 возможных мест в EEPROM емкостью 256 Кбит — и поскольку 255 — это наибольшее число, которое вы можете закодировать в одном байте, — нам нужно отправить этот адрес в двух байтах. Сначала мы отправляем старший байт (MSB) — в данном случае первые 8 бит. Затем мы отправляем младший байт (LSB) — вторые 8 бит. Почему? Потому что именно так устройство их ожидает, вот и все.

Написание страницы

Запись по одному байту — это нормально, но большинство устройств EEPROM имеют так называемый «буфер записи страницы», который позволяет записывать несколько байтов за раз так же, как и один байт. Мы воспользуемся этим в нашем примере скетча. EEPROM использует внутренний счетчик, который автоматически увеличивает размер памяти с каждым последующим байтом данных, который он получает. После того, как адрес памяти был отправлен, мы можем отслеживать до 64 байтов данных. EEPROM предполагает (справедливо), что адрес 312, за которым следуют 10 байтов, будет записывать байт 0 по адресу 312, байт 1 по адресу 313, байт 2 по адресу 314 и так далее.

  1. Отправьте старший байт адреса памяти, в который вы хотите записать.
  2. Отправьте младший байт адреса памяти, в который вы хотите записать.
  3. Запросите байт данных в этом месте.

Resources and Going Further

Now that you know how to read and write serial EEPROMs, you can have all kinds of fun with your Arduino! Why stop at song lyrics? Why not store journals or bitmaps… or even sensor readings? Actually, to think of it, sensor readings are probably the most practical thing to use it for…

For more information on the Microchip 24-series EEPROM, check out the resources below:

  • Datasheet (PDF)
  • Ghostbusters (TXT)
  • Arduino Sketch Examples

    • Write an EEPROM
    • Read an EEPROM

But wait, if you’re mad with power and want even more storage for your Arduino then you should check out this awesome tutorial on the MicroSD Card Breakout!

Запись данных на SD карту через Arduino

В приведенном скетче продемонстрированы базовые возможности для записи данных на карту. По сути это основа для работы с модулем SD карты.

Serial.print(«Initializing SD card. «);

// на Ethernet шилде CS соответствует 4 пину. По умолчанию он установлен в режим output

// обратите внимание, что если он не используется в качестве CS пина, SS пин на оборудовании

// (10 на большинстве плат Arduino, 53 на Arduino Mega) надо оставить в режиме output.

// иначе функции библиотеки SD library не будут работать.

// открываем файл

Обратите внимание, что открывать несколько файлов параллельно нельзя

// перед открытием нового файла, старый надо закрыть

myFile = SD.open(«test.txt», FILE_WRITE);

// если удалось открыть файл, записываем в него:

Serial.print(«Writing to test.txt. «);

myFile.println(«testing 1, 2, 3.»);

// если файл не открылся, выводим сообщение об ошибке:

Serial.println(«error opening test.txt»);

// после setup ничего не происходит

Запустив скетч на выполнение, вы увидите следующее:

После отработки скетча, можете открыть сформированный файл на персональном компьютере. Каждая строка соответствует одному циклу работы программы. То есть, данные добавляются, а не переписываются.

Стоит отметить несколько вещей:

  • Можно одновременно открывать несколько файлов и записывать в тот, который вы выберете.
  • Для записи строк, переменных и т.п. Используются функции print и println()
  • Вы должны закрыть (close()) файл(ы) после завершения, чтобы данные точно записались!
  • Вы можете открывать файлы из подпапок. Например, если вы хотите открыть файл, который находится по адрес /MyFiles/example.txt, вы можете вызвать SD.open(«/myfiles/example.txt») и все отлично отработает.

Библиотека SD card не поддерживает ‘длинные названия’, так что имена файлов должны быть короткими! Например, IMAGE.JPG — отличное название, datalog.txt — тоже подходит. А вот что-то вроде «My GPS log file.text» не подойдет! Также учтите, названия не чувствительны к регистру. То есть, datalog.txt — это то же самое, что и DataLog.Txt или DATALOG.TXT

Часть первая, I2C и библиотека «Wire».

Последовательный протокол обмена данными IIC (также называемый I2C — Inter-Integrated Circuits, межмикросхемное соединение). Разработана фирмой Philips Semiconductors в начале 1980-х как простая 8-битная шина внутренней связи для создания управляющей электроники. Так как право на использование его стоит денег фарма Atmel назвала его TWI, но смысл от этого не меняется.

Как это работает ?

Для передачи данных используются две двунаправленные лини передачи данных. SDA (Serial Data) шина последовательных данных и SCL (Serial Clock) шина тактирования. Обе шины подтянуты резисторами к плюсовой шине питания. Передача/Прием сигналов осуществляется прижиманием линии в 0, в единичку устанавливается сама, за счет подтягивающих резисторов.

В сети есть хотя бы одно ведущее устройство (Master), которое инициализирует передачу данных и генерирует сигналы синхронизации и ведомые устройства (Slave), которые передают данные по запросу ведущего. У каждого ведомого устройства есть уникальный адрес, по которому ведущий и обращается к нему. Конечно понятно что Ведущий это наш микроконтроллер , а ведомый наша память. Ведущее устройство начинает прижимать шину SCL  к нулю с определенной частотой, а шину SDA прижимать или отпускать на определенное число тактов передавая Единичку или Нолик. Передача данных начинается с сигнала START потом передается 8 бит данных и 9-тым битом Ведомое устройство подтверждает прием байт  прижимая шину SDA к минусу. Заканчивается передача сигналом STOP.

Библиотека «Wire».

Для облегчения обмена данными с устройствами по шине I2C для Arduino написана стандартная библиотека Wire которая есть уже в комплекте IDE. Она имеет следующие основные функции:

Wire.begin(Address) вызывается один раз для инициализации  и подключения к шини как Ведущий или Ведомое устройство. Если Address не задан подключаемся как Мастер устройство.

Wire.beginTransmission(address)  начинает передачу на ведомое I2C устройство с заданным адресом.

Wire.endTransmission() прекращает передачу данных ведомому. Функция возвращает значение типа byte:

  • 0 — успех.
  • 1- данные слишком длинны для заполнения буфера передачи.
  • 2 — принят NACK при передаче адреса.
  • 3 — принят NACK при передаче данных.
  • 4 — остальные ошибки.

Wire.write() запись данных  от ведомого устройства в отклик на запрос от ведущего устройства, или ставит в очередь байты для передачи от мастера к ведомому устройству.Фактически записывает данные в буфер. Размер буфера 32 байта ( минус 2 байта адрес, фактически 30 байт), а передает буфер функция Wire.endTransmission().

  • Wire.write(value) — value: значение для передачи, один байт.
  • Wire.write(string) — string: строка для передачи, последовательность байтов.
  • Wire.write(data, length) — data: массив данных для передачи, байты. length: количество байтов для передачи.

Wire.read() Считывает байт, который был передан от ведомого устройства к ведущему или который был передан от ведущего устройства к ведомому. Возвращаемое значение byte : очередной принятый байт.

Это самые основные функции библиотеке, остальные мы рассмотрим по ходу пьесы ))

Подключение Arduino к адаптеру карт

Эти модули обычно используют последовательный периферийный интерфейс (SPI) для связи с микроконтроллером. Поэтому он будет занимать три вывода GPIO на Arduino. Кроме того, вам необходимо подключить линию выбора микросхемы, чтобы включить SD-карту и линии питания для питания адаптера.

Схема подключения Arduino к адаптеру SD-карты

Зеленая (MISO) и желтая (MOSI) линии соединяются с контактами 12 и 11 Arduino. Clock (тактовый сигнал, синий) должен быть привязан к контакту 13. Обратитесь к документации Arduino, если вы не уверены, какие контакты необходимо использовать на Arduino.

Создание динамической библиотеки

Для начала стоит сказать, что объектный файл создаваемый обычным способом не подходит для динамических
библиотек. Связано это с тем, что все объектные файлы создаваемые обычным образом не имеют представления о том в какие
адреса памяти будет загружена использующая их программа. Несколько различных программ могут использовать одну библиотеку,
и каждая из них располагается в различном адресном пространстве. Поэтому требуется, чтобы переходы в функциях библиотеки
(операции goto на ассемблере) использовали не абсолютную адресацию, а относительную. То есть генерируемый компилятором
код должен быть независимым от адресов, такая технология получила название PIC — Position Independent Code. В компиляторе
gcc данная возможность включается ключом

Теперь компилирование наших файлов будет иметь вид:

Динамическая библиотека это уже не архивный файл, а настоящая загружаемая программа, поэтому созданием динамических
библиотек занимается сам компилятор gcc. Для того, чтобы создать динамическую библиотеку надо использовать
ключ :

В результате получим динамическую библиотеку libfsdyn.so, которая по моей задумке будет динамической версией библиотеки
libfs.a, что видно из названия Теперь, чтобы компилировать результирующий файл с использованием динамической
библиотеки нам надо собрать файл командой:

Если теперь Вы сравните файлы, полученные при использовании статической и динамической библиотеки, то увидите, что их
размеры отличаются. В данном случае файл созданный с динамической библиотекой занимает чуть больше места, но это лишь
от того, что программа используемая нами совершенно примитивная и львиную долю там занимает специальный код для
использования динамических возможностей. В реальных условиях, когда используются очень большие функции размер программы
с использованием динамической библиотеки значительно меньше.

На этом фокусы не кончаются, если Вы сейчас попробуете запустить файл rezultdyn, то получите ошибку:

Это сообщение выдает динамический линковщик. Он просто не может найти файл нашей динамической библиотеки. Дело в том, что
загрузчик ищет файлы динамических библиотек в известных ему директориях, а наша директория ему не известна. Но это мы чуть
отложим, потому что это достаточно сложный вопрос.

А сейчас стоит поговорить еще об одном моменте использования библиотек. Я специально создал динамическую библиотеку с
названием fsdyn, чтобы она отличалась от названия статической библиотеки fs. Дело в том, что если у Вас две библиотеки
статическая и динамическая с одинаковыми названиями, то есть libfs.a и libfs.so, то компилятор всегда будет использовать
динамическую библиотеку.

Связано это с тем, что в ключе -l задается часть имени библиотеки, а префикс lib и окончание .a или .so приставляет сам
компилятор. Так вот алгоритм работы компилятора таков, что если есть динамическая библиотека, то она используется по
умолчанию. Статическая же библиотека используется когда компилятор не может обнаружить файл .so этой библиотеки. Во всей
имеющейся у меня документации пишется, что если использовать ключ -static, то можно насильно заставить компилятор
использовать статическую библиотеку. Отлично, попробуем…

Как бы я не пробовал играть с позицией ключа -static, результирующий файл rez1 получается размером в 900 Кб. После
применения программы strip размер ее уменьшается до 200 Кб, но это же не сравнить с тем, что наша первая статическая
компиляция давала программу размером 10 Кб. А связано это с тем, что любая программа написанная на C/C++ в Linux
использует стандартную библиотеку «C» library, которая содержит в себе определения таких функций, как printf(), write()
и всех остальных. Эта библиотека линкуется к файлу как динамическая, чтобы все программы написанные на C++ могли
использовать единожды загруженные функции. Ну, а при указании ключа -static компилятор делает линковку libc статической,
поэтому размер кода увеличивается на все 200 Кб.

Этот эффект я не смог побороть. Поэтому я пришел к выводу, что статическую библиотеку и динамическую лучше всего создавать
с разными именами. Надеюсь в будущем мы с Вами еще разберемся с этой загвоздкой, но если действительно все так плохо,
то решение с различными именами будет единственно верным.

Схема Arduino Nano ISCP

Напоследок нужно сказать о подключении программатора. Для программирования контроллеров Atmel, на которых собран модуль Arduino, используется интерфейс ICSP. Для Arduino Nano icsp распиновка выглядит так (см. Верхнюю часть предыдущего рисунка):

  1. MISO (мастер получает от подчиненного);
  2. + 5В (питание);
  3. SCK (тактовый импульс);
  4. MOSI (мастер передает подчиненному);
  5. СБРОС НАСТРОЕК
  6. GND (земля).

Первый контакт 6-контактного разъема имеет квадратную форму у основания и пронумерован по часовой стрелке, если смотреть сверху. Чтобы не возникало сомнений в порядке нумерации выводов разъема, ниже представлен фрагмент принципиальной схемы платы Arduino:

Этот разъем подключается к программатору последовательного интерфейса программирования (SPI) Atmel. Кроме того, микропрограмму контроллера можно изменить из среды программирования через USB-кабель, поэтому нет необходимости покупать программатор (он нужен только в том случае, если нет программы загрузчика).

4Чтение данных из флеш-памяти с помощью Arduino

Согласно документации, чтение из флешки выполняется посредством такой последовательности: отправка команды на чтение (1 байт), начальный адрес (3 байта), а далее запрашивается столько байтов, сколько хотим прочитать из ПЗУ. Собственно, мы будем передавать в ПЗУ 16 нулей. Так как SPI – синхронный интерфейс, нам в ответ вернутся 16 записанных в ПЗУ байтов. Вот такая диаграмма приводится в описании к микросхеме:

Диаграмма чтения данных из флеш-памяти 25L8005

Напишем скетч для чтения наших заветных 16-ти байт из микросхемы флеш-памяти 25L8005:

#include <SPI.h>

const int SSPin = 10;
const byte READ = 0x03;
const byte ADDR1 = 0;
const byte ADDR2 = 0;
const byte ADDR3 = 0;

void setup() {
  Serial.begin(9600);
  pinMode(SSPin, OUTPUT);
  SPI.begin();  
}

void loop() { 
  SPISettings mySet(100000, MSBFIRST, SPI_MODE0);
  SPI.beginTransaction(mySet);
  digitalWrite(SSPin, LOW);
  SPI.transfer(READ); 
  SPI.transfer(ADDR1);
  SPI.transfer(ADDR2);
  SPI.transfer(ADDR3);
  for (int i=0; i<16; i++) {
    byte data = SPI.transfer(0);
    Serial.print((char)data);
  }
  Serial.println();
  digitalWrite(SSPin, HIGH);
  SPI.endTransaction();
  delay(1000); // повторяем чтение каждую секунду
}

Загрузим скетч в Arduino и откроем монитор последовательных портов. В мониторе, как и ожидалось, 1 раз в секунду будет выводиться наш массив, считанный из флеш-памяти с помощью Arduino.

Чтение из флеш-памяти с помощью Arduino и вывод в монитор последовательных портов

Вот как выглядит чтение из ПЗУ, если подключиться к линиям SPI логическим анализатором:

Временная диаграмма чтения данных из ПЗУ по SPI

Как видно, байты этого массива соответствуют кодам ASCII строки «HELLO, SOLTAU.RU», которые мы и записали в микросхему памяти 25L8005

Некоторые вещи, которые необходимо учитывать при использовании библиотеки SD

Обзор

Связь между микроконтроллером и SD картой использует интерфейс SPI, который занимает цифровые выводы 11, 12 и 13 (на большинстве плат Arduino) или 50, 51 и 52 (Arduino Mega). Кроме того, для выбора SD карты должен использоваться еще один дополнительный вывод. Это может быть аппаратный вывод SS – вывод 10 (на большинстве плат Arduino) или вывод 53 (на платах Arduino Mega) – или какой-либо другой вывод, заданный с помощью вызова 

Обратите внимание, что даже если вы не используете аппаратный вывод SS, он должен быть оставлен настроенным для работы на выход, иначе библиотека SD работать не будет. Разные платы расширения для этого используют разные выводы, поэтому убедитесь в правильности выбора вывода в

Форматирование/подготовка карты

Примечание: всякий раз, когда в данной статье упоминается SD карта, это означает и SD, и microSD размеры, а также SD и SDHD форматы.

Большинство SD карт работает правильно сразу из коробки, но, возможно, ваша карта использовалась в компьютере или камере и не может быть прочитана с помощью библиотеки SD. Форматирование такой карты создаст файловую систему, в которой Arduino сможет читать и писать.

Часто форматировать SD карты нежелательно, так как это уменьшает их срок службы.

Для форматирования карты вам понадобятся SD ридер и компьютер. Библиотека поддерживает файловые системы FAT16 и FAT32, но по возможности лучше используйте FAT16.

Именование файлов

Файловые системы FAT имеют ограничения, когда в них используются соглашения по именованию файлов. Вы должны использовать формат 8.3, в котором имена файлов выглядят так «NAME001.EXT«, где «NAME001» – строка из 8 или менее символов, а «EXT» – расширение из 3 символов. Люди часто используют расширения .TXT и .LOG. Возможно использовать и более короткие имена (например, mydata.txt или time.log), но более длинные имена файлов использовать запрещается.

Открытие/закрытие файлов

Когда вы используете , то на карту ничего не будет записано, пока вы не вызовете или . Всякий раз, когда вы открываете файл, убедитесь, что закрыли его, чтобы сохранить свои данные.

Начиная с версии 1.0, стало возможно иметь открытыми сразу несколько файлов.

Различные платы расширения

Ниже приведено несколько различных плат расширения, поддерживающих SD карты. Этот список неполный, но в нем приведены наиболее часто используемые платы.

Arduino Ethernet Shield

Arduino Ethernet Shield

Плата расширения Ethernet Shield поставляется со слотом для SD карты. Плата устанавливается на Arduino сверху. Поскольку Ethernet модуль использует вывод 10, вывод CS для SD карты был перемещен на вывод 4. Для использования функционала SD карты вызывайте метод .

Adafruit Micro-SD breakout Board

Adafruit Micro-SD breakout Board

Данная плата поддерживает Micro-SD карты. Перед использованием ее необходимо правильно подключить к Arduino. Вывод GND на плате соедините с шиной земли на Arduino, вывод 5V – с шиной 5V, CLK – с выводом 13 на Arduino, DO – с выводом 12, DI – с выводом 11, CS – с выводом 10. Если вы уже используете вывод 10, то можете к CS подключить другой вывод, но не забудьте изменить вывод в .

Sparkfun SD Shield

Sparkfun SD Shield

Плата расширения Sparkfun устанавливается на Arduino сверху и использует вывод 8 для CS. При использовании SD карты вам необходимо вызвать метод .

Arduino EEPROM запись, чтение данных

Для этого занятия потребуется:

Arduino Uno / Arduino Nano / Arduino Mega

Скетч. Чтение Arduino EEPROM (read)

#include <EEPROM.h>  // импортируем библиотеку
int address;                     // переменная для хранения адреса
byte value;                      // переменная для хранения значения

void setup() {
   Serial.begin(9600);  // запускаем монитор порта
   Serial.println(EEPROM.length());  // выводим общее количество ячеек в памяти
   delay(3000);

   // перебираем в цикле все адреса в EEPROM памяти, пока все не переберем
   while (address < EEPROM.length()) {
      value = EEPROM.read(address);  // считываем значение байта
      Serial.print("Address: ");               // выводим полученные данные на монитор порта
      Serial.print(String(address));
      Serial.print(", value: ");
      Serial.println(String(value));
      address++;                                       // наращиваем адрес и повторяем операции
      delay(100);
   }
}
void loop() {
}

Пояснения к коду:

  1. функция позволяет узнать общее число ячеек в памяти. Если вы работаете с Nano ATmega168, то цикл закончится на 512 ячейке;
  2. если память не использовалась, то все значения в ячейках будут равны 255.

Скетч. Запись Arduino EEPROM (write)

#include <EEPROM.h>  // импортируем библиотеку
int address;                     // переменная для хранения адреса
byte value;                      // переменная для хранения значения

void setup() {
   Serial.begin(9600);  // запускаем монитор порта
   Serial.println(EEPROM.length());  // выводим общее количество ячеек в памяти
   EEPROM.write(0,100);                    // записываем значение 100 в ячейку с адресом 0
   delay(3000);

   // перебираем в цикле все адреса в EEPROM памяти, пока все не переберем
   while (address < EEPROM.length()) {
      value = EEPROM.read(address);  // считываем значение байта
      Serial.print("Address: ");               // выводим полученные данные на монитор порта
      Serial.print(String(address));
      Serial.print(", value: ");
      Serial.println(String(value));
      address++;                                       // наращиваем адрес и повторяем операции
      delay(100);
   }
}
void loop() {
}

Пояснения к коду:

  1. функция каждый раз перезаписывает данные в ячейке с адресом 0, что снижает жизненный цикл памяти, лучше использовать ;
  2. в следующих примерах не будем перебирать все ячейки в памяти, а запишем и прочитаем только несколько байт в энергонезависимой памяти Ардуино.


Пример работы предыдущей программы

Скетч. Перезапись в Arduino EEPROM (update)

#include <EEPROM.h>  // импортируем библиотеку

void setup() {
   Serial.begin(9600);  // запускаем монитор порта

   EEPROM.update(0,100);               // записываем значение 100 в ячейку с адресом 0
   delay(2000);

   Serial.println(EEPROM.read(0));  // выведет на монитор порта 100
   Serial.println(EEPROM);          // выведет на монитор порта 100
   }
}
void loop() {
}

Пояснения к коду:

  1. вывод данных из ячейки с адресом 0 выполняется с помощью разных функций;
  2. функции write/read/update позволяют работать только с типами данных byte и использовать эти функции для данных типа float или int уже нельзя. Для этого следует использовать put/get, которые мы рассмотрим далее.

Подстроечный резистор и EEPROM

Чтобы было понятней, как работает EEPROM и как ее использовать, попробуем реализовать небольшой пример. Подключим к ардуино подстроечный резистор, кнопку и пять светодиодов(не забыв про резисторы, чтобы не сжечь светодиоды). И напишем небольшой скетч: по нажатию на кнопку будем считывать значения с подстроечного резистора и конвертировать их в число от 0 до 4х. По повторному нажатию на кнопку, будем сохранять полученное значение в EEPROM. И уже в зависимости от записанного значения, зажжем соответствующее количество светодиодов. Если после перезагрузки или после отключения питания arduino, будет гореть нужное количество огоньков, значит все работает и эксперимент можно считать успешным.
Чтобы было понятней, ниже приведена схема подключения всех элементов.

2.0 Описание выводов

Таблица 2-1: Назначение выводов

Название PDIP 8 SOIC 8 TSSOP 8 MSOP 8 DFN 8 CS Назначение
A0 1 1 1 1 3 Настраиваемый сигнал выбора микросхемы
A1 2 2 2 2 2
(NC) 1, 2 Не соединяется
A2 3 3 3 3 3 5 Сигнал выбора микросхемы
Vss 4 4 4 4 4 8 Земля
SDA 5 5 5 5 5 6 Данные
SCL 6 6 6 6 6 7 Тактовый сигнал
(NC) Не соединяется
WP 7 7 7 7 7 4 Вход защиты от записи
Vcc 8 8 8 8 8 1 от +1.7В до 5.5В (24AA256)
от +2.5В до 5.5В (24LC256)
от +1.7В до 5.5В (24FC256)

2.1 Адресные выводы A0, A1, A2

Уровни на этих выводах сравниваются с соответствующими битами в
адресе ведомого устройства. И в случае их совпадения микросхема —
активируется.

В варианте с корпусом MSOP выводы A0 и A1 не соединены.

Используя комбинации адресных выводов, к одной шине можно
подключить до 8 микросхем(2 для случая MSOP). Эти выводы должны подключаться
либо к Vss либо к Vcc.

В большинстве случаев, адресные выводы A0, A1 и A2 жестко
соединены с логическим ‘0’ или ‘1’. В приложениях, где эти выводы управляются
микроконтроллером или другим программируемым устройством, адресные выводы
должны быть установлены в логические ‘0’ или ‘1’ до того как начнётся работа
с микросхемой.

2.2 Линия данных (SDA)

Это
двунаправленный вывод, используется для передачи адреса и данных
в/из микросхемы. Является выводом с открытым стоком. Поэтому, для
вывода SDA необходима установка подтягивающего к Vcc резистора(10кОм для
100кГц, 2кОм для 400кГц и 1МГц). Во время передачи данных изменение сигнала
SDA допускается только во время низкого уровня SCL. Изменения во время
высокого уровня SCL указывают на сигнал START или STOP.

Этот вывод должен быть подключен либо к Vss либо к Vcc. Если
соединен с Vss операции записи разрешены. Если соединен с Vcc операции записи
запрещены, на операции чтения состояние вывода не влияет.

Понравилась статья? Поделиться с друзьями:
Зинг-Электро
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: