В электронике есть множество проводных полудуплексных асинхронных последовательных интерфейсов типа общая шина. Это 1-Wire, RS485, 10BASE2(thin Ethernet), LIN, K-Line , CAN, I2C, MIL-STD-1553, ARINC 429.
Во всех этих shared-bus интерфейсах так или иначе возникает задача сканирования шины.
Всем кто работал с i2c известна процедура сканирования шины. Там можно просто методом перебора просканировать шину. Так как длина адреса всего 7 бит, то можно просканировать шину просто за пару секунд.
![Результат сканирования шины I2C1 в UART-CLI Результат сканирования шины I2C1 в UART-CLI](https://habrastorage.org/getpro/habr/upload_files/c33/9b9/4b9/c339b94b95b4383670d8e543f6250bad.png)
В CAN задачи сканирования вообще не стоит так как там коллизии разруливаются на аппаратном уровне физических трансиверов или вовсе MAC периферии. В CAN достаточно подключится в любом месте и через мгновение в утилите CAN-Hacker будет понятно кто там живет на шине CAN. В CAN все ноды постоянно flood(дят) "Hello!" пакетами.
В Lin сеть узлов обычно полностью 100% статическая и прошивается во время производства. Это и понятно, ведь в автомобильной двери во время езды не появится новая кнопка. В салоне автобуса по маршруту не вырастет новый поручень с кнопкой остановки.
Как обстоят дела со сканированием в остальных проводных интерфейсах: 1-Wire, 10BASE2(thin Ethernet), K-Line, MIL-STD-1553, ARINC 429 я, честно, не знаю. Если кто в теме, то напишите, пожалуйста, в комментариях.
Как обычно выглядит сеть RS485?
![шпаргалка по шине RS485 шпаргалка по шине RS485](https://habrastorage.org/getpro/habr/upload_files/a80/ff4/721/a80ff472160fc41db7380db91fb61871.jpg)
Надо отметить что RS-485 это фактически только труба для чисел (числопровод). Интерфейс физического уровня в модели OSI-7. Протокол канального уровня поверх RS485 может быть самым разнообразным: ModBus, Pelco-D, yModem, xModem, или любой другой проприетарных протокол. В 80% случаев в этом протоколе будет идентификатор устройства в сети. Это может быть MAC, ID, IP, SN или что-то ещё. Про то какими атрибутами обладает хороший канальный протокол есть вообще отдельный текст. https://habr.com/ru/articles/682292/
В чем трудность сканирования шины RS485?
1--Трудность в том что адреса устройств в протоколе канального уровня поверх физического интерфейса RS485 могут иметь существенно более высокую разрядность чем 8 бит, как правило это 32 бита (4байта) или даже MAC адреса по 48бит (6 байт) или 64бит(8-байт). Предположим в протоколе канального уровня узлы на интерфейсе RS485 имеют 32х битные адреса и если сканировать шину RS485 как это было в I2C то китайский калькулятор покажет что надо "подождать и потерпеть" 14 лет!
![вычисления времени ожидания сканирования методом перебора вычисления времени ожидания сканирования методом перебора](https://habrastorage.org/getpro/habr/upload_files/0cc/e0e/40f/0cce0e40f3ecf8dbf33bb1770e4534ca.png)
2--В шине RS485 нет аппаратного механизма разрешения коллизий подобно CAN(у). Если 2 ноды начнут передавать одновременно, то данные в витой паре исказятся и мастер прочитает мусорный пакет с поврежденной контрольной суммой.
3--Все устройства на шине RS485 могут вообще работать на разных битовых скоростях 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, 230400, 460800, 921600 бит/c. Я работал в трех конторах и у каждой была своя стандартная битовая скорость шины RS485. И у всех разная! Если устройство работает на битовой скорости 460800 бит/c то оно не будет отвечать на пакеты которые ей посылают на битовой скорости 115200 бит/c.
Как же просканировать шину RS485?
Перед тем как приступить к объяснению сути алгоритма сканирования шины RS485 хочется привести аналогию из жизни. Аналогия эта про то как медвежатники отмычками взламывают навесные замки. Первой отмычкой создается момент силы, который фиксирует положение одного из пинов. Затем второй отмычкой находят пин, который движется туго и медленно и аккуратно подбирают положение упирающегося пина пока не услышат тихенький щелчок. Первая отмычка дрогнет. Затем начинает упираться другой пин. Аналогично двигают следующий пин до такого же щелчка. И так до тех пор пока все пины точно не встанут на нужные положения. Тогда замок откроется.
![Как работает отмычка Как работает отмычка](https://habrastorage.org/getpro/habr/upload_files/a82/5f3/32d/a825f332d267d5ebd4b928efff8a9cbc.gif)
Тут ситуация аналогичная. Вместо пинов - биты, вместо щелчка - сигнал подтверждения.
Прежде чем двигаться дальше надо договориться о терминологии.
Терминология
--Адрес устройства - это либо MAC адрес, серийный номер (SN), либо аналог IP адреса или любой другой ID(шник) уникальный для каждого экземпляра устройства на шине RS485. Важен тот момент, что адрес широкий много битный. Пусть это, например, 32х битный адрес.
--Маска адреса - это часть адреса устройства, которая начинается с наименьшего значащего бита LSB и увеличивается в сторону старшего бита. Имеет смысл расширять маску от младших битов ибо младшие есть у всех адресов, а вот старших единичных битов может и не быть. Вот пример нескольких реальных масок:
№ | Пример маски для адреса | Длина маски, [бит] |
1 | xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx | 0 |
2 | xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxx0 | 1 |
3 | xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xx00 | 2 |
4 | xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xx01 | 2 |
5 | 1000_0100_0000_1111_1111_0001_1101_0011 | 32 |
6 | xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xx10 | 2 |
7 | xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xx10_1110 | 6 |
--Сигнал подтверждения- это когда ведомое устройство на RS485 берет пин UART_TX, переводит его в режим GPIO PUSH-PULL, устанавливает 0V, ждет T_ack секунд (например 10ms) и после этого снова подключает к пину UART_TX контроллер. Всё это и называется сигналом подтверждения. По сути устройство на время прижимает шину в ноль вольт. При этом совершенно не опасно, если несколько устройств одновременно прижмут шину в ноль. Эффект будет как от одного. То есть получается логическое ИЛИ. У мастера на UART_RX будет 0V.
--Пакет mute - это такой бинарный пакет получив который ведомое устройство перестает что- либо отправлять в общую шину RS485 и не будет даже испускать сигналы. Устройство будет только слушать шину. Mute пакет может содержать параметр включить или отключить Mute режим.
Словесное описание алгоритма сканирования шины RS485
1--Мастер устройство объявляет что сейчас все ведомые устройства переходят в режим сканирования.
2--мастер отправляет маску адреса, например Mx=xx...xx0 или Mx1=xx...xx1 и просит, чтобы откликнулись те устройства чей адрес совпадает с маской. То есть у кого нулевой бит равен нулю.
3--мастер переводит пин UART_RX в GPIO input, устанавливает подтяжку к питанию и непрерывно смотрит за напряжением на проводе UART_RX. Тут есть два исхода.
a) У мастера на проводе UART_RX появился 0.0 V. Значит, что на шине RS485 присутствует как минимум одно ведомое устройство у кого адрес совпадает с маской Mx.
b) У мастера на проводе UART_RX остался 3,3V. Значат что на шине RS485 нет ни одного устройства у кого бы адрес совпадал с маской Mx. Это значит, что дальше мы с этой маской Mx не работаем и просто отбрасываем её в сторону как заранее неправильный путь. Причем мастер ожидает не бесконечно, а строго определённой время таймаута, которое общее для всех устройств, например 20ms.
4--В случае 3.a) маска расширяется на 1 бит влево. Тут тоже есть два варианта. Либо мы к маске обнаруженного устройства приписываем префикс 0 либо 1. Надо идти по обоим путям: 1 и 2.
№ | Маска | Пояснение | Пример |
1 | xx...x0[PREV_ACK_MASK] | увеличили на 0 | x...x00 |
2 | xx...x1[PREV_ACK_MASK] | увеличили на 1 | x...x10 |
Тут прослеживается рекурсия или элементы динамического программирование. Каждый шаг порождает 2 шага: c префиксом 0 и с префиксом 1.
Далее шаги 2-3-4 можно повторять снова и снова пока маска не достигнет длинны 32 бита. Как только это произойдет это станет означать что найдено одно устройство на шине. Но как найти остальные N-1 устройство?
5--Как только маска будет совпадать с 32 битами то мастер устройство отправляет команду заглушить устройство по определённому адресу. Master отправляет mute пакет.
Шаги 2-3-4-5 это по сути одна итерация. На следующей итерации мастер обнаружит другое устройство. И так до тех пор пока все маски перестанут выдавать сигнал подтверждения. После этого шина RS485 будет полностью просканирована.
К слову, на маску длинной ноль (xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx) отвечают установкой сигнала подтверждения все не заглушенные узлы RS485 сети. Поэтому данный пакет установки маски может служить критерием окончания сканирования сети.
Справедливости ради можно добавить что надо проделать все то же самое для всех возможных битовых скоростей RS485: 9600, 115200, и проч. Однако как правило RS485 сеть собирают из устройств у которых уже прописана битовая скорость по умолчанию.
Время сканирования на одной битовой скорости займет
Вариант | Время | Пояснение |
лучший случай | 32*N*dt | подтверждение при первом увеличении маски |
Худший случай | 32*N*2*dt | подтверждение при втором увеличении маски |
где dt - это время отклика на адресную маску
Алгоритм сканирования общей шины можно изобразить в виде вот этой диаграммы обмена пакетами
![](https://habrastorage.org/getpro/habr/upload_files/edc/2bc/4eb/edc2bc4eb5130382d5b32bfc8ae1f35e.jpg)
Вот лог сканирования для 32-х битных адресов
Лог сканирования для 32битных адресов
-->
-->rss
2.784 :I [RS485] Scan
2.786 :I [RS485] 1: IsAnyBodyWith x:0
2.788 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x:0
2.790 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x:0
2.792 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x:0
2.794 :I [RS485] 3: IsAnyBodyWith x1:1
2.796 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x1:1
2.798 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x1:1
2.800 :I [RS485] 4: IsAnyBodyWith x11:2
2.802 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x11:2
2.804 :I [RS485] 5: IsAnyBodyWith x111:3
2.806 :N [RS485] NoMask x111:3!
2.808 :I [RS485] 6: IsAnyBodyWith x011:3
2.810 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x011:3
2.812 :I [RS485] 7: IsAnyBodyWith x1011:4
2.814 :N [RS485] NoMask x1011:4!
2.816 :I [RS485] 8: IsAnyBodyWith x0011:4
2.818 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x0011:4
2.820 :I [RS485] 9: IsAnyBodyWith x10011:5
2.822 :N [RS485] NoMask x10011:5!
2.824 :I [RS485] 10: IsAnyBodyWith x00011:5
2.826 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x00011:5
2.828 :I [RS485] 11: IsAnyBodyWith x100011:6
2.830 :N [RS485] NoMask x100011:6!
2.832 :I [RS485] 12: IsAnyBodyWith x000011:6
2.834 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x000011:6
2.836 :I [RS485] 13: IsAnyBodyWith x1000011:7
2.838 :N [RS485] NoMask x1000011:7!
2.840 :I [RS485] 14: IsAnyBodyWith x0000011:7
2.842 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x0000011:7
2.844 :I [RS485] 15: IsAnyBodyWith x10000011:8
2.846 :N [RS485] NoMask x10000011:8!
2.848 :I [RS485] 16: IsAnyBodyWith x00000011:8
2.850 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x00000011:8
2.852 :I [RS485] 17: IsAnyBodyWith x100000011:9
2.854 :N [RS485] NoMask x100000011:9!
2.856 :I [RS485] 18: IsAnyBodyWith x000000011:9
2.858 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x000000011:9
2.860 :I [RS485] 19: IsAnyBodyWith x1000000011:10
2.862 :N [RS485] NoMask x1000000011:10!
2.864 :I [RS485] 20: IsAnyBodyWith x0000000011:10
2.866 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x0000000011:10
2.868 :I [RS485] 21: IsAnyBodyWith x10000000011:11
2.870 :N [RS485] NoMask x10000000011:11!
2.872 :I [RS485] 22: IsAnyBodyWith x00000000011:11
2.874 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x00000000011:11
2.876 :I [RS485] 23: IsAnyBodyWith x100000000011:12
2.878 :N [RS485] NoMask x100000000011:12!
2.880 :I [RS485] 24: IsAnyBodyWith x000000000011:12
2.882 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x000000000011:12
2.884 :I [RS485] 25: IsAnyBodyWith x1000000000011:13
2.886 :N [RS485] NoMask x1000000000011:13!
2.888 :I [RS485] 26: IsAnyBodyWith x0000000000011:13
2.890 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x0000000000011:13
2.892 :I [RS485] 27: IsAnyBodyWith x10000000000011:14
2.894 :N [RS485] NoMask x10000000000011:14!
2.896 :I [RS485] 28: IsAnyBodyWith x00000000000011:14
2.898 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x00000000000011:14
2.900 :I [RS485] 29: IsAnyBodyWith x100000000000011:15
2.902 :N [RS485] NoMask x100000000000011:15!
2.904 :I [RS485] 30: IsAnyBodyWith x000000000000011:15
2.906 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x000000000000011:15
2.908 :I [RS485] 31: IsAnyBodyWith x1000000000000011:16
2.910 :N [RS485] NoMask x1000000000000011:16!
2.912 :I [RS485] 32: IsAnyBodyWith x0000000000000011:16
2.914 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x0000000000000011:16
2.916 :I [RS485] 33: IsAnyBodyWith x10000000000000011:17
2.918 :N [RS485] NoMask x10000000000000011:17!
2.920 :I [RS485] 34: IsAnyBodyWith x00000000000000011:17
2.922 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x00000000000000011:17
2.924 :I [RS485] 35: IsAnyBodyWith x100000000000000011:18
2.926 :N [RS485] NoMask x100000000000000011:18!
2.928 :I [RS485] 36: IsAnyBodyWith x000000000000000011:18
2.930 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x000000000000000011:18
2.932 :I [RS485] 37: IsAnyBodyWith x1000000000000000011:19
2.934 :N [RS485] NoMask x1000000000000000011:19!
2.936 :I [RS485] 38: IsAnyBodyWith x0000000000000000011:19
2.938 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x0000000000000000011:19
2.940 :I [RS485] 39: IsAnyBodyWith x10000000000000000011:20
2.942 :N [RS485] NoMask x10000000000000000011:20!
2.944 :I [RS485] 40: IsAnyBodyWith x00000000000000000011:20
2.946 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x00000000000000000011:20
2.948 :I [RS485] 41: IsAnyBodyWith x100000000000000000011:21
2.950 :N [RS485] NoMask x100000000000000000011:21!
2.952 :I [RS485] 42: IsAnyBodyWith x000000000000000000011:21
2.954 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x000000000000000000011:21
2.956 :I [RS485] 43: IsAnyBodyWith x1000000000000000000011:22
2.958 :N [RS485] NoMask x1000000000000000000011:22!
2.960 :I [RS485] 44: IsAnyBodyWith x0000000000000000000011:22
2.962 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x0000000000000000000011:22
2.964 :I [RS485] 45: IsAnyBodyWith x10000000000000000000011:23
2.966 :N [RS485] NoMask x10000000000000000000011:23!
2.968 :I [RS485] 46: IsAnyBodyWith x00000000000000000000011:23
2.970 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x00000000000000000000011:23
2.972 :I [RS485] 47: IsAnyBodyWith x100000000000000000000011:24
2.974 :N [RS485] NoMask x100000000000000000000011:24!
2.976 :I [RS485] 48: IsAnyBodyWith x000000000000000000000011:24
2.978 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x000000000000000000000011:24
2.980 :I [RS485] 49: IsAnyBodyWith x1000000000000000000000011:25
2.982 :N [RS485] NoMask x1000000000000000000000011:25!
2.984 :I [RS485] 50: IsAnyBodyWith x0000000000000000000000011:25
2.986 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x0000000000000000000000011:25
2.988 :I [RS485] 51: IsAnyBodyWith x10000000000000000000000011:26
2.990 :N [RS485] NoMask x10000000000000000000000011:26!
2.992 :I [RS485] 52: IsAnyBodyWith x00000000000000000000000011:26
2.994 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x00000000000000000000000011:26
2.996 :I [RS485] 53: IsAnyBodyWith x100000000000000000000000011:27
2.998 :N [RS485] NoMask x100000000000000000000000011:27!
3.000 :I [RS485] 54: IsAnyBodyWith x000000000000000000000000011:27
3.002 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x000000000000000000000000011:27
3.004 :I [RS485] 55: IsAnyBodyWith x1000000000000000000000000011:28
3.006 :N [RS485] NoMask x1000000000000000000000000011:28!
3.008 :I [RS485] 56: IsAnyBodyWith x0000000000000000000000000011:28
3.010 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x0000000000000000000000000011:28
3.012 :I [RS485] 57: IsAnyBodyWith x10000000000000000000000000011:29
3.014 :N [RS485] NoMask x10000000000000000000000000011:29!
3.016 :I [RS485] 58: IsAnyBodyWith x00000000000000000000000000011:29
3.018 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x00000000000000000000000000011:29
3.020 :I [RS485] 59: IsAnyBodyWith x100000000000000000000000000011:30
3.022 :N [RS485] NoMask x100000000000000000000000000011:30!
3.024 :I [RS485] 60: IsAnyBodyWith x000000000000000000000000000011:30
3.026 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x000000000000000000000000000011:30
3.028 :I [RS485] 61: IsAnyBodyWith x1000000000000000000000000000011:31
3.030 :N [RS485] NoMask x1000000000000000000000000000011:31!
3.032 :I [RS485] 62: IsAnyBodyWith x0000000000000000000000000000011:31
3.034 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask:x0000000000000000000000000000011:31
3.036 :I [RS485] 63: IsAnyBodyWith :32
3.038 :N [RS485] NoMask :32!
3.040 :I [RS485] 64: IsAnyBodyWith :32
3.042 :W [RS485] ACK Addr 0x3=0000_0000_0000_0000_0000_0000_0000_0011 Mask::32
3.044 :W [RS485] SpotAddr 0x3!
3.046 :W [RS485] MuteAddr 0x3
3.048 :I [RS485] 65: IsAnyBodyWith x01:2
3.050 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x01:2
3.052 :I [RS485] 66: IsAnyBodyWith x101:3
3.054 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x101:3
3.056 :I [RS485] 67: IsAnyBodyWith x1101:4
3.058 :N [RS485] NoMask x1101:4!
3.060 :I [RS485] 68: IsAnyBodyWith x0101:4
3.062 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x0101:4
3.064 :I [RS485] 69: IsAnyBodyWith x10101:5
3.066 :N [RS485] NoMask x10101:5!
3.068 :I [RS485] 70: IsAnyBodyWith x00101:5
3.070 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x00101:5
3.072 :I [RS485] 71: IsAnyBodyWith x100101:6
3.074 :N [RS485] NoMask x100101:6!
3.076 :I [RS485] 72: IsAnyBodyWith x000101:6
3.078 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x000101:6
3.080 :I [RS485] 73: IsAnyBodyWith x1000101:7
3.082 :N [RS485] NoMask x1000101:7!
3.084 :I [RS485] 74: IsAnyBodyWith x0000101:7
3.086 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x0000101:7
3.088 :I [RS485] 75: IsAnyBodyWith x10000101:8
3.090 :N [RS485] NoMask x10000101:8!
3.092 :I [RS485] 76: IsAnyBodyWith x00000101:8
3.094 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x00000101:8
3.096 :I [RS485] 77: IsAnyBodyWith x100000101:9
3.098 :N [RS485] NoMask x100000101:9!
3.100 :I [RS485] 78: IsAnyBodyWith x000000101:9
3.102 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x000000101:9
3.104 :I [RS485] 79: IsAnyBodyWith x1000000101:10
3.106 :N [RS485] NoMask x1000000101:10!
3.108 :I [RS485] 80: IsAnyBodyWith x0000000101:10
3.110 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x0000000101:10
3.112 :I [RS485] 81: IsAnyBodyWith x10000000101:11
3.114 :N [RS485] NoMask x10000000101:11!
3.116 :I [RS485] 82: IsAnyBodyWith x00000000101:11
3.118 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x00000000101:11
3.120 :I [RS485] 83: IsAnyBodyWith x100000000101:12
3.122 :N [RS485] NoMask x100000000101:12!
3.124 :I [RS485] 84: IsAnyBodyWith x000000000101:12
3.126 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x000000000101:12
3.128 :I [RS485] 85: IsAnyBodyWith x1000000000101:13
3.130 :N [RS485] NoMask x1000000000101:13!
3.132 :I [RS485] 86: IsAnyBodyWith x0000000000101:13
3.134 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x0000000000101:13
3.136 :I [RS485] 87: IsAnyBodyWith x10000000000101:14
3.138 :N [RS485] NoMask x10000000000101:14!
3.140 :I [RS485] 88: IsAnyBodyWith x00000000000101:14
3.142 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x00000000000101:14
3.144 :I [RS485] 89: IsAnyBodyWith x100000000000101:15
3.146 :N [RS485] NoMask x100000000000101:15!
3.148 :I [RS485] 90: IsAnyBodyWith x000000000000101:15
3.150 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x000000000000101:15
3.152 :I [RS485] 91: IsAnyBodyWith x1000000000000101:16
3.154 :N [RS485] NoMask x1000000000000101:16!
3.156 :I [RS485] 92: IsAnyBodyWith x0000000000000101:16
3.158 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x0000000000000101:16
3.160 :I [RS485] 93: IsAnyBodyWith x10000000000000101:17
3.162 :N [RS485] NoMask x10000000000000101:17!
3.164 :I [RS485] 94: IsAnyBodyWith x00000000000000101:17
3.166 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x00000000000000101:17
3.168 :I [RS485] 95: IsAnyBodyWith x100000000000000101:18
3.170 :N [RS485] NoMask x100000000000000101:18!
3.172 :I [RS485] 96: IsAnyBodyWith x000000000000000101:18
3.174 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x000000000000000101:18
3.176 :I [RS485] 97: IsAnyBodyWith x1000000000000000101:19
3.178 :N [RS485] NoMask x1000000000000000101:19!
3.180 :I [RS485] 98: IsAnyBodyWith x0000000000000000101:19
3.182 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x0000000000000000101:19
3.184 :I [RS485] 99: IsAnyBodyWith x10000000000000000101:20
3.186 :N [RS485] NoMask x10000000000000000101:20!
3.188 :I [RS485] 100: IsAnyBodyWith x00000000000000000101:20
3.190 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x00000000000000000101:20
3.192 :I [RS485] 101: IsAnyBodyWith x100000000000000000101:21
3.194 :N [RS485] NoMask x100000000000000000101:21!
3.196 :I [RS485] 102: IsAnyBodyWith x000000000000000000101:21
3.198 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x000000000000000000101:21
3.200 :I [RS485] 103: IsAnyBodyWith x1000000000000000000101:22
3.202 :N [RS485] NoMask x1000000000000000000101:22!
3.204 :I [RS485] 104: IsAnyBodyWith x0000000000000000000101:22
3.206 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x0000000000000000000101:22
3.208 :I [RS485] 105: IsAnyBodyWith x10000000000000000000101:23
3.210 :N [RS485] NoMask x10000000000000000000101:23!
3.212 :I [RS485] 106: IsAnyBodyWith x00000000000000000000101:23
3.214 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x00000000000000000000101:23
3.216 :I [RS485] 107: IsAnyBodyWith x100000000000000000000101:24
3.218 :N [RS485] NoMask x100000000000000000000101:24!
3.220 :I [RS485] 108: IsAnyBodyWith x000000000000000000000101:24
3.222 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x000000000000000000000101:24
3.224 :I [RS485] 109: IsAnyBodyWith x1000000000000000000000101:25
3.226 :N [RS485] NoMask x1000000000000000000000101:25!
3.228 :I [RS485] 110: IsAnyBodyWith x0000000000000000000000101:25
3.230 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x0000000000000000000000101:25
3.232 :I [RS485] 111: IsAnyBodyWith x10000000000000000000000101:26
3.234 :N [RS485] NoMask x10000000000000000000000101:26!
3.236 :I [RS485] 112: IsAnyBodyWith x00000000000000000000000101:26
3.238 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x00000000000000000000000101:26
3.240 :I [RS485] 113: IsAnyBodyWith x100000000000000000000000101:27
3.242 :N [RS485] NoMask x100000000000000000000000101:27!
3.244 :I [RS485] 114: IsAnyBodyWith x000000000000000000000000101:27
3.246 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x000000000000000000000000101:27
3.248 :I [RS485] 115: IsAnyBodyWith x1000000000000000000000000101:28
3.250 :N [RS485] NoMask x1000000000000000000000000101:28!
3.252 :I [RS485] 116: IsAnyBodyWith x0000000000000000000000000101:28
3.254 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x0000000000000000000000000101:28
3.256 :I [RS485] 117: IsAnyBodyWith x10000000000000000000000000101:29
3.258 :N [RS485] NoMask x10000000000000000000000000101:29!
3.260 :I [RS485] 118: IsAnyBodyWith x00000000000000000000000000101:29
3.262 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x00000000000000000000000000101:29
3.264 :I [RS485] 119: IsAnyBodyWith x100000000000000000000000000101:30
3.266 :N [RS485] NoMask x100000000000000000000000000101:30!
3.268 :I [RS485] 120: IsAnyBodyWith x000000000000000000000000000101:30
3.270 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x000000000000000000000000000101:30
3.272 :I [RS485] 121: IsAnyBodyWith x1000000000000000000000000000101:31
3.274 :N [RS485] NoMask x1000000000000000000000000000101:31!
3.276 :I [RS485] 122: IsAnyBodyWith x0000000000000000000000000000101:31
3.278 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask:x0000000000000000000000000000101:31
3.280 :I [RS485] 123: IsAnyBodyWith :32
3.282 :N [RS485] NoMask :32!
3.284 :I [RS485] 124: IsAnyBodyWith :32
3.286 :W [RS485] ACK Addr 0x5=0000_0000_0000_0000_0000_0000_0000_0101 Mask::32
3.288 :W [RS485] SpotAddr 0x5!
3.290 :W [RS485] MuteAddr 0x5
3.292 :I [RS485] 125: IsAnyBodyWith x001:3
3.294 :N [RS485] NoMask x001:3!
3.296 :I [RS485] 126: IsAnyBodyWith x0:1
3.298 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x0:1
3.300 :I [RS485] 127: IsAnyBodyWith x10:2
3.302 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x10:2
3.304 :I [RS485] 128: IsAnyBodyWith x110:3
3.306 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x110:3
3.308 :I [RS485] 129: IsAnyBodyWith x1110:4
3.310 :N [RS485] NoMask x1110:4!
3.312 :I [RS485] 130: IsAnyBodyWith x0110:4
3.314 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x0110:4
3.316 :I [RS485] 131: IsAnyBodyWith x10110:5
3.318 :N [RS485] NoMask x10110:5!
3.320 :I [RS485] 132: IsAnyBodyWith x00110:5
3.322 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x00110:5
3.324 :I [RS485] 133: IsAnyBodyWith x100110:6
3.326 :N [RS485] NoMask x100110:6!
3.328 :I [RS485] 134: IsAnyBodyWith x000110:6
3.330 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x000110:6
3.332 :I [RS485] 135: IsAnyBodyWith x1000110:7
3.334 :N [RS485] NoMask x1000110:7!
3.336 :I [RS485] 136: IsAnyBodyWith x0000110:7
3.338 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x0000110:7
3.340 :I [RS485] 137: IsAnyBodyWith x10000110:8
3.342 :N [RS485] NoMask x10000110:8!
3.344 :I [RS485] 138: IsAnyBodyWith x00000110:8
3.346 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x00000110:8
3.348 :I [RS485] 139: IsAnyBodyWith x100000110:9
3.350 :N [RS485] NoMask x100000110:9!
3.352 :I [RS485] 140: IsAnyBodyWith x000000110:9
3.354 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x000000110:9
3.356 :I [RS485] 141: IsAnyBodyWith x1000000110:10
3.358 :N [RS485] NoMask x1000000110:10!
3.360 :I [RS485] 142: IsAnyBodyWith x0000000110:10
3.362 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x0000000110:10
3.364 :I [RS485] 143: IsAnyBodyWith x10000000110:11
3.366 :N [RS485] NoMask x10000000110:11!
3.368 :I [RS485] 144: IsAnyBodyWith x00000000110:11
3.370 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x00000000110:11
3.372 :I [RS485] 145: IsAnyBodyWith x100000000110:12
3.374 :N [RS485] NoMask x100000000110:12!
3.376 :I [RS485] 146: IsAnyBodyWith x000000000110:12
3.378 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x000000000110:12
3.380 :I [RS485] 147: IsAnyBodyWith x1000000000110:13
3.382 :N [RS485] NoMask x1000000000110:13!
3.384 :I [RS485] 148: IsAnyBodyWith x0000000000110:13
3.386 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x0000000000110:13
3.388 :I [RS485] 149: IsAnyBodyWith x10000000000110:14
3.390 :N [RS485] NoMask x10000000000110:14!
3.392 :I [RS485] 150: IsAnyBodyWith x00000000000110:14
3.394 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x00000000000110:14
3.396 :I [RS485] 151: IsAnyBodyWith x100000000000110:15
3.398 :N [RS485] NoMask x100000000000110:15!
3.400 :I [RS485] 152: IsAnyBodyWith x000000000000110:15
3.402 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x000000000000110:15
3.404 :I [RS485] 153: IsAnyBodyWith x1000000000000110:16
3.406 :N [RS485] NoMask x1000000000000110:16!
3.408 :I [RS485] 154: IsAnyBodyWith x0000000000000110:16
3.410 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x0000000000000110:16
3.412 :I [RS485] 155: IsAnyBodyWith x10000000000000110:17
3.414 :N [RS485] NoMask x10000000000000110:17!
3.416 :I [RS485] 156: IsAnyBodyWith x00000000000000110:17
3.418 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x00000000000000110:17
3.420 :I [RS485] 157: IsAnyBodyWith x100000000000000110:18
3.422 :N [RS485] NoMask x100000000000000110:18!
3.424 :I [RS485] 158: IsAnyBodyWith x000000000000000110:18
3.426 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x000000000000000110:18
3.428 :I [RS485] 159: IsAnyBodyWith x1000000000000000110:19
3.430 :N [RS485] NoMask x1000000000000000110:19!
3.432 :I [RS485] 160: IsAnyBodyWith x0000000000000000110:19
3.434 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x0000000000000000110:19
3.436 :I [RS485] 161: IsAnyBodyWith x10000000000000000110:20
3.438 :N [RS485] NoMask x10000000000000000110:20!
3.440 :I [RS485] 162: IsAnyBodyWith x00000000000000000110:20
3.442 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x00000000000000000110:20
3.444 :I [RS485] 163: IsAnyBodyWith x100000000000000000110:21
3.446 :N [RS485] NoMask x100000000000000000110:21!
3.448 :I [RS485] 164: IsAnyBodyWith x000000000000000000110:21
3.450 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x000000000000000000110:21
3.452 :I [RS485] 165: IsAnyBodyWith x1000000000000000000110:22
3.454 :N [RS485] NoMask x1000000000000000000110:22!
3.456 :I [RS485] 166: IsAnyBodyWith x0000000000000000000110:22
3.458 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x0000000000000000000110:22
3.460 :I [RS485] 167: IsAnyBodyWith x10000000000000000000110:23
3.462 :N [RS485] NoMask x10000000000000000000110:23!
3.464 :I [RS485] 168: IsAnyBodyWith x00000000000000000000110:23
3.466 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x00000000000000000000110:23
3.468 :I [RS485] 169: IsAnyBodyWith x100000000000000000000110:24
3.470 :N [RS485] NoMask x100000000000000000000110:24!
3.472 :I [RS485] 170: IsAnyBodyWith x000000000000000000000110:24
3.474 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x000000000000000000000110:24
3.476 :I [RS485] 171: IsAnyBodyWith x1000000000000000000000110:25
3.478 :N [RS485] NoMask x1000000000000000000000110:25!
3.480 :I [RS485] 172: IsAnyBodyWith x0000000000000000000000110:25
3.482 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x0000000000000000000000110:25
3.484 :I [RS485] 173: IsAnyBodyWith x10000000000000000000000110:26
3.486 :N [RS485] NoMask x10000000000000000000000110:26!
3.488 :I [RS485] 174: IsAnyBodyWith x00000000000000000000000110:26
3.490 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x00000000000000000000000110:26
3.492 :I [RS485] 175: IsAnyBodyWith x100000000000000000000000110:27
3.494 :N [RS485] NoMask x100000000000000000000000110:27!
3.496 :I [RS485] 176: IsAnyBodyWith x000000000000000000000000110:27
3.498 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x000000000000000000000000110:27
3.500 :I [RS485] 177: IsAnyBodyWith x1000000000000000000000000110:28
3.502 :N [RS485] NoMask x1000000000000000000000000110:28!
3.504 :I [RS485] 178: IsAnyBodyWith x0000000000000000000000000110:28
3.506 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x0000000000000000000000000110:28
3.508 :I [RS485] 179: IsAnyBodyWith x10000000000000000000000000110:29
3.510 :N [RS485] NoMask x10000000000000000000000000110:29!
3.512 :I [RS485] 180: IsAnyBodyWith x00000000000000000000000000110:29
3.514 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x00000000000000000000000000110:29
3.516 :I [RS485] 181: IsAnyBodyWith x100000000000000000000000000110:30
3.518 :N [RS485] NoMask x100000000000000000000000000110:30!
3.520 :I [RS485] 182: IsAnyBodyWith x000000000000000000000000000110:30
3.522 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x000000000000000000000000000110:30
3.524 :I [RS485] 183: IsAnyBodyWith x1000000000000000000000000000110:31
3.526 :N [RS485] NoMask x1000000000000000000000000000110:31!
3.528 :I [RS485] 184: IsAnyBodyWith x0000000000000000000000000000110:31
3.530 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask:x0000000000000000000000000000110:31
3.532 :I [RS485] 185: IsAnyBodyWith :32
3.534 :N [RS485] NoMask :32!
3.536 :I [RS485] 186: IsAnyBodyWith :32
3.538 :W [RS485] ACK Addr 0x6=0000_0000_0000_0000_0000_0000_0000_0110 Mask::32
3.540 :W [RS485] SpotAddr 0x6!
3.542 :W [RS485] MuteAddr 0x6
3.544 :I [RS485] 187: IsAnyBodyWith x010:3
3.546 :N [RS485] NoMask x010:3!
3.548 :I [RS485] 188: IsAnyBodyWith x00:2
3.550 :N [RS485] NoMask x00:2!
-->
Плюсы этого метода
1++Алгоритм сканирования RS485 простой. Его может реализовать даже программист-микроконтроллеров с экстремально низкой квалификацией.
2++эффективность
3++Быстрота работы в сравнении с перебором всех адресов.
4++Нет нужды в дополнительных проводах. Всё что надо это одна витая пара интерфейса RS485.
Минусы
1--Master устройство должно быть микроконтроллером с полноценным драйвером GPIO и UART. Не получится просто взять первый попавшийся китайский переходник USB-RS485, подключить его к PC и написать консольное Windows приложение, которое выполнит сканирование RS485 шины. Надо чтобы была не просто возможность читать\писать байты в RS485, но и переключать функции пинов с GPIO на UART и обратно. Причем надо переключать функции пинов быстро чтобы успеть принять сигналы от Slave nodes.
2--Нужна программная поддержка этого простенького протокола сканирования RS485 как на стороне master так и на стороне slave устройств.
3--Если Ваш мастер RS485 это embedded Linux SoC то очень трудно сделать в run-time переключение пина из UART_RX в GPIO-in. Как правило, low level API в Linux такого не позволяет, так как Linux - это не RTOS. Linux может вообще после отправки маски начать 20 мин обновлять антивирус. Однако, на самом деле не обязательно переключать функции GPIO c UART на GPIO. Если у Slave(ва) адрес совпал с маской, то он может прижать шину просто отправив несколько раз 0x00. Мастер в RS485 увидит это как принятие пакета с неправильной контрольной суммой или UART периферия выдаст прерывание по over-run и так мастер поймет, что поступил ACK сигнал. Нам главное хоть какой-то отклик на маску, будь до нулевой байт, либо оver-run прерывание.
Вывод
Теперь и вы умеете сканировать шину RS485 и можете учить других. Этот простой алгоритм сканирования адресов на общей шине подойдет не только для RS485. Его можно реализовать для любого другого интерфейса с топологией "общая шина". Это может быть интерфейс 1-wire, LIN или даже вовсе беспроводные интерфейсы типа GFSK, LoRa или UWB.
Словарь
Акроним | Расшифровка |
RS485 | Recommended Standard 485 |
LSB | Least Significant Bit |
MAC | medium access control |
PC | personal computer |
UART | Universal asynchronous receiver-transmitter |
SoC | System on a chip |
GPIO | General-purpose input/output |
Links
https://habr.com/ru/companies/wirenboard/articles/737402/
https://habr.com/ru/companies/milandr/articles/540084/
https://we.easyelectronics.ru/STM32/stm32-1-wire-poisk-ustroystv.html
https://www.analog.com/en/app-notes/1wire-search-algorithm.html