Запись и чтение at24c32

dardik
Offline
Зарегистрирован: 09.03.2013

Добрый день.  Arduino только начинаю осваивать. Помогите разобраться. Без проблем пишу и читаю по 1 байту.

Функция для записи:

  void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
    int rdata = data;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.write(rdata);
    Wire.endTransmission();
  }

Функция для чтения:

 byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
    byte rdata = 0xFF;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.endTransmission();
    Wire.requestFrom(deviceaddress,1);
    if (Wire.available()) rdata = Wire.read();
    return rdata;
  }

Пример:

//записываю единицу по адресу 4000

i2c_eeprom_write_byte( 0x50, 4000, 1 );
 delay(10);

//считываю данные по адресу 4000

byte b = i2c_eeprom_read_byte(0x50, 4000);

Вопрос: как записать 2х байтовое число по адресу 4000? Я понимаю, что в 1 ячейку не поместится, тоесть нужно записывать по адресу 4000 и 4001. Как реализовать такую запись и чтение. Например, я хочу записать в по адресу 4000 значение 3000, а затем считать это значение 3000.

 

Видел функцию, которая возможно и может так делать, но не могу разобраться...

//пишет

void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) {
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddresspage >> 8)); // MSB
    Wire.write((int)(eeaddresspage & 0xFF)); // LSB
    byte c;
    for ( c = 0; c < length; c++)
      Wire.write(data[c]);
    Wire.endTransmission();
  }

//читает

 void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.endTransmission();
    Wire.requestFrom(deviceaddress,length);
    int c = 0;
    for ( c = 0; c < length; c++ )
      if (Wire.available()) buffer[c] = Wire.read();
  }

maksim
Offline
Зарегистрирован: 12.02.2012
dardik
Offline
Зарегистрирован: 09.03.2013

Спасибо!

MacSim
Offline
Зарегистрирован: 28.11.2012

Возник вопрос:

все ли ячейки памяти 24С32, установленную на часах модуле часов 3231, можно использовать для своих нужд, или что-то используют часы?

почитайте, пожалуйста, с адреса 0 до 25. какие значения там? 65-90?

пытался писать с 0-го адреса. значеня  по адресам 1 и 2 сбиваются, на 66 и 67.

видимо 3231 туда  пишет.

 

 

Fremen72
Offline
Зарегистрирован: 03.04.2016

Для начала в реализации zs-042 имеет на борту АТ24С32 начальный адрес которой 0x68. И действительно первые 16 байт заняты под часы. Таким образом доступная рамять начинается с 0x78

MacSim
Offline
Зарегистрирован: 28.11.2012

Fremen72 пишет:

Для начала в реализации zs-042 имеет на борту АТ24С32 начальный адрес которой 0x68. И действительно первые 16 байт заняты под часы. Таким образом доступная рамять начинается с 0x78

 

В моем случае не было задержки после записи байта. писался мусор. добавил, все ок, работает как часы, китайские :-)

откуда такая информация?

0х68 начальный адрес? то есть перемычками я меняю начальный адрес? есть сомнения. 68-адрес устройства на шине, а не памяти

dhog1
Offline
Зарегистрирован: 01.03.2016

Разрешите побыть КО (капитаном).

Вот два модуля RTC 3231 с Ali, оба "сверху" и потом "снизу". На одном напаяна память 24С32 (4 кБ) и он справа, на другом такой памяти нет.

 

Разумеется, оба модуля работают как RTC часы DS3231 без вопросов (левый не имеет встроенной подтяжки I2C шины, правый имеет 4.7 кОм подтягивающие резисторы). Разумеется, "часы" писать сами по себе куда-либо вовне (например, в EEPROM на той же плате модуля) не могут и не умеют.

Разумеется на фото справа перемычки (A0, A1 и A2) относятся к EEPROM памяти, позволяют изменять ее адрес, в то время как I2C адрес DS3231 ("часы") остается 0x68. Если что, то I2C адрес напаяной 24С32 EEPROM (на фото справа) по умолчанию 0x57 (перемычки не запаяны).

Как представляется разумным, добавление EEPROM к RTC есть калька с удачного проекта, когда к работе RTC добавляют _расписание_, по аналогии с расписанием школьных звонков по дням недели и, может быть, по классам (учащихся). "Регулярную" задачу для часов придумать несложно.

Ну и, разумеется, никакой мистики во всем этом не имеется. Просто часы, просто бесплатно еще и 4 кБ (I2C eeprom) памяти.

 

MacSim
Offline
Зарегистрирован: 28.11.2012

вот и я о том-же. а память использовал как раз для будильников.

dhog1
Offline
Зарегистрирован: 01.03.2016

Посчитал нужным дополнить пост "от имени КО" тем, что от MacSim (дата регистрации на форуме 28/11/2012) многому (ну или кое-чему, что тоже значительно) научился "в процессе". Спасибо.

sav liana
Offline
Зарегистрирован: 28.11.2016

При работе с памятью 24C32 (i2c 0x57) в модуле DS3231

 Пример ... была ошибка, Arduino: 1.6.4 (Windows XP), Плата"Arduino Uno"

collect2.exe: error: ld returned 5 exit status
Ошибка компиляции.
 
 
ИгорьУ
Offline
Зарегистрирован: 24.04.2016

Покритикуйтье меня пожалуйста. Я хочу этот модуль применить к следующей задаче. Мне надо опредилить время между аварийным выключением питания и включением. Вот такая блок схема предлагается. Я считываю время с модуля ардуинкой каждую минуту и записываю в память модуля (EEPROM ардуины не подходит изза ограниченого колличества записей). Если ардуина замечает что разница текущего времени и времени в памяти модуля больше минуты, значит питание отключалось, ну и дальше понятно на сколько. Что скажите специалисты? Спасибо. 

Logik
Offline
Зарегистрирован: 05.08.2014

У at24c32 тоже ограничено число циклов записи, так что решение не лучшее. Заводите сигнал с питания на прерывание, а питание поддерживайте электролитами. Тогда при исчезновении питания, пока работает от электролитов ловите прерывание и записывайте время в EEPROM. Можна и во внутрений, без разницы впринципе. 

ИгорьУ
Offline
Зарегистрирован: 24.04.2016

Спасибо. Но мне непонятно все же как ардуина поймет что питание отключилось и пора сбрасывать в EEPROM. Может имеется ввиду что можно успеть зафиксиповать уменьшение напряжения питания от кнденсатора, пока он будет розряжаться. Какая тогда схема. Мне она видится следующим образом = Запитываем ардуину от стабилизированого  источника до 12 В. електролитический конденсатор подключаем паралельно входному питанию и измеряем напряжение самой ардуиной. Когда напряжение станет ниже скажем 10В Начинаем аварийное сохранение данных и может успеем записаться до полной разрядки конденсатора. И тут возникает вопрос какой емкости брать конденсатор, ибо... ибо от этого будет зависеть погрешность в измерении времени

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

ИгорьУ, либо как говорит Logik (кстати этот вариант мы неоднократно обсуждали на форуме, ищите) , либо можно взять часы на чипе DS1307, в нём есть пользовательское ОЗУ на 56 байт, пиши в него сколько хошь..

ИгорьУ
Offline
Зарегистрирован: 24.04.2016

 (кстати этот вариант мы неоднократно обсуждали на форуме, ищите) Спасибо, Хоть по каким ключевым словам искать

Начинает доходить почему необходимо измерять напряжение  именно с использованием прерывания. 

wan-derer.ru
Offline
Зарегистрирован: 06.10.2017
dhog1 пишет:
 
... I2C адрес напаяной 24С32 EEPROM (на фото справа) по умолчанию 0x57 (перемычки не запаяны)
 
 
Спасибо автору исходного поста и dhog1, с этими данными всё работает.
Вопрос. Читаю доку на 24С32, стр 9 и получается что 24С32 должна видеться как 2 устройства:
1010 111 0 (0xAE) на запись
1010 111 1 (0xAF) на чтение
 
В реальности же всё сдвинуто вправо и микросхема видится как одно устройство 0x57
 
Как это понимать? Особенность I2C? Особенность библиотеки wire?
Просветите, пжлст!
 
 
sadman41
Offline
Зарегистрирован: 19.10.2016

Первые семь битов первого байта образуют адрес ведомого. Восьмой, младший бит, определяет направление пересылки данных. «Ноль» означает, что ведущий будет записывать информацию в выбранного ведомого. «Единица» означает, что ведущий будет считывать информацию из ведомого.(C) Wikipedia

В вашем случае 0x57 - адрес, а 0/1 справа - направление данных. Приписывать его к адресу не надо, библиотека сама добавит этот бит в зависимости от выбранной операции