В первой части был рассмотрен пример побайтовой записи/чтения данных в электрически стираемое перепрограммируемое ПЗУ с интерфейсом I2C.
Однако, может возникнуть потребность быстрой записи/чтения целого массива данных…
24С64 может и такое. В общем случае надо указать начальный адрес места куда хотим что-то записать и число записываемых байт информации. Микросхема сама справится с заданием. Таким образом можно сэкономить время на передаче очередного адреса ячейки памяти.
!!! Есть некотрая особенность такого режима: при работе через I2C непосредственно (без использования ардуиновских библиотек), все адреса должны быть в пределах одной страницы (для 24С64 страница содержит 32 байта). При попытке передать большее число данных — они будут перезаписывать байты той же страницы.
Коротко про 24Сххх: вид микросхемы:
Здесь: питание подаем на VCC (обычно от 1,6В до 5,5В), VSS — это «земля».
SCL и SDA — это шина I2C (Clock и Data);
WC (Write Control) — это вход для «защиты» от случайной записи — редко когда нужный вывод — его надо либо оставить свободным, либо «посадить» на землю — в противном случае произвести запись данных в микросхему не удастся.
Три входа Е0-Е2 (в некоторых исполнениях их может и не быть) — Chip Enable — входы выбора микросхемы. Комбинация сигналов на них определяет адрес микросхемы на шине I2C. Именно эта комбинация должна быть в битах b1-b3 7-битного кода выбора устройства:
Входы можно оставить «висящими в воздухе» — это воспримется микросхемой как «0». Как видно из таблицы, адрес микросхемы в этом случае будет 0х50.
Как отмечено выше, емкость EEPROM может быть разной и узнать ее можно из цифр названия после «24С»: например в примере ниже 24C64 — это 64Кбит (именно бит! а не байт! как многим бы хотелось), т.е. 8КБайт.
Микросхему будем подключать к Arduino UNO.
Питание (+5В) подаем на вывод 8 микросхемы, GND соединяем с 4. SDA (A4 Arduino UNO) к ножке 5, а SCL (A5 Arduino UNO) — к 6. Остальные «ножки» микросхемы оставляем не подключенными.
Корпус 24С64 имеет 8 ножек, выводы располагаются так, как показано на рисунке:
Программированием особенно не заморачиваемся — используем одну из многочисленных библиотек (берем с Github-a). Не забываем распаковать архив, убрать «master» из названия и папочку «\Eeprom24C32_64» укладываем в ..\Arduino\libraries.
Для проверки «страничной» записи/чтения берем стандартный пример WriteReadBytes из примеров библиотеки (привожу код примера — тут я убрал комментарии):
/****************************************************************** * \brief EEPROM 24C32 / 24C64 library for Arduino - Demonstration * \author Copyright (C) 2012 Julien Le Sech - www.idreammicro.com * \version 1.0 * \date 20120218 *******************************************************************/ #include <Wire.h> #include <Eeprom24C32_64.h> #define EEPROM_ADDRESS 0x50 static Eeprom24C32_64 eeprom(EEPROM_ADDRESS); void setup() { // Initialize serial communication. Serial.begin(9600); // Initialize EEPROM library. eeprom.initialize(); const word address = 0; const byte count = 94; // Declare byte arrays. byte inputBytes[count] = { 0 }; byte outputBytes[count] = { 0 }; // Fill input array with printable characters. See ASCII table for more // details. for (byte i = 0; i < count; i++) { inputBytes[i] = i + 33; } // Write input array to EEPROM memory. Serial.println("Write bytes to EEPROM memory..."); eeprom.writeBytes(address, count, inputBytes); // Read array with bytes read from EEPROM memory. Serial.println("Read bytes from EEPROM memory..."); eeprom.readBytes(address, count, outputBytes); // Print read bytes. Serial.println("Read bytes:"); for (byte i = 0; i < count; i++) { Serial.write(outputBytes[i]); Serial.print(" "); } Serial.println(""); } void loop() { }
Код прост: используем стандартную библиотеку для I2C из Wire и скачанное выше.
#include <Wire.h> #include <Eeprom24C32_64.h>
Определяем адрес микросхемы 0х50 — см.выше — так определено на выводах Е0-Е2.
#define EEPROM_ADDRESS 0x50
Далее после инициализации микросхемы
eeprom.initialize();
(где, собственно, выполняется только вызов процедуры Wire.begin();), определяем начальный адрес — куда будем писать
const word address = 0;
и количество записываемых байт
const byte count = 94;
Вот тут самое интересное — 94 явно больше 32, но с упомянутым выше ограничением библиотека справляется сама!
Не забываем определить записываемый массив в памяти ATmega
byte inputBytes[count] = { 0 };
Далее пишем массив в EEPROM
eeprom.writeBytes(address, count, inputBytes);
Потом читаем из EEPROM эти данные и помещаем их в другой массив
eeprom.readBytes(address, count, outputBytes);
и выводим прочитанное на экран. Если увидим последовательность ASCII символов — значит все работает нормально.
Так оно и случилось…
Пример простейший, описывает запись/чтение массивов в EEPROM.
!!!ВНИМАНИЕ. Как известно, «флешки» не отличаются уж очень высокой скоростью записи информации… Так и в EEPROM 24Cxxx — есть такой параметр Internal write cyrcle. Длительность цикла записи отличается в разных микросхемах. «С запасом» можно брать его равным 10мс (бывают микросхемы и 5мс). Цикл запускается после получения всей информации о записываемых данных (адрес ячейки и байт (страница) данных). Во время записи микросхема игнорирует запросы.
Надо помнить, что пауза в эти 10 мс «вшита» в используемую библиотеку и работает для каждой страницы (32 байта для 24С64) при выполнении процедуры writeBytes().
Thanks for the site, it is loaded with so much useful information. This helped me a lot.