о том, как разделить один внешний последовательный EEprom с помощью двух микроконтроллеров?
развернутый текстУ меня есть датчик Vector nav100 IMU, который отправляет данные последовательно через UART. Я хочу получать данные от него с помощью ATmega32, а затем сохранять данные в AT24c1024 EEprom с использованием I2C, а затем использовать другой ATmega32 для чтения сохраненных данных на AT24c1024 EEprom с использованием I2C для управления серводвигатель.. Итак, EEprom AT24c1024 затем распределяется между двумя микроконтроллерами... я искал в Интернете информацию о том, как разделить один внешний последовательный EEprom, я обнаружил, что ...... (в пути будет для два микроконтроллера, чтобы иметь выходную линию в качестве входа для другого Мастер, который «использует» EEPROM, возможно, вытягивает свой выход на низкий (или высокий - ваш выбор), чтобы сказать: «Я использую его в данный момент». Другой сначала читает свой ввод, прежде чем приблизиться к EEPROM, если он находит линию активной, он отступает, пока она не будет отключена другим мастером. я пробовал это решение, но я потерпел неудачу ... может ли кто-нибудь помочь мне с этим решением? Заранее спасибо...... это мой код
{ // первый микроконтроллер сначала проверяет пин //если высокий, то пишем, затем устанавливаем низкий, чтобы разрешить чтение //второй MCU сначала проверяет пин //если низкий, то пишем, затем устанавливаем высокий, чтобы разрешить запись //для микроконтроллера, который будет писать //сначала он проверит контакт, если он НИЗКИЙ, //затем он может записывать данные в EEprom DDRA=0x00;//настроить порт A как вход if(PINA==0x00)//проверить пин, если LOW,то написать { byte_write (данные); _задержка_мс (10); //После записи установите вывод как высокий, чтобы второй MCU мог читать DDRA=0xff;//настроить порт A как выход PORTA=0xff;//устанавливаем пин как высокий _delay_ms(10);} // для MCU, который будет читать, я установил задержку 10 мс // разрешить первому MCU записать некоторые данные _delay_ms(1000);//задержка от записи данных в EEprom DDRA=0x00;//настроить порт A как вход if(PINA==0x01)//проверить вывод, если ВЫСОКИЙ, то прочитать { у = byte_read (данные); DDRA=0xff;настроить порт A как выход PORTA=0x00;//устанавливаем пин как высокий }
@mohamed, 👍1
Обсуждение1 ответ
Лучший ответ:
Вы не показали нам полный, минимальный, компилируемый пример, поэтому мой ответ будет охватывать только некоторые важные моменты.
Ваш отступ неверен. Важно использовать правильный отступ, так как это помогает структурировать ваш код и позволит вам быстро увидеть неуместные скобки. В среде разработки Arduino для этого даже есть функция автоформатирования.
Вы всегда настраиваете и проверяете весь ПОРТ A, но подключили только один из контактов. Когда вы настраиваете весь порт как вход (без подтягивания), другие контакты будут плавающими. Кроме того, если оба устройства имеют вывод на входе (без подтягивания), этот вывод также будет плавающим. Проверка не может работать таким образом. Вы должны смотреть только на первый бит в регистрах порта, так как это контакт, который вы подключили. Вы можете установить все остальные биты равными нулю при чтении, выполнив побитовую операцию И:
if(PINA & (1<< ;PA0))
. Это будет выполнено, когда первый бит PINA равен 1. Чтобы установить один бит, вы можете использовать побитовое ИЛИ:DDRA |= 1<<PA0;
установит первый бит DDRA. Чтобы удалить только этот бит из регистра, вы можете использоватьDDRA &= ~(1<<PA0);
. При этом остальная часть порта останется нетронутой.Ваш текущий протокол заключается в том, что первый MCU проверяет наличие НИЗКОГО уровня, выполняет передачу, а затем переводит вывод в ВЫСОКИЙ уровень в качестве сигнала для второго MCU, чтобы начать передачу. Второй MCU будет выполнять свои функции I2C, а затем активировать вывод НИЗКИМ. Итак, теперь у нас есть активный НИЗКИЙ и активный ВЫСОКИЙ уровни на одном и том же контакте, что в принципе является коротким замыканием. Довольно большое количество тока будет течь от одного микроконтроллера к другому, что, скорее всего, разрушит как минимум один из контактов (имеется в виду аппаратное обеспечение вывода в микроконтроллере, которое обслуживает этот контакт). Чтобы избежать этого, вы можете использовать принцип, подобный тому, который использует порт I2C: логика Open Drain. Вы можете начать с первого вывода MCU, настроенного как OUTPUT LOW, а другого — как INPUT PULLUP. НИЗКИЙ означает, что первый MCU может работать. Если первый MCU хочет, чтобы второй MCU выполнил передачу, он освободит линию, установив для PIN-кода значение INPUT PULLUP. Второй MCU теперь видит высокий уровень на своем выводе и начинает передачу. По завершении он активирует НИЗКИЙ уровень на линии в течение определенного времени (достаточно для того, чтобы первый микроконтроллер среагировал), а затем снова перейдет в режим INPUT PULLUP. Затем первый MCU увидит НИЗКИЙ уровень на своем выводе как сигнал о том, что второй MCU завершен. Затем он сам переводит линию в НИЗКИЙ уровень. Затем игра начинается снова. Важно то, что ВЫСОКОЕ состояние достигается только подтягиванием, а не активным управлением.
Тем не менее, я по-прежнему не вижу необходимости в совместном использовании внешней EEPROM для этого варианта использования. Вы слишком много думаете о проблеме. Вы написали, что не хотите пропустить кадр, если второй MCU все еще обрабатывает последний кадр. Есть лучшие способы сделать это (особенно если учесть ограниченный срок службы EEPROM).
Вы не сказали нам, почему используете 2 MCU, поэтому, возможно, ваша цель может быть достигнута только с 1 MCU, что полностью избавит от необходимости передачи.
Вы можете использовать другой интерфейс UART через
SoftwareSerial
или родственные библиотеки, чтобы обеспечить прямую связь MCU. «Не пропущенный кадр» будет по-прежнему иметь место, если вы не отключите прерывания. Библиотека будет считывать данные в буфер в прерываниях, пока вы обрабатываете предыдущий кадр. В зависимости от того, сколько данных вы отправляете, вы можете увеличить буфер, но это простое изменение в определениях библиотек.Если вы хотите использовать I2C для связи между обоими MCU, у вас есть 2 способа сделать это. Вы можете либо пойти тем же путем, что описан выше для UART, просто позволив ему заполнить достаточно большой буфер, либо вы можете сделать это через передачи по шине. Первый MCU будет ведущим, который пытается отправить данные второму MCU (подчиненному), когда будут доступны новые данные. Ведомый будет получать данные в обычном режиме. Когда прием кадра завершен, ведомое устройство может покинуть шину до тех пор, пока не будет завершена его обработка. Таким образом, когда мастер попытается отправить больше данных за это время, передача будет неудачной в начале, поскольку на шине нет ведомого с таким адресом (ведомый MCU покинул шину на этот период времени). Вы можете проверить возвращаемое значение
Wire.endTransmission()
, которое будет отражать соответствующий код ошибки. Если возвращается этот код ошибки, мастер должен немного подождать и попытаться отправить этот кадр еще раз, пока он не будет успешно получен. Это также означает, что мастеру нужен достаточно большой буфер для хранения новых данных в ожидании готовности слейва. Или по-другому: Мастер может запросить у ведомого 1 байт, который указывает, готов ли ведомый к новым данным. Если нет, мастер немного подождет и спросит снова. Если да, он передаст данные.
Примечание: В любом случае частота приема и обработки данных должна быть одинаковой для непрерывной работы. Вся цепочка будет такой же быстрой, как и самая медленная часть. Если вы получаете данные быстрее, чем они обрабатываются, буфер будет быстро заполняться, пока вам действительно не придется пропускать кадры. Приведенные выше принципы больше касаются случая, когда обработка и прием могут не совпадать или немного различаться, но в среднем остаются на одной скорости. И для этого вполне достаточно простых коммуникационных буферов, которые используют все коммуникационные библиотеки, с достаточным пространством для передачи от 2 до 4 (в зависимости от варианта).
- Arduino EEPROM сохраняет старые данные после прошивки новой программой
- Не получается читать из / писать в EEPROM
- Serial.println не будет форматировать DEC
- о том, как записать данные во весь EEprom?
- использование EEPROM Arduino
- Скорость последовательной связи (UART) датчика выше, чем скорость обработки микроконтроллера.
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
Интересно, в чем причина EEPROM... из-за временного хранения данных, или в качестве буфера (разница во времени между записывающим mcu и читающим mcu? Или по другим причинам (тоже)? В противном случае удалите EEPROM, и отправьте данные напрямую от одного MCU к другому (например, с помощью UART/SPI/I2C)., @Michel Keijzers
@MichelKeijzers, чтобы предотвратить потерю данных, если придет следующий кадр с датчика, а микроконтроллер все еще обрабатывает последний кадр, поэтому кадр будет удален., @mohamed
Если правильно написать, получение и обработка - это 2 разные вещи. Также библиотека Wire не поддерживает работу с несколькими мастерами. Когда оба контроллера пытаются получить доступ к EEPROM одновременно, шина будет заблокирована., @chrisl
@chrisl Хорошо. это правда .. Итак, я искал это в Интернете и обнаружил, что на пути два микроконтроллера должны иметь выходную линию в качестве входа для другого. Мастер, который «использует» EEPROM, возможно, устанавливает на своем выходе низкий (или высокий — на ваш выбор) уровень, чтобы сказать: «Я использую его в данный момент». Другой сначала читает свой ввод, прежде чем приблизиться к EEPROM, если он находит линию активной, он отступает, пока она не будет отключена другим мастером. Я пробовал это, но мне не удалось ... могу ли я дать мне псевдокод для этого решения?, @mohamed
С чем ты не справился? Вы должны предоставить код, о котором идет речь, чтобы мы могли помочь вам с этим. Хотя я все еще не уверен, что использование внешнего eeprom - хорошая идея., @chrisl
@chrisl Хорошо, я дам вам код ... но есть ли другой способ предотвратить потерю данных?, @mohamed
@chrisl Я подключил первый контакт к порту A в обоих микроконтроллерах. Для микротроллера, который будет читать, я записываю задержку 10 мс для данных, которые будут записаны в EEprom DDRA = 0xff; PORTA=0x00;//на выводе высокий уровень _delay_ms(10);пока(1){ для (целое я = 0; я <10; я ++) { ДДРА=0x00; если(ПИНА==0x01){ y=random_location_byte_read(i,0xA0); _задержка_мс (10); uart_send (у); _задержка_мс (10); ДДРА=0xff; ПОРТ = 0x00;, @mohamed
Пожалуйста, включите весь компилируемый код в вопрос, отредактировав его. Вы можете отформатировать его правильно, выбрав его и нажав кнопку
{}
, @chrisl@chrisl я отредактировал вопрос и отправил код, @mohamed