Эмулятор EEPROM по I2C на arduino nano

grial78
Offline
Зарегистрирован: 07.12.2015

Доброго времени суток! Помогите разрешить вопрос. Есть приборчик на Atmega 32A, который использует внешнюю память 24c02wp. Нужно эмулировать эту EEPROM хотя бы на чтение. Частично я эту задачку решил на Arduino Nano 328 на стандартной библиотеке:

#include <Wire.h>
char BB[256] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};

  Wire.begin(80);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // register event
  Wire.onRequest(requestEvent); // register event

void requestEvent(){
  if (fl == 0) Wire.write(BB, 32); /* Работает!!! */
/*  if (fl == 0) Wire.write(BB, 255); Не работает Работает!!! */
}

void receiveEvent(int howMany) {
  b  = Wire.read();
};

void loop() {}

Но когда я пытаюсь отправить более 32 байт (Wire.write(BB, 255)), на устройство приходит совсем не то, что отправил эмулятор. Если отправить только 32 байта, то устройство получает их без проблем, но этого не достаточно для нормальной работы- нужно отправить весь массив.  Что-то с этим можно сделать? 

b707
Онлайн
Зарегистрирован: 26.05.2017

grial78 пишет:

Но когда я пытаюсь отправить более 32 байт (Wire.write(BB, 255)), на устройство приходит совсем не то, что отправил эмулятор. Если отправить только 32 байта, то устройство получает их без проблем, но этого не достаточно для нормальной работы- нужно отправить весь массив.  Что-то с этим можно сделать? 

Внутренний буфер I2C - 32 байта, поэтому больше за один раз отправить нельзя.

Можно, конечно, увеличить буфер, но правильнее просто отправлять данные порциями менее 32 байт

grial78
Offline
Зарегистрирован: 07.12.2015

Т.е. разбить весь массив на 8 частей и отправлять их подряд? Типа такого Wire.write(BB0, 32); Wire.write(BB1, 32);...

А как можно буфер увеличить? Я так понимаю, нужно лезть в библиотеку Wire, это если первый вариант не получится.

grial78
Offline
Зарегистрирован: 07.12.2015

Вариант с разбиением массива почему-то не прошел.

Установил #define TWI_BUFFER_LENGTH 256 - заработало почти как надо. Осталось разобраться с переопределением библиотек, думаю, разберусь здесь сам.

Спасибо за дельную мысль! 

astwo
Offline
Зарегистрирован: 10.07.2019

grial78 пишет:

Т.е. разбить весь массив на 8 частей и отправлять их подряд? Типа такого Wire.write(BB0, 32); Wire.write(BB1, 32);...

А как можно буфер увеличить? Я так понимаю, нужно лезть в библиотеку Wire, это если первый вариант не получится.


Буфер увеличить не получится. Это аппаратное ограничение. Причём со стороны ОЗУ.

grial78
Offline
Зарегистрирован: 07.12.2015

А за что тогда отвечает  #define TWI_BUFFER_LENGTH из twi.h? 

astwo
Offline
Зарегистрирован: 10.07.2019

За то что бы альтернативно гениальные программисты не отправляли больше. Чем вам существующая библиотека мешает работать с этой памятью. В ней авторы решили эту проблему.

grial78
Offline
Зарегистрирован: 07.12.2015

Так я выше написал, что не могу отправить больше 32 байт- начинаются глюки. Последовательная отправка по-кускам тоже не спасает- похоже, после первого, остальные просто игнорируются. Альтернативно-гениальное программирование это, конечно, не по-феншую, но в конкретном случае работает :) . Если есть другие, более правильные, решения- с интересом выслушаю.

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

grial78 пишет:

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

Потомучто, EEPROM-у надо сначала адрес передать, а потом то, что туда записывается.  Ты даташыт на него читал?  Или даже в глаза не видел?  Методом гадания альтернативно программируешь?

astwo
Offline
Зарегистрирован: 10.07.2019

Скачать и установить библиотеку. У микросхемы ОЗУ входной буфер 32 байта. Но первые два байта это адрес куда писать. Потом нужна пауза, так как микросхема пишет из буфера в память. И что бы это узнать надо читать даташит на микросхему. Ну так по феншую что бы карму себе не портить

grial78
Offline
Зарегистрирован: 07.12.2015

DetSimen:

Специально для вас повторю вкратце ТЗ: мне нужно эмулировать EEPROM, а не писать на него!

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Тада понятно. 

astwo
Offline
Зарегистрирован: 10.07.2019

grial78 пишет:

DetSimen:

Специально для вас повторю вкратце ТЗ: мне нужно эмулировать EEPROM, а не писать на него!

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

grial78
Offline
Зарегистрирован: 07.12.2015

astwo:

"Холоп" это вы про себя? 

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

b707
Онлайн
Зарегистрирован: 26.05.2017

grial78 пишет:

Т.е. разбить весь массив на 8 частей и отправлять их подряд? Типа такого Wire.write(BB0, 32); Wire.write(BB1, 32);...

зачем разбивать на отдельные массивы? - этот массив последовательно и отправляйте.

А способ с увеличением буфера тупиковый. А если завтра понадобится отправить 10 Кб - куда еще буфер увеличивать будете?

grial78
Offline
Зарегистрирован: 07.12.2015

Wire.write может отправить только n байт с начала массива. Так что два варианта- или пробегать массив в  раздецикле или разделить на части и отправлять оптом каждую часть. Или я что то упустил?

В данном случае буфер больше 256 не понадобится точно.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

я наверное совсем ничего не понимаю в программировании, может кто подскажет зачем может понадобиться работа с буфером столь неординарным способом?

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

это он пытаеца ардуиной прикинуться Епромом на адресе 080H.

тока не понимает, что ведомому устройству сначала АДРЕС передают откуда читать/записывать, а он его не сохраняет нигде.  Вернее, сохраняет в нигде не описанной переменной с осмысленным названием "b". 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

это он пытаеца ардуиной прикинуться Епромом на адресе 080H.

тока не понимает, что ведомому устройству сначала АДРЕС передают откуда читать/записывать, а он его не сохраняет нигде.  Вернее, сохраняет в нигде не описанной переменной с осмысленным названием "b". 

IIC это жеж аппаратное, видимо надо подключать другую ардуину и на ней по даташиту эмулировать? Правильно???

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

вот это 

Wire.begin(80);

делает Ардуину слэйвом на I2C с адресом 80 или 0x50.  А с другой ардуины, видима, он пытается читать с этого адреса ХЗ как ХЗ что (кода нет) 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

DetSimen пишет:

это он пытаеца ардуиной прикинуться Епромом на адресе 080H.

Исправить:  80 без H

b707
Онлайн
Зарегистрирован: 26.05.2017

grial78 пишет:

Wire.write может отправить только n байт с начала массива.

Кто вам сказал такую чушь про "только с начала". Вы можете передать функции write ссылкуна произвольный элемент массива - и запись начнется с этого элемента.

grial78
Offline
Зарегистрирован: 07.12.2015

DetSimen пишет:

это он пытаеца ардуиной прикинуться Епромом на адресе 080H.

тока не понимает, что ведомому устройству сначала АДРЕС передают откуда читать/записывать, а он его не сохраняет нигде.  Вернее, сохраняет в нигде не описанной переменной с осмысленным названием "b". 

Примерно так. Только запись в епром эмулировать не нужно и запрашивается каждый раз вся память сразу, с нулевого адрес.

grial78
Offline
Зарегистрирован: 07.12.2015

b707 пишет:

grial78 пишет:

Wire.write может отправить только n байт с начала массива.

Кто вам сказал такую чушь про "только с начала". Вы можете передать функции write ссылкуна произвольный элемент массива - и запись начнется с этого элемента.

О как! Спасибо за подсказку, как то я это упустил.