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");
}
Редактировать: Есть и другие провода для программирования и т.д., Но они отсоединяются во время теста.
Редактировать: Я закомментировал все использование Wire1 в коде PB. И в результате Нано получил свой байт. Я вплел использование Wire1 обратно в код. Вплоть до тех пор, пока он действительно не стал активным, то есть не связался с мультиплексором. В этот момент Нано снова начал получать нулевой байт.
Кажется, это происходит, когда они оба активны. Это говорит о том, что это что-то в библиотеке Wire / Wire1 от Minicore.
Я подозреваю, что в регистрах что-то есть, но сканирование таблицы данных для PB не дает никаких результатов. За исключением этого:
26.1 - Устройство может работать как передатчик или приемник
В документе, который я вижу, нет никаких подробностей.
Я попытался ошеломить коммуникацию так, чтобы ни одна из них не была активна одновременно. Все тот же результат.
Все еще надеясь, что у кого-то здесь есть ответ ;-)
@Mike Watson, 👍3
Обсуждение2 ответа
Я заставил его работать ... вроде того. Мне пришлось переместить некоторые строки из 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); // Зарегистрировать событие.
}
Я собираюсь продолжить эту работу и посмотреть, обеспечивает ли она соответствующую степень надежности. Однако я все еще охочусь за корневой проблемой.
Я перестраиваюсь с помощью Atmel Studio. После долгого времени доведения моих навыков C ++ до нуля мне удалось заставить его работать очень надежно. Мне нравится больший уровень контроля, который он приносит. Я подозреваю, что пытался сделать что-то в Arduino IDE, что невозможно сделать с помощью библиотеки Wire. Мне пришлось эффективно переписать драйвер ведомого устройства Atmel Start, чтобы заставить его вести себя так, как я ожидал. У меня нет другого опыта использования I2C. Поэтому я не могу сказать, отличается ли Atmega328pb от других или нет.
Я собираюсь придерживаться Atmel Studio для этого проекта, спасибо за все ответы.
- Как перевести Arduino Nano в спящий режим с низким энергопотреблением (<0,05 мА)
- MAX30100 не работает
- Ведомое устройство Arduino с двумя мастерами, использующими одну и ту же шину I2C?
- Библиотека I2C MIFARE RC522
- Не удалось выделить SSD1306 при добавлении константы
- Сброс адреса I2c — MLX90614
- SSD1306 распознается сканером I2C, но не может его отобразить
- Могу ли я соединить вместе несколько плат Arduino Nano ?
Можете ли вы нарисовать картинку, показывающую структуру? Я еще не понял, какие платы подключены к какой шине 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