I2C - Путаница

Я не часто задаю вопросы. Однако этот вопрос меня немного озадачил.
Сценарий:
У меня есть 328PB (внутренний 8 МГц), он говорит с мультиплексором на Wire1 (второй IC2 - Minicore lib PB). Мультиплексор говорит со многими датчиками. Все это работает просто отлично.
У меня есть логический анализатор, подключенный к ключевым точкам, чтобы я мог видеть, что происходит.
У меня есть Nano (внешний 16 МГц), подключенный к проводу (первый I2C PB), он отправляет главный запрос.
PB является ведущим на проводе1 и ведомым на проводе.
По какой-то причине запрос Nano на (адрес 8) подтверждается PB, но затем последующие чтения доставляют нулевой байт и NACK.
Я просто прошу один байт для устранения неполадок. Предыдущие попытки с несколькими байтами давали ожидаемые байты, но все они были равны нулю.
Странная вещь, которую я вижу на логическом анализаторе, заключается в том, что связь PB с мультиплексором кажется медленнее, чем связь Nano с PB (намного медленнее).
Я просмотрел библиотеки, и оба Wire и Wire1, похоже, вычисляют скорость до 100 кГц. Я использую стандартный провод Arduino на Nano. Учитывая, что начальный адрес связи получает ACK. Я в тупике, почему последующее чтение получает ноль и НАК.
Я очень ценю любую помощь в восстановлении моего здравомыслия. Скорее всего, у меня тупой момент. Мои подозрения заключаются в том, что виноваты различия в часах (но по логике вещей этого не должно быть).


Редактировать: Это запись анализатора. Хитрый байт выделен синим цветом.

Связь от Atmega328pb к мультиплексору, а затем к датчику температуры работает нормально. Не все каналы мультиплексора имеют датчики на данный момент, следовательно, гнезда, но вы можете увидеть успех на канале 1 справа от скриншота. Связь Nano с Atmega328pb начинается хорошо, но я ожидаю увидеть 0X41 в синем поле, а не 0x00.

Это закончится чем-то простым, я собираюсь пнуть себя.

Нано-код:

#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(9600);             // start serial для вывода.
}

void loop() {
  Wire.requestFrom(8, 1);         // запросить 1 байт с ведомого устройства #8
  char c = Wire.read();           // получить байт в виде символа
  Serial.print("The character: ");  
  Serial.println(c);              // печать
  delay(1000);
}

Atmega328pb requestEvent код:

void requestEvent() {
  Wire.write("A");
}

Редактировать: Есть и другие провода для программирования и т.д., Но они отсоединяются во время теста. Schematic

Редактировать: Я закомментировал все использование Wire1 в коде PB. И в результате Нано получил свой байт. Я вплел использование Wire1 обратно в код. Вплоть до тех пор, пока он действительно не стал активным, то есть не связался с мультиплексором. В этот момент Нано снова начал получать нулевой байт.

Кажется, это происходит, когда они оба активны. Это говорит о том, что это что-то в библиотеке Wire / Wire1 от Minicore.

Я подозреваю, что в регистрах что-то есть, но сканирование таблицы данных для PB не дает никаких результатов. За исключением этого: 26.1 - Устройство может работать как передатчик или приемник
В документе, который я вижу, нет никаких подробностей.

Я попытался ошеломить коммуникацию так, чтобы ни одна из них не была активна одновременно. Все тот же результат.

Все еще надеясь, что у кого-то здесь есть ответ ;-)

, 👍3

Обсуждение

Можете ли вы нарисовать картинку, показывающую структуру? Я еще не понял, какие платы подключены к какой шине I2C и какую роль играет каждая плата в этих шинах. Также, пожалуйста, покажите нам соответствующий код, @chrisl

крисл - спасибо за ваш ответ, я нарисую несколько диаграмм. Я также опубликую весь код для каждого MCU. Большое спасибо., @Mike Watson

328 - это голая atmega, а не arduino, верно? Вы должны очистить предохранитель тактового деления, в противном случае эффективная частота mcu составляет 1 МГц, а не 8 МГц., @Sim Son

@SimSon - Спасибо за подсказку. У меня был неправильно установлен предохранитель на 328PB. Установите его на 8 МГц, и теперь скорости выглядят лучше. Тем не менее, у меня все еще есть моя проблема., @Mike Watson

Мы сделаем рисунок, который поможет нам лучше понять вашу установку., @Sim Son

@SimSon - Скоро появится один рисунок., @Mike Watson

у меня возникла аналогичная проблема: я не могу работать как master на SDA0 / SCL0 и как slave на SDA1 / SCL1 (и наоборот). Отличается от вашего исправления выше (вызов begin() и end() ) у меня не работает. Если я использую оба интерфейса i2c как ведущий или оба как ведомые, связь работает нормально. Не могли бы вы рассказать о том, как вы настроили свой uC в качестве ведомого и ведущего на двух интерфейсах? Был бы очень признателен!!, @Th3o

@Th3o - (Извините за поздний ответ) Я отказался от библиотеки WIRE для того, что я делал. Просто не удалось заставить ведущего и ведомого работать на одном микроконтроллере с ПРОВОДНОЙ библиотекой. В Amtel studio мне пришлось написать намного больше кода, что заняло намного больше времени, но я получил очень хороший контроль над интерфейсами. Микроконтроллер способен делать это и на бешеных скоростях!, @Mike Watson


2 ответа


1

Я заставил его работать ... вроде того. Мне пришлось переместить некоторые строки из init в цикл. Я обнаружил, что, задерживая связь Wire1 (pb к мультиплексору), я мог бы заставить Wire (Nano к pb) работать. Затем, как только связь Wire1 закончилась, Wire больше не работала. Интересно, что Wire продолжал работать, в то время как Wire1 также был активен. Это привело меня к мысли, что конец связи Wire1 оставляет что-то в конфликтном состоянии (события на Проводе больше не были связаны). Тупой ответ состоял в том, чтобы повторно инициализировать каждый цикл. Это, кажется, работает, но не особенно элегантно.

void loop()
{
    Wire1.begin();
    getTemperatures();
    Wire1.end();
    Wire.begin(8);                                               // Соединение шины i2c 0 с адресом #8
    Wire.onReceive(receiveEvent);                                // Зарегистрировать событие.
    Wire.onRequest(requestEvent);                                // Зарегистрировать событие.
}

Я собираюсь продолжить эту работу и посмотреть, обеспечивает ли она соответствующую степень надежности. Однако я все еще охочусь за корневой проблемой.

,

1

Я перестраиваюсь с помощью Atmel Studio. После долгого времени доведения моих навыков C ++ до нуля мне удалось заставить его работать очень надежно. Мне нравится больший уровень контроля, который он приносит. Я подозреваю, что пытался сделать что-то в Arduino IDE, что невозможно сделать с помощью библиотеки Wire. Мне пришлось эффективно переписать драйвер ведомого устройства Atmel Start, чтобы заставить его вести себя так, как я ожидал. У меня нет другого опыта использования I2C. Поэтому я не могу сказать, отличается ли Atmega328pb от других или нет.
Я собираюсь придерживаться Atmel Studio для этого проекта, спасибо за все ответы.

,