Эмулятор EEPROM по I2C на arduino nano
- Войдите на сайт для отправки комментариев
Пнд, 21/10/2019 - 04:05
Доброго времени суток! Помогите разрешить вопрос. Есть приборчик на 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 байта, то устройство получает их без проблем, но этого не достаточно для нормальной работы- нужно отправить весь массив. Что-то с этим можно сделать?
Но когда я пытаюсь отправить более 32 байт (Wire.write(BB, 255)), на устройство приходит совсем не то, что отправил эмулятор. Если отправить только 32 байта, то устройство получает их без проблем, но этого не достаточно для нормальной работы- нужно отправить весь массив. Что-то с этим можно сделать?
Внутренний буфер I2C - 32 байта, поэтому больше за один раз отправить нельзя.
Можно, конечно, увеличить буфер, но правильнее просто отправлять данные порциями менее 32 байт
Т.е. разбить весь массив на 8 частей и отправлять их подряд? Типа такого Wire.write(BB0, 32); Wire.write(BB1, 32);...
А как можно буфер увеличить? Я так понимаю, нужно лезть в библиотеку Wire, это если первый вариант не получится.
Вариант с разбиением массива почему-то не прошел.
Установил #define TWI_BUFFER_LENGTH 256 - заработало почти как надо. Осталось разобраться с переопределением библиотек, думаю, разберусь здесь сам.
Спасибо за дельную мысль!
Т.е. разбить весь массив на 8 частей и отправлять их подряд? Типа такого Wire.write(BB0, 32); Wire.write(BB1, 32);...
А как можно буфер увеличить? Я так понимаю, нужно лезть в библиотеку Wire, это если первый вариант не получится.
Буфер увеличить не получится. Это аппаратное ограничение. Причём со стороны ОЗУ.
А за что тогда отвечает #define TWI_BUFFER_LENGTH из twi.h?
За то что бы альтернативно гениальные программисты не отправляли больше. Чем вам существующая библиотека мешает работать с этой памятью. В ней авторы решили эту проблему.
Так я выше написал, что не могу отправить больше 32 байт- начинаются глюки. Последовательная отправка по-кускам тоже не спасает- похоже, после первого, остальные просто игнорируются. Альтернативно-гениальное программирование это, конечно, не по-феншую, но в конкретном случае работает :) . Если есть другие, более правильные, решения- с интересом выслушаю.
Так я выше написал, что не могу отправить больше 32 байт- начинаются глюки. Последовательная отправка по-кускам тоже не спасает- похоже, после первого, остальные просто игнорируются.
Потомучто, EEPROM-у надо сначала адрес передать, а потом то, что туда записывается. Ты даташыт на него читал? Или даже в глаза не видел? Методом гадания альтернативно программируешь?
Скачать и установить библиотеку. У микросхемы ОЗУ входной буфер 32 байта. Но первые два байта это адрес куда писать. Потом нужна пауза, так как микросхема пишет из буфера в память. И что бы это узнать надо читать даташит на микросхему. Ну так по феншую что бы карму себе не портить
DetSimen:
Специально для вас повторю вкратце ТЗ: мне нужно эмулировать EEPROM, а не писать на него!
Тада понятно.
DetSimen:
Специально для вас повторю вкратце ТЗ: мне нужно эмулировать EEPROM, а не писать на него!
astwo:
"Холоп" это вы про себя?
Нет, мне не нужен полный аналог. И принимать это "безобразие" у меня никто не будет- пишу для собственных нужд. Отчасти я с вами согласен, что все это извращение, но мне нужно быстрое, дешевое и сердитое решение.
Т.е. разбить весь массив на 8 частей и отправлять их подряд? Типа такого Wire.write(BB0, 32); Wire.write(BB1, 32);...
зачем разбивать на отдельные массивы? - этот массив последовательно и отправляйте.
А способ с увеличением буфера тупиковый. А если завтра понадобится отправить 10 Кб - куда еще буфер увеличивать будете?
Wire.write может отправить только n байт с начала массива. Так что два варианта- или пробегать массив в раздецикле или разделить на части и отправлять оптом каждую часть. Или я что то упустил?
В данном случае буфер больше 256 не понадобится точно.
я наверное совсем ничего не понимаю в программировании, может кто подскажет зачем может понадобиться работа с буфером столь неординарным способом?
это он пытаеца ардуиной прикинуться Епромом на адресе 080H.
тока не понимает, что ведомому устройству сначала АДРЕС передают откуда читать/записывать, а он его не сохраняет нигде. Вернее, сохраняет в нигде не описанной переменной с осмысленным названием "b".
это он пытаеца ардуиной прикинуться Епромом на адресе 080H.
тока не понимает, что ведомому устройству сначала АДРЕС передают откуда читать/записывать, а он его не сохраняет нигде. Вернее, сохраняет в нигде не описанной переменной с осмысленным названием "b".
IIC это жеж аппаратное, видимо надо подключать другую ардуину и на ней по даташиту эмулировать? Правильно???
вот это
Wire.begin(80);
делает Ардуину слэйвом на I2C с адресом 80 или 0x50. А с другой ардуины, видима, он пытается читать с этого адреса ХЗ как ХЗ что (кода нет)
это он пытаеца ардуиной прикинуться Епромом на адресе 080H.
Исправить: 80 без H
Wire.write может отправить только n байт с начала массива.
это он пытаеца ардуиной прикинуться Епромом на адресе 080H.
тока не понимает, что ведомому устройству сначала АДРЕС передают откуда читать/записывать, а он его не сохраняет нигде. Вернее, сохраняет в нигде не описанной переменной с осмысленным названием "b".
Примерно так. Только запись в епром эмулировать не нужно и запрашивается каждый раз вся память сразу, с нулевого адрес.
Wire.write может отправить только n байт с начала массива.
О как! Спасибо за подсказку, как то я это упустил.