[Home] [< Prev: Пример использования цифрового датчика температуры DS18B20] [Next: Тактовые сигналы микроконтроллеров STM32F100xx >]

Переходник RS-232 (COM-порт) - 1-Wire. SEARCH ROM

В этой статье рассмотрим два важных вопроса: подключение к компьютеру устройств с интерфейсом 1-Wire, для чего соберём соответствующий переходник и случай подключения нескольких ведомых устройств к одной 1-Wire шине. Когда на одной шине имеется несколько устройств, уже не удастся отделаться простейшими командами вроде SKIP ROM или READ ROM, а потребуется полноценное исследование ROM-кодов всех устройств. Многие авторы избегают этой темы, с помощью отговорки типа "рассмотрим простейший случай случай подключения одного устройства, а вообще используйте какую-нибудь готовую библиотеку из целой кучи существующих". Конечно, это нечестно - желающим пользоваться готовыми библиотеками не особенно нужны даже простые примеры работы с 1-Wire на низком уровне, а желающим разобраться недостаточно тривиальных примеров очевидного кода.

Подключение шины 1-Wire к COM-порту компьютера
Пример программы
Поиск ROM-кодов подключённых к 1-Wire шине устройств
Проблема локализации устройств



Подключение шины 1-Wire к COM-порту компьютера

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

Преобразователь интерфейса COM - 1-Wire не просто пример применения микроконтроллеров, но и в действительности полезное устройство. С его помощью возможно подключение к компьютеру множества датчиков для контроля за объектами с целью сбора и хранения данных, управления технологическими процессами в тех случаях, когда возможностей микроконтроллера оказывается недостаточно. Например, можно разместить датчики температуры по всем комнатам квартиры, а компьютер использовать как сервер, с помощью которого через Internet можно посмотреть, тепло ли дома, или может он уже в огне? Dallas Semiconductor выпускает с интерфейсом 1-Wire не только датчики температуры, но и другие устройства, например цифровые ключи. Цифровые ключи могут использоваться как ключи для цифровых замков или для получения прав на доступ в программах на компьютере. Цифровые замки в настоящее время очень распространены, практически в каждом подъезде установлен домофон, позволяющий открывать дверь с помощью ключа-таблетки, имеющего именно интерфейс 1-Wire.

Аппаратная реализация нашего преобразователя очень простая.

Схема переходника COM - 1-Wire

Как и в предыдущих примерах, здесь используется оценочная плата STM32VLDISCOVERY с ARM Cortex-M3 микроконтроллером STM32F100RBT6B. В качестве преобразователя уровней для подключения USART микроконтроллера к COM-порту, используется схема гальванической развязки, подробно описанная в одной из предыдущих статей: "UART и USART. COM-порт. Часть 1".

Взаимодействие компьютера и шины 1-Wire здесь реализовано следующим образом. Компьютер, как ведущее устройство, подключённое к 1-Wire шине является инициатором любой активности в шине. Для генерации сигналов сброса, тайм-слотов записи и чтения, компьютер посылает преобразователю команды через COM-порт. Преобразователь интерфейса дешифрует полученную команду, выполняет необходимые действия с шиной 1-Wire и отправляет компьютеру ответ о результатах выполнения команды.

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

Пример программы

Скачать исходный код, проект для компьютера

Скачать исходный код, проект для микроконтроллера

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

Для взаимодействия компьютера с 1-Wire шиной определён класс Com_1WireBridge. Объекты класса позволяют с помощью своих методов выполнять все необходимые действия: сброс; запись битов и байтов; чтение битов и байтов. При вызове соответствующих методов, прозрачно для пользователя, происходит формирование соответствующих команд, которые передаются через COM-порт и управляют преобразователем интерфейса.

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

class Com_1WireBridge
{
private:
    Com com;
public:
    // Открыть используемый для подключения моста COM-порт и настроить
    // его конфигурацию в соответствии с заданными параметрами.
    void open(unsigned char port_num, DWORD baud_rate, BYTE byte_size=8, BYTE parity=NOPARITY, BYTE stop_bits=ONESTOPBIT);

    // Закрыть COM-порт.
    void close();

    // Отправить байт с низкоуровневыми командами управления мостом и
    // вернуть полученный ответ.
    // В случае тайм-аута генерируется исключение.
    // Обычно нет необходимости использовать эту функцию, так как
    // есть более удобные функции для более высокоуровневого управления 1-Wire.
    unsigned char send_com_cmd(unsigned char cmd);
    
    // Инициализировать ведомые устройства на 1-Wire шине;
    // возвращает true, если получен сигнал присутствия.
    bool reset();

    // Генерирует слот записи на шине 1-Wire.
    void slot_w(bool d);

    // Генерирует слот чтения на шине 1-Wire,
    // возвращает прочитанный бит.
    bool slot_r();

    // Считывает с шины и возвращает два бита.
    char receive_2bits();

    // Запись в шину байта.
    void send_byte(char d);

    // Запись в шину 64-битного целого, может использоваться
    // для передачи ROM-кода.
    void send_rom(uint64_t rom);

    // Сформировать слот записи бита d и включить сильное подтягивание шины.
    void slot_w_and_strong_pullup(bool d);

    // Отправить байт и включить сильное подтягивание шины.
    void send_byte_and_strong_pullup(char d);
    
    // Отключить сильное подтягивание шины.
    void disable_strong_pullup();

    // Прочитать байт с шины.
    char receive_byte();
};

Программа для микроконтроллера не содержит ничего нового, здесь используется код из предыдущих статей - осуществляется приём/передача данных через USART и используется программно реализованный 1-Wire интерфейс. Для взаимодействия с 1-Wire определён класс Port1Wire. В программе можно создать несколько объектов-экземпляров класса для независимой работы с несколькими 1-Wire шинами.

Байты, получаемые от COM-порта компьютера и содержащие команды для переходника, декодируются обработчиком прерывания от USART, после чего вызываются соответствующие методы объекта типа Port1Wire.

// Открытые методы.

class Port1Wire
{
private:
    // *****************************************
public:
    // Конструктору требуется передать аргументы - 
    // порт GPIO и индекс разряда в пределах порта, используемый
    // для подключения шины 1-Wire.
    // Объект может быть сконструирован до включения тактового сигнала
    // используемого GPIO, но перед началом обмена данными, тактовый сигнал 
    // должен быть включён и должен быть вызван метод pin_config().
    Port1Wire(GPIO_TypeDef *_port, uint32_t _pin);

    // Сконфигурировать вывод микроконтроллера, используемый для
    // подключения 1-Wire шины перед началом обмена данными.
    // Перед вызовом функции должно быть включено тактирование
    // используемого порта GPIO микроконтроллера.
    void pin_config();

    // Отключить сильное подтягивание шины 1-Wire.
    inline void disable_strong_pullup();

    // Инициализация: сброс и проверка присутствия устройств на шине.
    // Возвращает true, если на шине есть готовые к работе 
    // ведомые устройства.
    bool reset();

    // Запись бита + формирование интервала восстановления.
    void slot_w(bool bit);

    // Запись бита + включение сильного подтягивания +
    // формирование интервала восстановления.
    void slot_w_and_strong_pullup(bool bit);

    // Сформировать слот чтения бита на шине;
    // возвращает false, если считан бит 0 и
    // возвращает true, если считан бит 1.
    bool slot_r();

    // Запись байта в шину.
    void send_byte(uint8_t b);

    // Отправить байт и включить сильное подтягивание.
    void send_byte_and_strong_pullup(uint8_t b);

    // Считать байт с шины.
    uint8_t receive_byte();
};

Поиск ROM-кодов подключённых к 1-Wire шине устройств

В статье "Измерение температуры. Аналоговые и цифровые датчики. Цифровой датчик DS18B20" уже рассказывалось об используемом шиной 1-Wire протоколе, наборе команд и о принципе определения ROM-кодов всех устройств, подключённых к шине с помощью ROM-команды SEARCH ROM (0xF0).

Фрагмент блок-схемы из спецификации на устройство DS18B20, приведённый ниже иллюстрирует процесс.

Блок-схема выполнения команды SEARCH ROM

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

Все устройства подключены к шине по схеме с открытым стоком, поэтому шина реализует так называемую схему "монтажное И". Это означает, что если хотя бы одно устройство, подключённое к шине, на своём выходе установит уровень логического 0, то уровень 0 будет установлен на всей шине. А для того чтобы на шине установился уровень логической 1 (под действием подтягивающего резистора), на выходах всех устройств должен быть установлен уровень 1, что и соответствует логике элемента И.

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

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

В случае одновременного ответа нескольких ведомых устройств, когда некоторые устройства передают бит 1 и хотя бы одно - бит 0, за счёт свойств схемы "монтажное И", ведущим устройством будет считано значение 0. Такое событие называют коллизией.

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

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

Мастер для изучения очередного бита ai ROM-кода производит два считывания шины (генерирует 2 тайм-слота чтения). Он ожидает считать бит ai и его отрицание ~ai, после чего должен записать в шину значение ai. Когда чтение шины происходит без коллизий, мастер считывает сначала бит 0, затем 1 и пишет в шину 0 или наоборот, получает сначала 1, затем 0 и пишет в шину 1. После этого происходит переход к следующему биту, и так до конца ROM-кода или до возникновения коллизии.

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

В случае коллизии какие-то устройства ответят сначала битом 0, затем битом 1, а другие наоборот, сначала передадут бит 1, а затем бит 0. Как сказано выше, за счёт свойств схемы с отрытым стоком, передача бита 0 "поглощает" передачу 1. В результате мастером будет считано два нулевых бита подряд. Это говорит ему о том, что произошла коллизия. Далее мастер делает выбор, какой бит передать в ответ - 0 или 1. Передав 0, мы переводим в ждущий режим ту группу устройств, которая содержит в данном бите ROM-кода значение 1 и наоборот. Каждая коллизия и каждый выбор будут сокращать количество устройств, остающихся активными, и дойдя до старшего бита, мы получим ROM-код одного из устройств.

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

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

Проблема локализации устройств

К одной шине 1-Wire может быть подключено множество устройств, каждое из которых имеет уникальный ROM-код. С помощью команды SEARCH ROM мы можем определить ROM-код каждого устройства и с помощью команды MATCH ROM выбрать то устройство, с которому хотим отправить функциональную команду.

1-Wire, шинная топология подключения

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

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

1-Wire, звездообразная топология подключения устройств

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

Также можно воспользоваться возможностью применения на усмотрение пользователя хранимых в EEPROM однобайтных ячеек датчика температуры TH и TL. С помощью отдельного программатора, например с помощью описанного здесь переходника COM - 1-Wire и простейшей программы, можно записывать в эти ячейки необходимую служебную информацию, допустим тот же самый порядковый номер, определяющий будущее расположение датчика.

author: hamper; date: 2016-02-24
  @Mail.ru