1 wire шина с датчиками

Протокол 1-Wire

1-Wire – протокол передачи данных в обе стороны по одному проводу.

Режим связи в этом протоколе – асинхронный и полудуплексный (об этом подробнее тут), а также «остроконечный» (при отсылке многобайтовых целых передача идёт от младшего байта к старшему).

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

Ещё раз подчеркнём – на шине может быть только ОДИН ведущий – иначе возникнут конфликты, когда оба ведущих будут тянуть одеяло на себя (на самом деле, есть некоторые приёмы организации сетей 1-Wire в режиме мультимастера – например, с помощью ветвителя сети DS2409 – но в «обычной» жизни все-таки предпочтительней иметь только одного ведущего на шине).

Протокол 1-Wire хорош тем, что не сложен в реализации и требует для связи всего два-три провода (шина данных, земля и при необходимости питание); однако при этом он не лишён и недостатков – этот протокол весьма чувствителен ко времени и к помехам. Также 1-Wire не предназначена для передачи больших объёмов информации и для скоростного обмена данными – максимальная скорость 9600 Бод/с.

Протокол 1-Wire описывает физический, канальный, сетевой и транспортный уровни взаимодействия (см. модель OSI).
На физическом уровне даются описания способов подключения, требования к шине данных и питанию и т.д.
Канальный уровень описывает способы чтения и передачи битов по протоколу.
Сетевой уровень описывает способы адресации к различным устройствам на линии.
Наконец, транспортный уровень описывает функциональные команды, используемые устройствами 1-Wire.

Физический уровень протокола

Физически для организации интерфейса необходимы как минимум линия для данных и «земля»; достаточно часто также для подключения устройств необходима также линия питания, однако некоторые ведомые устройства могут питаться и паразитно – получать «подпитку» через шину данных.

Рисунок 1. Пример подключения ведущего и ведомых устройств по протоколу 1-Wire.

Упрощенный пример подключения шины представлен на рисунке 1: так, у нас есть ведущее устройство и три ведомых, Slave1, Slave2 и Slave3. Шина данных (data) подтянута резистором к питанию и к ней присоединены все четыре устройства; также каждое из устройств подсоединено к земле. Master, Slave2 и Slave3 подключены к питанию (от 3 до 5 В, в зависимости от требований устройств), а устройство Slave1 питается паразитно через шину данных (об этом подробнее ниже).

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

Канальный уровень протокола

Обмен информацией ведётся так называемыми временными, или тайм-слотами (60 мкс): один тайм-слот служит для обмена одним битом информации. Данные передаются бит за битом, начиная с младшего бита младшего байта – это, кстати, достаточно часто приводит к ошибкам у новичков – кажется, что нужно передавать данные слева направо, так, как они хранятся в памяти (то есть, следите за словами: кажется, что нужно начинать со старшего бита младшего байта (вы уже запутались, да?) – но нет! При передаче по 1-Wire, например, двухбайтового числа порядок передачи будет таким:
Имеем число 1023410 – в двоичном виде выглядит так: 00100111 111110102
В памяти (так как у нас «остроконечный» порядок хранения данных) выглядит так: 11111010 00100111.
А передача по 1-Wire будет выглядеть так:
0→1→0→1→1→1→1→1→1→1→1→0→0→1→0→0
Если вы запутались так же, как и я – самое время выпить чая с шоколадкой и немного утрясти все в голове.

Идём дальше. При обмене информацией ведущий инициирует каждую связь на битном уровне. Это означает, что передача каждого бита, независимо от направления (передача или приём), должна быть инициирована ведущим. Шина данных по умолчанию подтягивается к «единице», поэтому для начала как приёма, так и для передачи ведущий опускает линию в «ноль» на некоторое время.

Рассмотрим 5 основных команд для связи по шине 1-Wire: «Запись 1», «Запись 0», «Чтение», «Сброс» и «Присутствие». При этом на рисунках красным выделено управление линией от ведущего, синим – управление линией от ведомого, черным – освобожденная линия (с помощью подтяжки шина автоматически переходит в «единицу»).

Сигнал «Запись 1». Ведущий устанавливает низкий уровень в течение 1…15 мкс. После этого, в течение оставшейся части временного слота он освобождает шину.

Сигнал «Запись 0». Ведущий формирует низкий уровень в течение не менее 60 мкс, но не дольше 120 мкс.

Сигнал «Чтение». Ведущий устанавливает низкий уровень в течение 1…15 мкс. После этого подчинённый, если хочет передать 0, удерживает шину в низком состоянии до 60 мкс; если же подчинённых хочет передать 1, то он просто освобождает линию. Ведущий обычно сканирует состояние шины по истечении 15 мкс после установки низкого уровня на шине.

Так, ведомый удерживает линию к земле, если хочет передать «0», и просто отпускает линию, если хочет передать «1».
Таким образом при чтении получаем следующие диаграммы.

Сигнал «Чтение при получении 1»:

Сигнал «Чтение при получении 0»:

Основные проблемы, которые возникают при реализации чтения-записи – это проблемы со временем, то есть «невыдерживание», или наоборот, «передерживание» временных задержек при чтении линии. Возникают эти проблемы из-за того, что часто не делают поправку на медленность языков программирования высокого уровня. Особенно это касается различных «дополнительных» функций и ништяков. Подробнее тут

Сигнал «Сброс/присутствие». Здесь временные интервалы импульсов отличаются. Ведущий устанавливает низкий уровень в течение 8 временных слотов (480 мкс), а затем освобождает шину. Данный длительный период низкого состояния называется сигнал «Сброс».
Если на шине присутствует подчинённый, то он должен в течение 60 мкс после освобождения ведущим шины установить низкий уровень длительностью не менее 60 мкс. Данный отклик носит название «Присутствие». Если такой сигнал не обнаруживается, то ведущий должен полагать, что нет подключённых устройств к шине и дальнейшая связь невозможна.
Данная связка сигналов всегда начинает любой обмен информацией между устройствами.
Помимо этого, нужно учитывать, что любое ведомое устройство после получения питания сразу же выдаёт сигнал присутствия.
Сигнал же «Сброс» позволяет ведущему досрочно завершить обмен информацией – например, если датчик температуры передаёт нам всю свою память, а нам нужны только первые два байта, которые содержат значение температуры, то после получения этих двух байт микросхема просто может опустить линию в ноль на нужное количество времени – датчик поймет, что больше ничего пересылать не нужно.

Читайте также:  Замена масла в акпп в волгограде цена

Сетевой и транспортный уровни протокола

Рассмотрим «более высокий» уровень протокола 1-Wire – последовательность действий при взаимодействии ведущего и ведомого, а также основные команды. При этом нужно отметить, все данные, в том числе команды, отсылаются побитно последовательно, начиная с младшего бита.

Так, например, если у нас есть микроконтроллер и DS18S20 – датчик температуры, и мы хотим получить от этого датчика значение температуры, то алгоритм работы будет следующим:

При этом нужно помнить, что ведомые устройства могут поломаться и, например, опускать линию всегда на 0. Допустим, у нас так закоротило датчик температуры в термостате печки. Тогда, если ведущий не проверит, что линия возвращается в единицу, то вероятна следующая ситуация:

Выглядит все это довольно печально – и черевато большими проблемами! Так что на протокол полагайся, но сам не плошай.

Вернёмся к алгоритму взаимодействия ведущего и ведомого по протоколу. Как видно, реализовать работу ведущего устройства не так уж сложно – при этом есть как уже готовые библиотеки с кодом, так и аппаратные реализации – например, от той же фирмы Maxim Integrated. Так, например, для AVR-ок написан целый даташит для реализации 1-Wire.

А вот реализовать ведомое устройство не так уж просто – и если библиотеки существуют (например, у нас на сайте), то аппаратных реализаций именно протокола 1-Wire мне не встречалось. Принцип же работы ведомых устройств подробно описан в их документации, обычно в виде блок-схемы.

Паразитное питание

Протокол 1-Wire позволяет ведомым устройствам при необходимости использовать паразитное питание – так, например, если уже есть линия с двумя проводами, или же необходимо удалённое измерение, или, например, в случае системы аутентификации, ведомое устройство (ключ или карточка) не подразумевает подключение питания.

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

Например, для датчика температуры DS18S20, использующего протокол 1-Wire, необходимо гарантировать, что на шине данных будет достаточное напряжение при выполнении температурного преобразования или при копировании данных из памяти EEPROM. Согласно даташиту, при этом рекомендуется подтягивать линию данных к питанию с помощью полевого транзистора; на деле же при использовании напряжения +5-+5.5 В микроконтроллеру достаточно просто не опускать шину данных в ноль (в случае именно с датчиком DS18S20 – другие датчики могут потреблять больше тока). Также именно паразитное питание является одной из причин, почему микроконтроллеру стоит передавать сигналы (то есть опускать линию данных в ноль) по минимальному времени – это позволяет устройствам на паразитном питании нормально функционировать.

К слову, не все авторы библиотек заморачиваются данным вопросом – так, при попытке заставить работать датчик DS18S20 на паразитном питании в среде MikroElectronika с использованием библиотеки этой среды датчик просто не получал достаточного питания и не мог нормально «общаться».

Области применения

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

Уникальные коды устройств 1-Wire

Пару слов об уникальных кодах устройств, с которыми и работают ROM-команды. Каждое «одноварное» устройство имеет свой 64-хбитный код, состоящий из трёх частей:

Младший байт – это код семейства, к которому относится устройство, 6 следующих байт – уникальный в семействе серийный номер, ну и наконец, старший байт – это CRC, который служит для проверки правильности приёма всего кода. Так, например, на родных даллосовских (сейчас максимовских) «таблетках» часть уникального кода – а именно, 48-битный серийный номер – пишется на металле в шестнадцатиричном виде (все дружно посмотрели на свои домофонные ключи).

Рассмотрим подробнее, какие коды семейств устройств 1-Wire бывают:

Код семейства (HEX) Устройство iButton Описание
01 DS1990A, DS1990R, DS2401, DS2411 Уникальный серийный номер-ключ
02 DS1991 Мультиключ, 1152-битная защищённая EEPROM
04 DS1994, DS2404 4 КБ NV RAM + часы, таймер и будильник
05 DS2405 Одиночный адресуемый ключ
06 DS1993 4 КБ NV RAM
08 DS1992 1 КБ NV RAM
09 DS1982, DS2502 1 КБ PROM
0A DS1995 16 КБ NV RAM
0B DS1985, DS2505 16 КБ EEPROM
0C DS1996 64 КБ NV RAM
0F DS1986, DS2506 64 КБ EEPROM
10 DS1920, DS1820, DS18S20, DS18B20 Датчик температуры
12 DS2406, DS2407 1 КБ EEPROM + двухканальный адресуемый ключ
14 DS1971, DS2430A 256 бит EEPROM и 64 бита PROM
1A DS1963L 4 КБ NV RAM + счётчик циклов записи
1C DS28E04-100 4 КБ EEPROM + двухканальный адресуемый ключ
1D DS2423 4 КБ NV RAM + внешний счётчик
1F DS2409 Двухканальный адресуемый ключ с возможностью коммутации на возвратную шину
20 DS2450 Четырёхканальный АЦП
21 DS1921G, DS1921H, DS1921Z Термохронный датчик с функцией сбора данных
23 DS1973, DS2433 4 КБ EEPROM
24 DS1904, DS2415 Часы реального времени
26 DS2438 Датчик температуры, АЦП
27 DS2417 Часы реального времени с прерыванием
29 DS2408 Двунаправленный 8-разрядный порт ввода/вывода
2C DS2890 Одноканальный цифровой потенциометр
2D DS1972, DS2431 1 КБ EEPROM
30 DS2760 Датчик температуры, датчик тока, АЦП
37 DS1977 32 КБ защищённой паролем EEPROM
3A DS2413 Двухканальный адресуемый коммутатор
41 DS1922L, DS1922T, DS1923, DS2422 Термохронные и гигрохронные датчики высокого разрешения с функцией сбора данных
42 DS28EA00 Цифровой термометр с программируемым разрешением, возможностью работать в режиме подключения к последовательному каналу и программируемыми портами ввода/вывода
43 DS28EC20 20 КБ EEPROM

NV RAM – Non-Volatile Random-Access Memory (энергонезависимое ОЗУ)
PROM – Programmable Read-Only Memory (однократно программируемое ПЗУ)
EEPROM – Electrically Erasable Programmable Random-Access Memory (электрически стираемое перепрограммируемое ПЗУ)

Про команду Search ROM (F0h):

По мотивам статьи Чернова Геннадия.
Если ведущий не знает серийный номер устройств, подключенных к шине, то существует возможность идентифицировать коды ROM каждого устройства – для этого необходимо использовать команду «Search ROM» [F0h]. Эта команда действует как команда «Read ROM», объединенная с командой «Match ROM».

Процесс идентификации кодов ROM ведомых устройств выглядит так:

После формирования мастером команды «Search ROM» все устройства посылают на шину значение своего младшего бита; при этом сначала в течение одного такта ведомыми посылается «прямое» значение бита, а в течение следующего такта – «обратное» (логическое НЕ, дополнение) значение этого же бита.
Тогда мастер может считать следующие последовательности:

Далее мастер в следующем временном слоте отсылает «0» или «1», таким образом определяя, с какими устройствами дальше будет общаться – все устройства, у которых младший бит не соответствует биту, сформированному мастером на этом этапе, перейдут в состояние ожидания и будут находиться в нём, пока не получат импульс сброса. Затем происходят аналогичные 63 цикла чтения-выбора, пока, наконец, ведущее устройство не определит код ROM одного из подчинённых устройств и не обратится к нему.
Для мастера каждая стадия выбора состоит из двух тайм-слотов чтения и одного тайм-слота записи.

Разберем работу команды «Search ROM» на примере.

Пусть на шине установлено четыре ведомых устройства со следующими значениями кодов:
устройство 1: xxxxxx10101100
устройство 2: xxxxxx01010101
устройство 3: xxxxxx10101111
устройство 4: xxxxxx10001000
для упрощения символом «x» заменены старшие биты и показаны только младшие восемь битов

Поиск младшего бита происходит следующим образом:

Иными словами, в процессе поиска ROM мы строим одно или два двоичных дерева размером 64 (длина кода ROM), с корнями в виде значений младшего бита и листьями в виде значений старшего байта кода ROM.
Время, требуемое для считывания содержания одного ROM (без учёта процессорного времени мастера) = 960 мкс + (8 + 3*64) *61 мкс =13.16 мс.

Источник

STM32 + 1-wire. Поиск устройств

В этой статье хочу рассказать про поиск устройств на шине 1-wire. У новичков это вызывает неподдельный ужас, вплоть до того, что начинаются выделения отдельных ножек для каждого 1-wire устройства. Но на самом деле не так все страшно.

Для начала вспомним, как же осуществляется чтение бита данных от slave-устройств 1-wire.
Сначала мастер на определенный промежуток времени прижимает линию к земле, сообщая устройствам что пора бы уже что-то посылать. Если устройство хочет передать «1», то оно ничего не делает. А если хочет передать «0», то в определенный момент времени тянет линию к земле. В принципе, кроме как тянуть линию к земле, устройства больше ничего и не могут сделать.

Получается, что бит «0» — доминантный. То есть, если два устройства одновременно пошлют биты «1» и «0», то мастер увидит на линии только «0». Собственно, этим и пользуются при поиске устройств.

Поиск происходит побитно. Все начинается с самого младшего бита. Мастер посылает Reset на линию, потом посылает команду с кодом 0F — Search ROM. После этой команды все устройства готовят свой первый бит идентификатора к предъявлению.

Итак, все готовы. Мастер читает с шины два бита. Все устройства посылают сначала свой первый бит, а потом комплементарный (обратный данному) бит. В чем пафос данного алгоритма? Устройство, которое посылает 1 ничем не отличается от неактивного устройства. И чтобы их как-то расшевелить, надо чтобы устройство послало 0. А чтобы при этом передать какую-то информацию, то устройство передает ноль либо при первом, либо при втором чтении. В зависимости от бита своего уникального идентификатора.

Какие могут быть варианты:

приняты биты 11 — в этом случае никакое устройство на шине не передало «0». Это означает, что либо устройств нет, либо мы где-то запутались в процессе поиска. В любом случае критическая ситуация.
Приняты биты 10 — это означает, что в едином порыве все активные устройства передали сначала «1», а потом «0», и соответствующий бит в идентификаторе у всех активных устройств «1».
Приняты биты 01 — все то же самое, что и в предыдущей ситуации, только бит «0»
А теперь самое интересное — приняты биты 00. Это означает коллизию — одновлеменно высказались устройства с битом «0» и битом «1» в соответствующем разряде. Помните про доминантный бит?

Как же разрулить коллизию? А просто — следующим ходом мастер отсылает всем устройствам оперделенный бит. Например «1». В этом случае все устройства, у которых в текущем разряде находится «0» просто отключаются и в дальнейших выборах не участвуют. То есть количество активных устройств уменьшается. Ясное дело, что если у всех устройств установлен одинаковый бит в текущем разряде (ситуации 10 и 01), то мы именно этот бит и передаем, чтобы не поломать весь процесс.

И таким образом, когда мы пройдем все 64 бита, у нас будет выбрано одно-единственное устройство.

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

Попробуем представить процедуру выбора в виде дерева. Для упрощения я взял четырехбитные номера и всего четыре устройства:

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

Попробуем походить:
Reset, 0F
первый бит: от устройств дружно приходит 10 — у всех наших устройств в младшем бите установлена 1, просто идем по этой ветке
второй бит: приходит 00 — коллизия. Идем вправо (мы туде еще не ходили) и запоминаем 2
Как только мы шагнули вправо, устройства №2 и №3 выпали из дальнейшей процедуры поиска и нам не мешают.
третий бит: опять коллизия. Опять идем вправо и запоминаем развилку (бит 3). Отметим, что устройство №1 тоже выпало из поиска
четвертый бит: все устройства (у нас оно одно) рапортуют 10 — бит1.

Итого сложился идентификатор 1111. Записываем его и возвращаемся на предыдущую развилку. Но вернуться так просто нам не получится, надо начинать процесс сначала.

Вторая итерация:
Reset, 0F
первый бит: от устройств дружно приходит 10 — у всех наших устройств в младшем бите установлена 1, просто идем по этой ветке
второй бит: приходит 00 — коллизия. Идем вправо, нам надо добраться до следующего ветвления. Запоминаем 2
третий бит: поскольку мы добрались до развилки 3 и мы направо уже ходили, то идем налево
четвертый бит: опять осталось одно устройство и мы распознали устройство №1

Третья и четвертая итерация аналогично.

А вот, соответственно, и процедура. Все дерево if-ов написано неоптимально, а точно в соответствии с нашим алгоритмом. Оптимизированные функции поиска можно найти в аппноте от Maxim. Разобравшись, уже можно модифицировать как угодно.

тут можно заметить две переменные — lastCollision и currentColision. Первая переменная — это последняя коллизия из предыдущей итерации, в которой мы пошли направо. Она нужна для того, чтобы в текущей итерации мы пришли точно к нужной развилке и свернули налево, в еще нехоженую сторону. А currentCollision запоминает последнюю развилку в текущей итерации, на которой мы повернули направо. Чтобы в следующей итерации уже идти до нее.

Источник

Поиск устройств на шине 1-Wire

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

Почему мы алгоритм именно рассмотрим, а не напишем? Да потому что он, вообще-то говоря уже написан. «Максимкины» инженеры накатали для этого специальный документ AN187, который лежит в сети в открытом доступе. Единственный его недостаток в том, что написан он на буржуинском, что, согласитесь, не очень удобно. Вот этот недостаток мы сегодня и исправим, ну и плюс, как всегда, некоторые подробности и объяснения по поводу того, откуда у этого алгоритма растут ноги.

Итак, первая команда называется «Search ROM» и имеет шестнадцатиричный код 0xF0. Она предназначена для поиска вообще всех подключенных к шине 1-Wire устройств.

Вторая команда называется «Alarm Search» и имеет шестнадцатиричный код 0xEC. Она предназначена для поиска всех подключенных к шине 1-Wire устройств, находящихся в состоянии Alarm.

Логика работы у обеих команд одинаковая. После того, как мастер отправляет в сеть одну из этих команд, все Slave-устройства, подпадающие под критерий поиска (то есть для команды «Search ROM» — вообще все устройства сети, а для команды «Alarm Search» — устройства, находящиеся в состоянии Alarm), начинают обмениваться с мастером информацией по следующему алгоритму:
1) Slave передаёт мастеру младший бит ROM
2) Slave передаёт мастеру инверсную копию младшего бита ROM и ждёт ответ от мастера
3) Если мастер присылает в ответ тот же самый бит, который Slave посылал ему в пункте 1, то Slave повторяет шаги 1,2 для следующего бита ROM, в противном случае Slave прекращает обмен данными с мастером

Теперь давайте мы эту логику пока запомним и немного от неё отвлечёмся. Рассмотрим просто произвольные двоичные числа. Ну, скажем, 8-битные. Ну, например такие: 10001010, 00110011, 10001100, 11001001. Всю группу этих двоичных чисел можно изобразить в виде двоичного дерева, ветвями которого являются биты в соответствующих разрядах, а узлами — места, после которых биты отличаются (то есть после которых ветвь раздваивается).

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

Далее, вспоминаем основы программирования, а конкретно, — алгоритм прямого обхода двоичных деревьев. Что нам нужно для обхода некоего произвольного дерева? Всего две вещи: a) знать, где находятся узлы; б) уметь выбирать то или иное направление обхода.

А вот теперь вернёмся к логике работы команд поиска, описанной нами в самом начале статьи. И подумаем вот о чём:

1) Поскольку шина общая, то посылаемые мастером команды будут видеть сразу все устройства на шине. И, соответственно, отвечать будут тоже сразу все устройства, причём все одновременно, поскольку передача данных синхронизируется мастером.

2) Архитектура шины 1-Wire такова, что доминантным является низкий уровень сигнала на шине. То есть, если какие-то устройства будут выставлять на шине низкий уровень, а какие-то — высокий, то победят те, кто выставлял низкий уровень, и, соответственно, на шине установится низкий уровень.

Эти две особенности шины 1-Wire, в сочетании с логикой работы команд поиска, дают нам механизм определения узлов в двоичном дереве, составленном из ROM-адресов устройств, отвечающих заданным критериям поиска.

Тут всё очень просто. Со стороны мастера, когда он читает биты от slave-устройств, возможны следующие ситуации:

Осталось только найти механизм выбора направления обхода. Ну, тут уж всё очевидно, — такой механизм предоставляется нам третьим пунктом логики работы команд поиска. Ответ от мастера — это и есть выбор направления. Отправляя в шину в качестве ответа ноль или единицу, мастер как раз и решает с какой группой устройств он «продолжит разговор», по какой ветке он дальше пойдёт.

Теперь рассмотрим одну особенность алгоритма обхода двоичного дерева, характерную для шины 1-Wire. Особенность эта заключается в том, что мы можем двигаться по дереву только вперёд и каждый новый маршрут должны проходить с самого начала. То есть для каждого нового маршрута нужно заново посылать в шину Reset, команду поиска и доходить до того узла, на котором нам сейчас нужно повернуть в другую сторону. Соответственно, нам нужно будет как-то запоминать, где и куда мы в последний раз поворачивали.

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

Всё, переходим к самому алгоритму.

I) Определимся с переменными, которые нам понадобятся:

II) Составим блок-схему процедуры прохода по одному из маршрутов:

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

Более того, если инициализировать значение ROM каким-либо номером, LastDev — нулём, а LastFork любым значением >64, то однократное выполнение процедуры позволяет проверить, есть ли на шине девайс с заданным номером. Если такого девайса нет, то выполнение процедуры завершится с ошибкой (на каком-то этапе мастер получит с шины две единицы).

Если записать в первый байт ROM код семейства, в остальные байты ROM — нули, LastFork инициализировать любым значением >64, а LastDev значением 0, то выполнение процедуры столько раз, сколько потребуется, до тех пор, пока очередное выполнение не завершится с ошибкой, позволит найти все устройства заданного семейства, отвечающие заданному командой критерию поиска.

Вот в общем-то и всё. Пример реализации описанного алгоритма можно посмотреть в программе для программирования микросхем памяти DS2430, исходники которой можно скачать в подразделе «полезные программы для ПК«.

Источник

То, что вы хотели знать
Adblock
detector