Работа с i2c и spi на примере часов реального времени pca2129t

Интерфейсная шина IIC (I2C)

Работа с i2c и spi на примере часов реального времени pca2129t

Один из моих самых любимых интерфейсов. Разработан в компании Philips и право на его использование стоит денег, но все на это дружно положили и пользуют в свое удовольствие, называя только по другому.

В Atmel его зовут TWI, но от этого ничего не меняется 🙂 Обычно при разборе IIC во всех книгах ограничиваются примером с EEPROM на этом и ограничиваются. Да еще юзают софтверный Master.

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

Физический уровень.
Данные передаются по двум проводам — провод данных и провод тактов. Есть ведущий(master) и ведомый (slave), такты генерирует master, ведомый лишь поддакивает при приеме байта. Всего на одной двупроводной шине может быть до 127 устройств.

Схема подключения — монтажное И

Передача/Прием сигналов осуществляется прижиманием линии в 0, в единичку устанавливается сама, за счет подтягивающих резисторов. Их ставить обязательно всегда! Стандарт! Резисторы на 10к оптимальны.

Чем больше резистор, тем дольше линия восстанавливается в единицу (идет перезаряд паразитной емкости между проводами) и тем сильней заваливаются фронты импульсов, а значит скорость передачи падает. Именно поэтому у I2C скорость передачи намного ниже чем у SPI.

Обычно IIC работает либо на скорости 10кбит/с — в медленном режиме, либо на 100кбит/с в быстром. Но в реальности можно плавно менять скорость вплоть до нуля.
Ни в коем случае нельзя переключать вывод микроконтроллера в OUT и дергать ногу на +5.

Можно запросто словить КЗ и пожечь либо контроллер либо какой-нибудь девайс на шине. Мало ли кто там линию придавит.

Вся передача данных состоит из Стартовой посылки, битов и стоповой посылки. Порядок изменения уровня на шинах задает тип посылки.

После старта передача одного бита данных идет по тактовому импульсу.

То есть когда линия SCL в нуле master или slave выставляют бит на SDA (прижимают — если 0 или не прижимают — если 1 линию SDA) после чего SCL отпускается и master/slave считывают бит.

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

Правда это не прокатит с железным I2C, там нет таких низких скоростей. Но что нам мешает затактовать микроконтроллер от ОЧЕНЬ медленного тактового генератора и отладить все по шагам? 😉

Повторим для ясности:

  • Начало передачи определяется Start последовательностью — провал SDA при высоком уровне SCL
  • При передаче информации от Master к Slave, ведущий генерирует такты на SCL и выдает биты на SDA. Которые ведомый считывает когда SCL становится 1.
  • При передачи информации от Slave к Master, ведущий генерирует такты на SCL и смотрит что там ведомый творит с линией SDA — считывает данные. А ведомый, когда SCL уходит в 0, выставляет на SDA бит, который мастер считывает когда поднимет SCL обратно.
  • Заканчивается все STOP последовательностью. Когда при высоком уровне на SCL линия SDA переходит с низкого на высокий уровень.

То есть, изменение на шине данных в момент приема данных может быть только при низком уровне на SCL. Когда SCL вверху то идет чтение. Если же у нас SDA меняется при высоком SCL, то это уже служебные команды START или STOP.

Если Slave торомоз и не успевает (у EEPROM, например, низкая скорость записи), то он может насильно положить линию SCL в землю и не давать ведущему генерировать новые такты. Мастер должен это понять и дать слейву прожевать байт.

Так что нельзя тупо генерить такты, при отпускании SCL надо следить за тем, что линия поднялась. Если не поднялась, то надо остановиться и ждать до тех пор, пока Slave ее не отпустит. Потом продолжить с того же места.

Логический уровень
Как передаются отдельные биты понятно, теперь о том что эти биты значат. В отличии от SPI тут умная адресная структура. Данные шлются пакетами, каждый пакет состоит из девяти бит. 8 данных и 1 бит подтверждения/не подтверждения приема.

Первый пакет шлется от ведущего к ведомому это физический адрес устройства и бит направления.

Сам адрес состоит из семи бит (вот почему до 127 устройств на шине), а восьмой бит означает что будет делать Slave на следующем байте — принимать или передавать данные. Девятым битом идет бит подтверждения ACK.

Если Slave услышал свой адрес и считал полностью, то на девятом такте он придавит линию SDA в 0, сгенерировав ACK — то есть Понял! Мастер, заметя это, понимает, что все идет по плану и можно продолжать.

Если Slave не обнаружился, прозевал адрес, неправильно принял байт, сгорел или еще что с ним случилось, то, соответственно, SDA на девятом такте будет прижать некому и ACK не получится. Будет NACK. Мастер с горя хлопнет водки и прекратит свои попытки до лучших времен.

После адресного пакета идут пакеты с данными в ту или другую сторону, в зависимости от бита RW в заголовочном пакете.
Вот, например, Запись. В квадратиках идут номера битов. W=0

Чтение практически также, но тут есть одна тонкость из-за которой я когда то убил кучу времени. При приеме последнего байта надо дать ведомому понять, что в его услугах больше не нуждаемся и отослать NACK на последнем байте. Если отослать ACK то после стопа Master не отпустит линию — такой уж там конечный автомат.

Так что прием двух байтов будет выглядеть так (R=1):
Есть еще одно состояние, как повторный старт.
Это когда мы не обьявляя STOP вкатываем на шину еще один START. После него мы можем обратиться к другому устройству не освобождая шину.

Но чаще идет обращение к тому же самому устройству и это связано с особенностями организации памяти.

Организация памяти.
Это относится уже не столько к самому протоколу I2C, сколько к заморочкам создателей разных EEPROM и прочих I2C устройств.

Но встречается это повсеместно, поэтому я расскажу про этот момент. Но, повторюсь, это не аксиома, не стандарт и вообще зависит от конкретного Slave устройства.

Так что датит в зубы и вкуривать, но обычно так принято.

Итак, о чем речь.
Как видно из протокола, в первом байте мы адресовываем само устройство, а их может быть до 127 штук. Но в самом устройстве вполне может быть очень сложная структура, с кучей ячеек.

Например EEPROM с килобайтами данных внутри. Как обращаться с этими данными? Не считывать же все по очереди от нуля до конца — это долго. Поэтому приняли хитрый формат.

Это не стандарт, но юзается повсеместно.

Поясню на примере:
Есть микросхема часов реального времени PCF8583 (я про нее еще напишу, следите за обновлениями), общающася по протоколу I2C. Внутри нее ячейки памяти, в которых хранятся часы, минуты, секунды, дата, состояние флагов и куча еще всего.

До кучи там еще 240 байт просто так, для свободного пользования. Карта адресов этой микросхемы выглядит так:

И вот надо мне установить дату. Для этого надо мне записать две ячейки памяти с адресами 0х05 и 0x06.

Как это сделать? Из даташита я узнаю, что первый байт данных это адрес куда мы будем обращаться, а потом уже идут данные и со следующим байтом счетчик адреса увеличивается на 1. Там же, в даташите, написано что эти часы откликаются на Slave-адрес 1010000х где х — состояние ноги А0 микросхемы.

Я эту ногу сразу посадил на 0 так что Slave-адрес у меня 10100000. Очевидно, что на одной шине может быть не более двух экземпляров этой микросхемы с адресами 10100000 и 10100001.

Задача решается так:
Вот и славно. Часы установлены и начали тикать. Но вот надо нам считать те же данные, а вдруг изменились?
С записью все понятно — записали вначале адрес, а потом следом записали данные. А умная микросхема все прекрасно поняла и рассовала по ячейкам. А с чтением? А с чтением все через задницу, в смысле через запись.

То есть, мы, вначале, записываем один байт — адрес. Потом делаем повторный старт, затем снова обращаемся к часам по ее Slave-адресу, но уже с битом R, на чтение.

И умная микруха выдает нам байты с адреса который мы в нее вот только что записали. Выглядит это так:
В этих часах так, у других микрух может быть все по другому, но в 99% очень похоже.

Адрес, например, может быть двухбайтным или страницу надо будет указать, но сути это не меняет. Цепочка запись-повстарт-чтение это повсеместно.
Вот так, кстати, выглядит чтение данных из часов PCF8583 на экране моего логического анализатора.

Тут не полная посылка (все 5 байт просто не влезли в экран), но тут четко видно запись начального адреса, потом повторный старт, и чтение из девайса.

Скриншот с осциллографа RIGOL 1042CD

Арбитраж шины I2C.
Почему то все мануалы для начинающих в которых рассматривалась тема протокола IIC как то ссыкливо замалчивают возможность работы двух ведущих на линии. Master-Slave и все тут.

А если у нас демократия? И каждый сам себе Master и сам себе Slave? Согласен, редкий случай, но тем не менее, описывать так описывать. Короче, в случае подобного садо-мазо варианта действует железное правило — кто раньше встал того и тапки. В смысле кто первый начал вещать тот и текущий Master.

Но вот случилось вообще невероятное — два Ведущих начали вещать одновременно. Прям совсем одновременно. Как быть? А тут нам поможет свойство монтажного И — где против лома нуля нет приема. Короче, оба мастера бит за битом играют в простую игру ножик-камень(1 и 0 соответственно). Кто первый выкинет камень против ножика тот и побеждает арбитраж, продолжая вещать дальше.

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

Вроде бы все, практический пример с AVR будет потом, а пока помедитируйте над диаграммой работы конечного автомата TWI передатчика ATmega8. Скоро я вас буду этим грузить!

Страшна? 😉 На самом деле там все не так брутально. Можно обойтись вообще парой десятков строк кода на ассемблере.

UPD:

Источник: http://easyelectronics.ru/interface-bus-iic-i2c.html

Подключение RTC часы реального времени DS1302, DS1307, DS3231 к Arduino

Для подключения RTC часов реального времени DS1302, DS1307, DS3231, была разработана универсальная библиотека.

Скачать библиотеку можно по ссылке : Универсальная библиотека для RTC DS1302, DS1307, DS3231 к Arduino

Подключение:

Подключение DS1307 к Arduino:

RTC DS1307Arduino UNO
GND GND
VCC +5V
SDA A4
SCL A5

Подключение DS1302 к Arduino:

RTC DS1302Arduino UNO
GND GND
VCC +5V
RST 10 (Можно изменить на другие в скетче)
CLK 13 (Можно изменить на другие в скетче)
DAT 12 (Можно изменить на другие в скетче)

Подключение DS3231 к Arduino:

RTC DS3231Arduino UNO
GND GND
VCC +5V
SDA A4
SCL A5

Программа:

В зависимости от того какой модуль Вы подключаете, необходимо в программе указать

Для DS1307:

time.begin(RTC_DS1307);

Для DS1302:

time.begin(RTC_DS1302,10,13,12);

Для DS3231:

time.begin(RTC_DS3231);

Пример установки текущего времени в RTC модуль (DS1307):

#include
iarduino_RTC time(RTC_DS1307);
void setup() { delay(300); Serial.begin(9600); time.begin(); time.settime(0,51,21,27,10,15,2); // 0 сек, 51 мин, 21 час, 27, октября, 2015 года, вторник
}
void loop(){ if(millis()%1000==0){ // если прошла 1 секунда Serial.println(time.gettime(“d-m-Y, H:i:s, D”)); // выводим время delay(1); // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс }
}

Пример считывания текущего времени с RTC модуля (DS1307) и вывод в “Последовательный порт” :

Читайте также:  Часы - календарь

#include
iarduino_RTC time(RTC_DS1307);
void setup() { delay(300); Serial.begin(9600); time.begin();
}
void loop(){ if(millis()%1000==0){ // если прошла 1 секунда Serial.println(time.gettime(“d-m-Y, H:i:s, D”)); // выводим время delay(1); // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс }
}

Преимущества библиотеки:

– библиотека имеет внутренние функции аппаратной обработки протоколов передачи данных I2C и SPI, а следовательно не требует подключения дополнительных библиотек, но и не конфликтует с ними, если таковые всё же подключены.

– библиотека имеет внутренние функции программой обработки протокола передачи данных 3-Wire

– для инициализации модуля необходимо вызвать функцию begin с названием модуля.

– подключение модулей осуществляется к аппаратным выводам arduino используемой шины (за исключением 3-Wire)

– простота установки и чтения времени функциями settime и gettime

функция settime может устанавливать дату и время, как полностью, так и частично (например только минуты, или только день, и т.д.)

функция gettime работает как функция date в php, возвращая строку со временем, но если её вызвать без параметра, то функция ничего не вернёт, а время можно прочитать из переменных в виде чисел.

– библиотека расширяемая, то есть для того, чтоб она работала с новым модулем, нужно указать параметры этого модуля в уже существующих массивах файла RTC.h (тип шины, частота шины в кГц, режимы работы, адреса регистров и т.д.), как всё это сделать, описано в файле extension.txt

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

– при вызове функции begin, библиотека читает флаги регистров модуля и при необходимости устанавливает или сбрасывает их так, чтоб модуль мог работать от аккумуляторной батареи, а на программируемом выводе меандра (если таковой у модуля есть) установилась частота 1Гц, тогда этот вывод можно использовать в качестве внешнего посекундного прерывания.

– при работе с модулем DS1302 не нужны никакие резисторы на выводе GND (которые нужны для его работы с другими библиотеками этого модуля), это достигнуто тем, что для шины 3-Wire указана конкретная частота 10кГц, не зависимо от частоты CPU arduino.

– в библиотеке реализована еще одна не обязательная функция period, принимающая в качестве единственного аргумента – количество минут (от 1 до 255)

если в течении указанного времени была вызвана функция gettime несколько раз, то запрос к модулю по шине будет отправлено только в первый раз, а ответом на все остальные запросы будет сумма времени последнего ответа модуля и времени прошедшего с этого ответа.

Функцию period достаточно вызвать один раз.

Подробное описание:

}// ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ:
//
// Подключение библиотеки:
// #include
// iarduino_RTC time(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]);
// если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC time(RTC_DS3231);
// если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC time(RTC_DS1305,22);
// если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC time(RTC_DS1302, 1, 2, 3); // RST, CLK, DAT
// // Для работы с модулями, в библиотеке реализованы 5 функции:
// инициировать модуль begin();
// указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]);
// получить время gettime(“строка с параметрами”);
// мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень)
// разгрузить шину period (минуты);
// // Функция begin():
// функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д.
// // Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]):
// записывает время в модуль
// год указывается без учёта века, в формате 0-99
// часы указываются в 24-часовом формате, от 0 до 23
// день недели указывается в виде числа от 0-воскресенье до 6-суббота
// если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение
// пример: settime(-1, 10); установит 10 минут, а секунды, часы и дату, оставит без изменений
// пример: settime(0, 5, 13); установит 13 часов, 5 минут, 0 секунд, а дату оставит без изменений
// пример: settime(-1, -1, -1, 1, 10, 15); установит дату 01.10.2015 , а время и день недели оставит без изменений
// // Функция gettime(“строка с параметрами”):
// функция получает и выводит строку заменяя описанные ниже символы на текущее время
// пример: gettime(“d-m-Y, H:i:s, D”); ответит строкой “01-10-2015, 14:00:05, Thu”
// пример: gettime(“s”); ответит строкой “05”
// указанные символы идентичны символам для функции date() в PHP
// s секунды от 00 до 59 (два знака)
// i минуты от 00 до 59 (два знака)
// h часы в 12-часовом формате от 01 до 12 (два знака)
// H часы в 24-часовом формате от 00 до 23 (два знака)
// d день месяца от 01 до 31 (два знака)
// w день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота)
// D день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun)
// m месяц от 01 до 12 (два знака)
// M месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
// Y год от 2000 до 2099 (четыре знака)
// y год от 00 до 99 (два знака)
// a полдень am или pm (два знака, в нижнем регистре)
// A полдень AM или PM (два знака, в верхнем регистре)
// строка не должна превышать 50 символов
// // если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных
// seconds секунды 0-59
// minutes минуты 0-59
// hours часы 1-12
// Hours часы 0-23
// midday полдень 0-1 (0-am, 1-pm)
// day день месяца 1-31
// weekday день недели 0-6 (0-воскресенье, 6-суббота)
// month месяц 1-12
// year год 0-99
// // Функция blinktime(параметр):
// указывает функции gettime мигать одним из параметров времени (заменять параметр пробелами)
// функция может быть полезна, для отображения на дисплее, устанавливаемого параметра времени
// функция получает один параметр в виде числа от 0 до 8
// 0 не мигать
// 1 мигают сек
// 2 мигают мин
// 3 мигают час
// 4 мигают дни
// 5 мигают мес
// 6 мигает год
// 7 мигают дни недели
// 8 мигает полдень
// // Функция period(минуты):
// устанавливает минимальный период обращения к модулю в минутах (от 0 до 255)
// функция может быть полезна, если шина сильно нагружена, на ней имеются несколько устройств
// period(10); период 10 минут, означает что каждые 10 минут к модулю может быть отправлен только 1 запрос на получение времени
// ответом на все остальные запросы будет результат последнего полученного от модуля времени + время прошедшее с этого запроса

Источник: https://lesson.iarduino.ru/page/podklyuchenie-rtc-chasy-realnogo-vremeni-ds1302-ds1307-ds3231-k-arduino

Уменьшаем количество проводов в Arduino — I2C LCD экран и RTC часы по двум проводам

Совсем недавно познакомился с Ардуино, поэтому многим мои примеры покажутся простыми. Однако таким же новичкам, как я, данная информация будет полезна и сэкономит массу времени.

I2C — стандарт общения устройств по 2м проводам, при этом количество устройств, которое висит параллельно на этих проводах может быть очень большим. У каждого устройства есть свой адрес, по которому происходит обращение к устройству.

Адресацию можно менять, если на устройстве есть перемычки, которыми можно установить дополнительное смещение относительно базового адреса, жестко прописанного в устройстве. Это в двух словах. Начал я все с того, что купил 16х2 символьный LCD дисплей на Ибее.

Подключив стандартно — понял что это не то, что нужно. Масса проводов — занимает кучу ножек, хаос и беспорядок.Погуглил, понял что есть дисплеи с интерфейсами, упрощающие подключение. погуглил еще, нашел переходник на I2C для моего LCD. Месяц ожидания, ура-ура, подключил.

Выглядит гораздо интереснее!

Проблема возникла на этапе поиска рабочих библиотек и примеров. Как оказалось потом — в основной наиболее известной библиотеке bitbucket.org/fmalpartida/new-liquidcrystal/downloads — примеры — не рабочие! Это заняло некоторое время и силы=)

Конкретно вот тут лежат рабочие примеры и ссылка на библиотеку. arduino-info.wikispaces.com/LCD-Blue-I2C

Там же можно найти описания различных версий LCD-I2C переходников, которые можно купить.

Я покупал вот такой www.ebay.com/itm/310565362720 собран он на чипе PCF8574

Данная версия библиотеки требует установку параметров дисплея в следующем видеLiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address
где первое число — адрес устройства, остальные — назначают управляющие пины переходника под конкретный дисплей. тут то и была скрыта проблема — многие примеры инициализируют экран неправильными данными — при этом экран моргает, дергается и не работает. Правильная строка, с адресом и нужными пинами — зависит от конкретного дисплея. Новичку понять суть и забить необходимые данные — сложно! Все что выше — рабочий вариант. Он, наверняка, даже лучше той библиотеки, которую я сейчас использую. Но он показался мне чересчур избыточным и громоздким.

Вторая библиотека заработала сразу. arduino-info.wikispaces.com/file/detail/LiquidCrystal_I2C1602V1.zip/341635514

К сожалению, не помню откуда взял демо для данной библиотеки, но в ней используется упрощенная настройка LCD, что мне было и нужно.

LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
В данной строке назначается адрес устройства и определяется тип дисплея, 16 символов в 2 строки.

Первая и вторая библиотеки между собой не совместимы! .

Примеры для одной библиотеки не работают с другой. Нижеследующий код будет относиться к последней указанной библиотеке для работы с I2C LCD.

После подключения экрана, захотелось что-то на него выводить. Просто цифры не интересно. Пусть будут часы=)) Наверное, все проходят этот путь, включая меня. Софтовые часы Ардуины вполне себе позволяют показывать время, но проблема в сбросе данных при отключении.

А так как кнопок у меня нет, устанавливать часы приходится через кабель по COM порту через консоль. Вообщем, надоело мне это очень быстро. Часы реального времени RTC1307 — наверное самая распространенная микросхема для часов.

Плюсов много — отдельная микросхема, независима от основного питания Ардуино при наличии батарейки, не зависима от основной программы — время считает точно! Преимущество часов на базе 1307 — I2С.

При этом никаких дополнительных выходов задействовать не нужно — управляется все по тем же 2м проводам как и LCD.

Библиотека для работы с часами по I2c заработала сразу, примеры рабочие. github.com/adafruit/RTClib

Программа простая, все прозрачно. Цифры создаются функциями, в которых отдельными блоками выводится цифра. Блоки по 5×8 точек задаются в пользовательских символах, максимально их может быть 8. Пример взят с форума arduino.cc. Отрисовка происходит в отдельной функции, цифры выводятся по одной. Бегающие крестики — прихоть автора, т.е. моя)) Смещение цифр контролируется при вызове функции отрисовки.Код для Ардуины

Источник: https://habr.com/post/219137/

Arduino. Контакты и шины — Полезный сайт

Если к вам в руки уже попала Arduino, то Вы, наверняка обращали внимание на большое количество надписанных черных разъемов (далее пинов), расположенных по краям платы. Какой же выход для чего предназначен? Какой компонент куда подключать? Попробуем ответить на этот вопрос.

Сразу оговорюсь, что буду рассматривать самую распространенную плату Arduino Uno. На остальных назначение некоторых выводов может отличаться http://pighixxx.com/test/pinoutspg/boards вот ссылка на ресурс, где можно посмотреть назначение пинов конкретно для Вашей платы. Итак, поехали..

.

Большинство пинов может работать как на вход (считывать данные с подключенных устройств), так и на выход (выдавать сигналы на подключенные устройства). Соответственно, это пины, помеченные как 0-13 и АО-А5. По-умолчанию все пины работают на выход. Чтобы изменить их режим мы можем использовать функцию pinMode.

Пины питания и земля.

Из школьного курса физики Вы должны знать, что, во-первых любая электрическая цепь должна быть замкнута, а во-вторых, постоянный ток течет от “+” к “-“. В данном случае в роли “+” выступают пины “3.3V” и “5V”, которые выдают напряжение соответственно 3.

Читайте также:  Atmel studio

3 и 5 вольт. Сила тока на этих пинах будет не больше 100 мА. В роли “-” выступают пины с обозначением “GND” (земля). На Uno этих пинов 2 (на старых версиях) или 3.

Таким образом, вам надо запомнить, что каждая наша схема должна начинаться с пинов питания и заканчиваться землей.

Пин VIN.

Этот пин служит для подачи питания непосредственно на плату, минуя USB или разъем питания. Зачем? Ну, например, если в вашем проекте используется источник в 4.5 вольт (или батарейный отсек) и вы не хотите использовать громоздкие импульсные адаптеры или USB-разъемы.

Аналоговые пинв А0-А5.

В отличие от цифровых пинов, эти выходы подключены к микроконтроллеру через шестиканальный аналого-цифровой преобразователь (АЦП) и имеют разрешение 10 бит.

Это говорит о том, что при подключении к этим пинам мы будем получать значения от 0 до 1023. Основным применением этих пинам является чтение с аналовых датчиков.

В то же время при нехватке цифровых выходов мы можем использовать аналоговые выходы в качестве цифровых (аналогичным пинам 0-13).

Давайте чуть подробнее рассмотрим функции, закрепленные за цифровыми пинами.

ШИМ или PWM.

Обратили внимание, что пины с номерами 3,5,6,9,10 и 11 на плате помечены знаком “#” или “~”? Это пины, работающие с широтно-импульсной модуляцией. Что же скрывается за этим названием? Все очень просто: цифровой выход Arduino может выдавать или 0 вольт, или 5 вольт. Промежуточные значения, например, в ШИМ.

На рисунке выше мы видим, как получается сигнал: часть времени подается напряжение в 0В, часть 5В, а в среднем мы получаем в 0В, 1.25В, 2.5В, 3.75В и 5В (сверху вниз). Именно благодаря ШИМ мы можем задать значение напряжения от 0 до 5 В с шагом примерно в 0.019В.

Как это сделать видно на том же рисунке: в функцию analogWrite передаются значения от 0 (0 вольт) до 255 (5 вольт). В частности, значение 191 соответствует 3.75В.

I2C.

Контакт А4 и А5 используются для работы с I2C-шины. Что она из себя представляет? грубо говоря, используя 4 провода (питания, земля, линию данных SDA и линию тактирования SCL) мы можем подключить до 112 устройств. Не просто 112 различных устройств, а 112 различных устройств одновременно.

Достигается это благодаря тому, что каждая модель устройства имеет свой уникальный адрес, по которому к нему и осуществляется обращение.

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

Таких устройств, с поддержкой шины I2C множество: “часы” RTC, дисплеи, датчик и многое другое. Более того, написано множество библиотек под такие устройства, позволяющие не указывать напрямую адрес устройства, а обращаться к нему, как самостоятельному датчику.

SPI.

Еще одна последовательная шина. На ней может располагаться одно ведущее устройство (в нашем случае Arduino) и несколько ведомых. Помимо линий питания и земли использует 4 канала:

  1. SCLK (пин 13) – тактовый.
  2. MOSI (пин 11) – данные, передаваемые от ведущего устройства к ведомому.
  3. MISO (пин 12) – наоборот, данные от ведомого к ведущему.
  4. SS (обычно пин 10, но его функцию может выполнять любой цифровой пин) – выбор ведомого устройства, с которым в данный момент будет осуществляться обмен данными. В отличие от остальных линии SS для каждого устройства своя. Например, если мы хотим подключить к Arduino 4 устройства по линии SPI, нам нужно будет задействовать 7 проводов, а для одного – 4 провода.

SPI или I2C?

В чем отличие SPI от I2C и что выбрать? SPI требует больше проводов и поддерживает меньше одновременно подключенных устройств.

Используя SPI, мы можем подключить практически любое устройство, а для использования шины I2C выбор устройств довольно ограничен (хотя весьма велик).

Также скорость передачи по SPI значительно (более чем в 5 раз) выше I2C. Есть ещё рад отличий, выходящих за рамки нашего рассмотрения.

RX/TX.

На UNO это пины 0 и 1 (на большинстве плат они как раз соответствующий помечены). Это линии последовательного порта (также известного как UART). Например, вы можете использовать их для подключения GSM-модема или терминала.

С теорией закончили и в следующей статье мы попробуем сделать простейшую (но просто расширяемую) сетевую метеостанцию, чтобы продемонстрировать возможность Arduino и закрепить вышеизложенное.

автор: ansealk (Пикабу)

Источник: https://MindWork.su/arduino/arduino-kontakti-i-shini/

Работа с I2C и SPI на примере часов реального времени PCA2129T

Работа с I2C и SPI на примере часов реального времени PCA2129T

Все началось с того, что ко мне в руки попала микросхема PCA2129T. После недолговременного “гугления” выяснилось, что это волшебство техники производит NXP Semiconductors аж в Нидерландах.

Хотя это не в особенности любопытно, еще увлекательнее оказался даташит на данную микросхему. Скачивается он с веб-сайта производителя, а если быть четким, то вот тут.

Скачиваем, открываем и начинаем пристально учить, попутно осуществляя с британского языка.

Итак, исследовав первую страничку даташита, выясняем, что PCA2129T обыденные часы реального времени (дальше RTC), со интегрированным кварцем на 32,768 КГц. и температурной компенсацией оного. Да к тому же оптимизирована для высокоточных устройств с низким потреблением. Не считая этого, микросхема может работать на шинах I2C и SPI.

Вот этот момент, естественно не совершенно понятен. Я лично так и не сумел представить для себя устройство в каком требуется подключить RTC конкретно по SPI, потратив на это целых 4 (ну либо 3) вывода микроконтроллера. Разве что у вас уже подключено 157 устройств по I2C (а больше и нельзя), а часов для полного счастья как раз и не хватает.

Ну да хорошо, он никому не мешает. Читаем далее:

Осциллятор с температурной компенсацией и вставленными конденсаторами; Точность хода 3ppm (part per million), температуре от -30 до +80 градусов Цельсия. Т. е. часта кварца может изменяться на 3 миллионных. Даже очень хорошо, я бы даже произнес замечательно.

Обыденные часовые кварцы имеют малое отклонение 5ppm и это у самых-самых, обычно все намного ужаснее и ppm переваливает за 10; Год, месяц, денек, часы, минутки, секунды и подстройка под високосный год (ну этим уже никого не удивишь); Функция штампа времени. Смешная штучка, к примеру не желаем мы, чтоб юзер колупал наше устройство.

Берем и вешаем на крышку микропереключатель. Крышку открыли, контакт замкнулся, и в память микросхемы записалась дата и время. Очень комфортно, в особенности если после вскрытия устройство работать не стала, а юзер клянется, что ничего не трогал.

Или может поставить “штамп” при смене батарейки, чтоб не запамятовать когда поменяли; Снова описание интерфейсов; Запасная батарея. Куда же без нее; Контроль напряжения батареи. А вот это нужная штука, не нужно АЦП МК использовать.

Ударили микросхеме, она все измерила и произнесла нам пора поменять либо нет; Сенсор отключения наружного питания; Сброс при подаче питания; Сенсор остановки осциллятора; Выход прерываний. На него можно вывести ежесекундное/минутное прерывание, прерывание сторожевого таймера и прерывания от будильника; Программируемый выход.

На этом способности исчерпаны, да и того, что есть, больше чем довольно. Дальше можно узреть предназначение выводов микросхемы.

Здесь все очень просто: питание (Vss, Vdd), интерфейсы (SDA/CE, SDO, SDI, SCL), переключение интерфейсов (IFS) резервная батарея (вход Vbat и выход BBS), вывод прерываний (INT), вход для “штампа” даты (TS), программируемый выход (CLKOUT) и еще 4 вывода для которых производители не выдумали никаких функций.

Сейчас самое увлекательное — описание адресов регистров памяти и хранящихся в их данных. В самом начале памяти хранятся данные контрольных регистров, т. е. опции микросхемы. Далее идет время и дата. Все, что связано с временем и датой хранится хитрецким образом.

За 10-ки чисел отвечают одни биты 8-миюитного числа в памяти, а за единицы – другие. Это именуется BCD — двоично-десятичный код. Потому при чтении и записи этих данных следует позаботиться об их преобразовании.

Далее хранится время будильника (тоже в BCD), опции температурной компенсации и программируемого выхода. Последующие две ячейки памяти занимают опции сторожевого таймера, сходу за ними идут регистры “штампа” времени.

И заканчивается все это дело опциями точности хода, значение варьируется от -7 до +8 сек. Да, еще есть два регистра, которые можно использовать для хранения собственных данных. В общем, не так и много различий от DS1307.

Ну вот, с регистрами памяти разобрались, сейчас можно попробовать запустить это волшебство техники. Паяем микросхему вот на такую плату (ну либо на всякую другую):

А сверху наклеиваем бумажку с заглавием выводов разъема:

Размеры, естественно, огромные по сопоставлению с той же DS3107. Зато производитель обещает высшую точность хода, плюс не нужно находить высокоточный кварц. И из наружных компонент только 3 резистора, ну и пара конденсаторов по питанию. Кстати о питании. Малое напряжение всего 1,8В.

, а очень 6,5В. хотя производитель советует не превосходить 4,2В. Да, спалить ее довольно тяжело. Один раз спутал провода питания и подал питание напротив. Нашел это, когда что-то задымило. Микросхема раскалилась, но выжила.

После остывания и правильной подачи питания заработала, как ни в чем же не бывало.

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

Он, естественно, не имеет таких широких способностей, как аппаратный, но для работы с таковой примитивной микросхемой его полностью хватит. Для написания библиотеки программного I2C нам будет нужно описание его механизмов работы.

Сложного ничего нет, открываем спецификацию протокола и читаем. В общем виде работа I2C смотрится последующим образом:

Начало передачи определяется Start последовательностью — переход линии SDA На маленький уровень при высочайшем уровне SCL; При передаче инфы от Master к Slave, ведущий генерирует такты на SCL и выдает биты на SDA.

Которые ведомый считывает когда SCL Становится 1. При передачи инфы от Slave к Master, ведущий генерирует такты на SCL и считывает данные с полосы SDA.

А ведомый смотрит за состоянием SCL И после того, как SCL уходит в 0, посылает на SDA бит, который мастер считывает, после того как ит SCL в высочайший уровень. Завершается все STOP последовательностью.

Когда при высочайшем уровне на SCL линия SDA Перебегает из низкого в высочайший уровень.

Ну вот, вроде все очень просто. Да, AVR МК содержат аппаратный I2C, который производители обругали TWI. Вообщем очень комфортная штука, не нужно мыслить о том, как идет передача, все разруливается аппаратно. К тому же целую кучу ошибок может выслеживать. Для полного счастья к нему приделали прерывания. Т. е.

подключили, настроили МК и все работает. Но все есть же один небольшой минус – жесткая привязка к определенным выводам МК. И вот бы весь порт под какую-нибудь периферию использовать, к примеру как здесь http://cxem. net/mc/mc187.php (очень комфортно было все лампы подключить на один порт), а там I2C.

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

Тем паче, если устройство всего одно, к тому же установлено на плате вкупе с МК, то выслеживать ошибки нам не очень то и необходимо. Устройство ведь без нашего ведома никуда убежать не может. Ага, означает все полностью реализуемо. Берем и пишем библиотеку.

Весь код я в статье приводить не буду, а то она получится очень длинноватой, обрисую только главные функции. Все другое будет в исходниках, которые я снабдил комментами. Итак, вот функции:

i2c_init() – настройка портов МК и установка обеих шин в состояние 1. i2c_start() – отправка СТАРТ последовательности. i2c_stop() – отправка СТОП последовательности. i2c_write() – отправка данных. i2c_read() – прием данных.

Читайте также:  Как подключить к устройству нагрузку?

Ну вот и все, сейчас пишем библиотеку для самой PCA2129. Поначалу заглянем в даташит, в раздел Interfaces и найдем там диаграммы записи и чтения. Вот эти:

Для записи (верхняя диаграмма) все просто, оправляем адресок устройства + бит чтения/записи (0), адресок ячейки памяти и данные. Ну и не забываем про СТАРТ и СТОП. Для чтения (нижняя диаграмма) все незначительно труднее. Поначалу отправляем адресок устройства + бит чтения/записи (0) и адресок ячейки памяти.

После чего отправляем СТОП и опять СТАРТ. А сейчас отправляем адресок устройства + бит чтения/записи (1) и начинаем читать данные. Т. е. все что от нас требуется – это отправлять адреса соответственных ячеек памяти и читать/писать данные. Означает, мы можем просто и непосредственно написать библиотеку для PCA2129.

Вышло вот так (код как обычно в прикрепленных исходниках):

pca2129_init()– инициализация pca2129_set_time() – установка времени pca2129_get_time() – чтение времени pca2129_set_date() – установка даты pca2129_get_date() – чтение даты pca2129_set_alarm() – установка будильника pca2129_get_alarm() – чтение состояния будильника low_bat() – чтение состояния батареи WDT() – настройка сторожевого таймера

Ну вот, фактически, и все. Подключаем PCA2129 к отладочной плате (на ней стоит ATmega16).

Включаем и… Ура, заработало!

А ведь и правда, работает. И время, и дата, даже будильник и определения заряда батареи. Функцию “штампа” времени я не писал, но если пригодится, дописать не неувязка.

Итак, с I2C все понятно. Перемещаемся на SPI. Он тоже есть в программной реализации. Как раз те же выводы, к которым подсоединяется программатор: MOSI, MISO, SCK. Ничем особым эта шина не отличается. По SCK шлем тактовые импульсы, а по MOSI и MISO идет обмен данными (MOSI – выход, MISO – вход).

Да, еще нужна линия CE (chip enable), конкретно она гласит устройству на полосы о начале обмена данными. МК опускает линию в 0 и начинает обмен. Да, у каждого устройства на шине своя линия CE. Обмен данными по SPI происходит еще проще, чем по I2C. Да, она к тому же более высокоскоростная, до 6,5 Мбит/с. Полностью можно подключать высокопроизводительный АЦП либо ЦАП.

Мы же будем подключать часы. Обмен данными смотрится последующим образом:

Как видно из диаграмм, все тривиально. На самом деле это обыденный сдвиговый регистр. При записи употребляется только вывод MOSI МК, при чтении добавляется вывод MISO.

При этом запись и чтение данных идут при противоположенных состояниях полосы SCK. Как конкретно — зависит от режима работы SPI, а их целых 4.

Описание всех режимов есть в соответственной документации, потому тут я их приводить не буду. Тем паче обычно употребляется режим 0.

Для SPI я написал библиотеку для программной и аппаратной реализации. При программной реализации можно избрать хоть какой порт МК, также вынести линию MISO на хоть какой порт, не зависимо от других выводов. Не считая этого можно соединить выводы MOSI и MISO, сэкономив один вывод МК. В аппаратной реализации все стандартно, подключаемся к определенным выводам МК и работаем.

Зато можно избрать 4 режима работы, скорость передачи данных, использовать прерывания и использовать режим Slave (к примеру, для связи 2-ух МК). Да, PCA2129 не производит синхронную передачу данных, потому и в библиотеке программной реализации ее нет. Но если пригодится, можно без заморочек ее добавить. В обеих библиотеках функции именуются идиентично и имеют однообразные характеристики.

Смотрятся они вот так:

spi_init()– инициализация SPI; spi_write() – передача данных; spi_read() – чтение данных;

Осталось только малость поменять библиотеку для работы с PCA2129 (ту, что написали для работы по I2C). Что мы и делаем. Сейчас подключаем плату с микросхемой к отладочной плате по SPI (не запамятывая переставить джампер SPI/I2C и снять джампер I/S).

Подаем питание, и… Опять работает! Только проводов стало больше.

А вот и видео работы:

Итак, подведем итоги. PCA2129T оказалась хорошей микросхемой часов реального времени.

Из плюсов необходимо отметить высшую точность хода, которая еще выше, чем можно получить при использовании наружного кварца), температурная компенсация (она и дает такую точность), отслеживание уровня заряда запасной батареи, “штамп” времени, сторожевой таймер и вывод прерываний.

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

Прикрепленные файлы: PCA2129T. rar (5 Кб) PCA2129T_Plata. rar (6 Кб)
SPI I2C RTC AVR Sprint-Layout Eclipse

Источник: http://bloggoda.ru/2017/11/16/rabota-s-i2c-i-spi-na-primere-chasov-realnogo-vremeni-pca2129t/

Мониторинг шины I2C

Электронщики в своей работе часто встречаются с шиной I2C. Как правило, на этой шине висят разные заводские микросхемки: датчики, память, раширители портов ввода-вывода, часы реального времени и так далее. Обмен по шине минимален и, в общем-то, достаточен, если говорить о взаимодействии в рамках одной платы или одного небольшого устройства.

Скорость передачи – порядка 100 кбод, на шине может быть несколько мастеров, да и протокол сводится, как правило, к обращению к регистрам устройства. Большинство поставляемых сейчас микроконтроллеров уже имеют на борту модуль обмена по I2C, причём могут быть и мастером шины, и слейвом. Поэтому в некоторых случаях есть смысл использовать I2C для обмена между “своими” устройствами.

В обоих случаях возникает проблема отслеживания линии во время отладки. Дело в том, что при работе, например, с UART, можно взять один из сотен существующих в продаже переходников, подключить его к COM или USB порту и воспользоваться одним из десятков программ-терминалов (например, minicom, hyperterminal, cutecom). А вот с I2C всё не так уж очевидно.

В этой статье попробую рассмотреть несколько найденных вариантов комплексов для анализа шины I2C.Заголовок вышел не совсем корректный, так как я расскажу и о решениях, подключающихся к компьютеру через USB. Дело в том, что все эти решения в конечном итоге прикидываются в операционной системе последовательным портом, после чего передают данные об обменах прямо в терминал.

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

Примеры таких проектов:  Плюсы такого подхода:

  • простота исполнения: аппаратно такие адаптеры устроены несложно, при должной сноровке легко повторяются в домашних условиях;
  • нет необходимости в приобретении специфического ПО, достаточно иметь простой терминал последовательного порта;
  • несложно использовать подобные адаптеры при написании скриптов для взаимодействия ПК со схемой.

Однако, очевидны минусы:

  • нет возможности вменяемо оценить загрузку линии;
  • нет возможности фильтровать посылки (что особенно необходимо при большой загрузке линии);
  • ограниченные возможности визуализации и анализа получаемых данных; 
  • нет чёткого стандарта вывода сообщений такими устройствами: каждый любитель, как правило, по-своему отображает события на шине (начало посылки, адрес получателя, “повторный старт” и так далее).

В целом, такие решения неплохо подходят для анализа событий на шине, к которой подключено небольшое количество устройств, редко обменивающихся сообщениями. Они дешевы и при необходимости легко повторимы радиолюбителями. Но их область применения, в сущности, ограничивается несложными любительскими устройствами. Далее рассмотрим более профессиональные программно-аппаратные комплексы для анализа шины I2C.

Программное обеспечение Total Phase Data Center для работы с Beagle Protocol Analyzer

Beagle Protocol Analyzer – устройство, разработанное компанией Total Phase для захвата и анализа данных, передаваемых по шинам SPI и I2C. Подключается к компьютеру через USB, требует для работы специальный драйвер и ПО Data Center.

Анализатор способен считывать данные с линии I2C при частоте шины до 4 МГц, работает только в режиме чтения данных.

Total Phase Data Center – ПО, написанное для работы с серией анализаторов аппаратных интерфейсов (SPI, I2C, USB, CAN), разработанных компанией Total Phase. Для этой серии анализаторов также официально распространяется API для написания собственных программ.

Считанные данные отображаются в окне несколькими способами: в сыром виде (raw) и в виде списка транзакций (сохраняющим, в том числе, время начала передачи). Умеет сохранять записи транзакций, а также экспортировать полученные данные в виде CSV для последующей обработки любым удобным способом, в том числе в математических средах (таких как Matlab) или электронных таблицах.

Данный комплекс предлагает довольно неплохие возможности по сбору данных о работе шины, не вмешиваясь при этом в его работу. Проприетарное ПО распространяется бесплатно (требуется регистрация на сайте Total Phase), доступно для Windows, Mac и Linux в виде 32- и 64-битных бинарников. Cтоимость самого адаптера – $330.

Для активного вмешательства в работу шины можно использовать другой проект этой же компании – Aardwark I2C/SPI Host Adapter

ПО Total Phase Control Center

Ещё один проект представленной выше компании Total Phase, разработанный для активной работы с шинами I2C и SPI.

ПО Control Center предлагает пользователю сконфигурировать адаптер в качестве master или slave, позволяет отправлять сообщения вручную, либо писать несложные batch-скрипты на XML для автоматизации работы с шиной, а также ведёт лог транзакций.

Адаптер подключается к компьютеру по USB, предлагает выбор напряжения логических уровней и питания целевого устройства.

Как и в случае с Data Center, ПО доступно для всех основных платформ и распространяется бесплатно. Стоимость адаптера Aardwark Host Adapter – $275.Bus Pirate – один из самых дешёвых доступных на рынке логических анализаторов, разработанный Ian Lesnet из Dangerous Prototypes.

Является open-source проектом: исходные коды прошивки и разводка печатной платы находятся в свободном доступе. Выпуск этих анализаторов развёрнут компанией Sparkfun.

BusPirate может выступать как обычный логический анализатор, а также имеет встроенную поддержку множества протоколов и интерфейсов, в том числе I2C, SPI, Dallas 1-Wire и HD44780 LCD. Способен выступать в роли пассивного анализатора, а также подключаться к шинам и работать в качестве master или slave.

Общение с ПК происходит через USB-порт, устройство распознаётся как последовательный порт, через который идёт взаимодействие с прошивкой. Доступен интерфейс командной строки, что позволяет использовать устройство без графического интерфейса, а также упрощает написание скриптов.

Для эффективной работы с анализатором используется открытое ПО LogicSniffer. Написанное на языке Java, оно доступно практически для всех платформ.

ПО LogicSniffer в режиме логического анализатора/осциллографа

Данный программно-аппаратный комплекс идеально подходит для многих задач анализа цифровых схем в любительской лаборатории. Идеальным его делает и стоимость самого анализатора – $30.

Однако, существующее ПО ориентировано на анализ физического уровня интерфейсов (с расшифровкой кодов), не предлагая возможностей анализа передаваемых данных. Открытость проекта BusPirate, тем не менее, даёт возможность написать ПО, ориентированное непосредственно на анализ посылок.

ПО BitScope Logic Protocol Analyzer

BitScope – компания, занимающаяся разработкой профессиональных цифровых осциллографов и анализаторов для подключения к ПК.

Для работы с этими устройствами компания разработала целую серию программ, нацеленных на различные задачи анализа сигналов, в том числе на расшифровку и анализ данных, передаваемых по стандартным интерфейсам.

ПО BitScope Logic – логический анализатор с возможностью расшифровки сообщений, передаваемых по протоколам UART, I2C, SPI, CAN и многим другим. Распространяется бесплатно, используется с аппаратным обеспечением BitLogic. Однако, как в случае с LogicSniffer, его возможности ограничены анализом физического уровня. ПО доступно для Windows, Mac OS и Linux.

Стоимость логических анализаторов BitLogic начинается от $150.

Мы рассмотрели лишь несколько решений для анализа передаваемых по шине I2C данных.

Как правило, такие решения нацелены на анализ проблем на физическом уровне, что обусловлено частым использованием I2C с несложными устройствами, работающими по несложным протоколам, где все передачи сводятся к чтению/записи значений регистров. Тем не менее, существуют решения, нацеленные на работу именно с передаваемыми данными.

Беглый обзор существующих решений показывает, что не так просто найти качественное ПО, способное на анализ как физического уровня передающей среды, так и на анализ данных.

Источник: http://ru-webconn.blogspot.com/2015/10/i2c.html

Ссылка на основную публикацию
Adblock
detector