Опубликовано

Шина SPI и библиотеки сторонних разработчиков

По материалам книги Т.Иго «Изучаем Arduino: инструменты и методы технического волшебства. 2-е изд.: пер. с англ.»  (Глава 11. Шина SPI и библиотеки сторонних разработчиков)

Изучаем Arduino: инструменты и методы технического волшебства. 2-е изд.

Исходный код, видеоуроки и прочие электронные ресурсы для этой главы можно загрузить с веб-страницы https://www.exploringarduino.com/content2/ch11.

Исходный код для проектов этой главы можно также загрузить на вкладке Downloads веб-страницы издательства Wiley для этой книги: https://www.wiley.com/go/exploringarduino2e.


Мы уже познакомились с двумя основными методами цифровой передачи данных, поддерживаемыми платформой Arduino: шиной последовательного интерфейса УАПП (RS-232) и шиной I2C. В этой главе мы рассмотрим третий метод цифровой связи, поддерживаемый Arduino: шиной SPI[1].

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


Примечание

В первом издании этой книги для демонстрации принципов работы шины SPI использовалась микросхема цифрового потенциометра MCP4231, поддерживающая возможности SPI. В последнее время эти микросхемы трудно найти и, кроме того, проекты на их основе не особенно стимулируют умственные способности, по сравнению с применением акселерометра. Но если вы хотите узнать, как реализовать сопряжение цифрового потенциометра с платой Arduino, это можно сделать, просмотрев учебный фильм на эту тему по ссылке blum.fyi/spi-digipot-tutorial.

Общие сведения о шине SPI

Шина SPI была разработана компанией Motorola для реализации полнодуплексной последовательной связи между ведущим устройством и одним или несколькими ведомыми устройствами. Поскольку для протокола SPI нет формального стандарта, часто можно встретить SPI-устройства, работающие немного по-разному. Например, количество передаваемых битов может быть другим, или линия выбора ведомого устройства может не использоваться. В этой главе мы сделаем акцент на сопряжении платы Arduino с устройствами, реализующими наиболее распространенные SPI-интерфейсы. Эти устройства поддерживаются средой разработки Arduino IDE и библиотеками сторонних разработчиков, которые мы будем использовать.

Внимание!

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

Шина SPI может работать в четырех основных режимах, выбор конкретного из которых зависит от требований конкретного устройства. Устройства SPI работают в синхронном режиме, т. е. передача данных синхронизируется сигналом тактирования, подаваемым на линию SCLK. Данные могут вводиться в ведомое устройство или по положительному, или по отрицательному перепаду сигнала тактирования (называющемуся фазой сигнала тактирования), а уровень по умолчанию линии сигнала тактирования SCLK (называющийся полярностью сигнала тактирования) можно установить или высоким или низким.

Таким образом, две опции для фазы сигнала тактирования и два варианта его полярности определяют четыре способа конфигурации шины SPI. В таблице 11.1 приведены все четыре возможные комбинации фазы и полярности тактового сигнала и соответствующие режимы в библиотеке SPI языка Arduino.

Таблица 11.1. Режимы связи шины SPI

Режим SPI Полярность сигнала тактирования Фаза сигнала тактирования
Режим 0 Низкий уровень при простое Захват данных по положительному перепаду сигнала тактирования
Режим 1 Низкий уровень при простое Захват данных по отрицательному перепаду сигнала тактирования
Режим 2 Высокий уровень при простое Захват данных по отрицательному перепаду сигнала тактирования
Режим 3 Высокий уровень при простое Захват данных по положительному перепаду сигнала тактирования

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

Подключение устройств SPI

Конфигурация системы обмена данными по шине SPI сравнительно проста. Для взаимодействия между ведущим устройством и всеми ведомыми устройствами предусмотрены три линии:

  • SCLK (serial clock) — последовательный тактовый сигнал.
  • MOSI (master out, slave in) — выход ведущего, вход ведомого.
  • MISO (master in, slave out) — вход ведущего, выход ведомого.

Кроме этих линий, для каждого ведомого устройства требуется отдельная линия для его выбора. Эта линия называется SS (slave select — выбор ведомого). Таким образом, общее число линий и контактов ввода-вывода ведущего устройства всегда будет равно 3 + n, где n обозначает число ведомых устройств.

На рис. 11.1 показан пример системы связи по шине SPI с двумя ведомыми устройствами.

image1

Рис. 11.1. Стандартная схема организации связи по шине SPI (Рисунок создан в программе EAGLE)

Конфигурация интерфейса SPI

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

Таблица 11.2. Линии шины SPI

Линия шины SPI Описание
MOSI(выход ведущего, вход ведомого) Передача последовательных данных от ведущего устройства ведомому устройству
MISO(вход ведущего, выход ведомого) Передача последовательных данных от ведомого устройства ведущему устройству
SCLK(последовательный тактовый сигнал) Сигнал, синхронизирующий последовательные данные с принимающим устройством, чтобы оно знало, когда считывать входные данные
SS(выбор ведомого) Линия для выбора ведомого устройства. Установка на этой линии сигнала низкого уровня означает выбор данного ведомого устройства для обмена данными с ведущим устройством. Как правило, одновременно следует активировать только одну линию выбора ведомого устройства

В отличие от шины I2C для линий шины SPI подтягивающие резисторы не требуются, поскольку контакты ввода-вывода устройств сконфигурированы для работы в двухтактном режиме, а не в режиме открытого стока. Связь осуществляется в полнодуплексном режиме (т. е. она полностью двунаправленная). Чтобы подключить SPI-устройство к плате Arduino, нужно просто соединить соответствующие контакты MOSI, MISO, SCLK и SS обоих устройств. При этом следует иметь в виду уровни напряжения питания и логических сигналов. Если используется плата Arduino с питанием 5 В (как Arduino Uno), то подключаемое к ней ведомое SPI-устройство также должно поддерживать работу с логическими уровнями величиной 5 В.

О НАЗВАНИЯХ ЛИНИЙ

Поскольку протокол SPI официально не стандартизован, некоторые производители устройств SPI могут по-разному именовать линии связи для своих устройств. Например, линия SS (slave select — выбор ведомого) иногда называется CS (chip select — выбор микросхемы), линия SCLK (serial clock — последовательный тактовый сигнал) может называться просто CLK (clock — тактовый сигнал) или SCK (вариант SCLK), а контакты MOSI и MISO ведомых устройств иногда обозначаются как SDI (serial data in — вход последовательных данных) и SDO (serial data out —выход последовательных данных). В этой главе употребляются все разновидности наименований сигналов, согласно их применению производителями соответствующих устройств.

Протокол передачи данных SPI

Передача данных по протоколу SPI синхронизуется с помощью сигнала тактирования и управляется посредством линии SS для выбора ведомого устройства. Поскольку все устройства на шине SPI подключены к одним и тем же линиям MOSI, MISO и SCLK, посылаемые ведущим устройством сигналы видимы всем ведомым устройствам. Выбор устройства, которое должно реагировать на эти сигналы, осуществляется с помощью соответствующей линии SS. Важно отметить, что это означает необходимость следить за тем, чтобы в любой разрабатываемой программе низкий (активный) уровень одновременно подавался только на одну линию SS выбора ведомого устройства. Базовая процедура связи с устройством SPI следующая:

  1. Подаем сигнал низкого уровня на линию SS ведомого устройства, с которым необходимо выполнить обмен данными.
  2. Подаем на линию тактирования прямоугольный сигнал с частотой меньшей или равной скорости обмена в бодах, поддерживаемой ведомым устройством.
  3. В каждом цикле сигнала тактирования передаем один бит по линии MOSI и принимаем один бит по линии MISO.
  4. Продолжаем до тех пор, пока не будут переданы или приняты все данные, после чего снимаем сигнал тактирования с линии SCLK.
  5. Снова устанавливаем на линии SS сигнал высокого уровня.

Сравнительные характеристики протоколов SPI, I2C и UART

Многие устройства, включая акселерометры, цифровые потенциометры и дисплеи поддерживают как протокол SPI, так и протокол I2C. (В частности, акселерометр, с которым мы будем работать далее в этой главе, поддерживает оба протокола.) Это означает, среди прочего, что если вы хотите организовать взаимодействие между несколькими платами Arduino, то для этого можно разработать программу, которая будет работать с шиной SPI, I2C или RS-232 (UART). Но как решить, какой из протоколов выбрать? В таблице 11.3 приведены сравнительные характеристики этих трех протоколов, включая их преимущества и недостатки. В конечном итоге, решение будет зависеть от того, какой из них, по вашему мнению, легче всего реализовать и который лучше всего отвечает требованиям вашей задачи.

Таблица 11.3. Сравнительные характеристики протоколов SPI, I2C и UART

SPI I2C UART (RS-232)
Обеспечивает наивысшую скорость передачи данных Максимальная скорость передачи данных сильно зависит от физических свойств шины: длины линий, количества подключенных к ней устройств, значений сопротивлений повышающих резисторов и т.п. Скорость передачи в бодах должна быть согласована между обоими участвующими в обмене устройствами до начала обмена
В целом, с этим протоколом легче работать, чем с протоколом I2C. Требует всего лишь две линии связи Практически не требует никаких протокольных накладных расходов, в результате чего легко поддается реализации
Не требует повышающих резисторов для линий связи Поддерживает взаимодействие устройств с разными уровнями напряжения питания Нет предопределенных ведущего и ведомого устройств. Протокол определяется разработчиком
Количество ведомых устройств ограничено только количеством доступных контактов SS на ведущем устройстве Количество ведомых устройств ограничено доступностью микросхем с конкретных адресом ведущего устройства Поддержку нескольких ведомых устройств трудно реализовать
Поддерживает аппаратное и программное обеспечение платформы Arduino Поддерживает аппаратное и программное обеспечение платформы Arduino Поддерживает аппаратное и программное обеспечение платформы Arduino
  1. Англ. Serial Peripheral Interface — последовательный синхронный периферийный интерфейс — Пер.
Опубликовано

Шина I2C

Исходный код и прочие электронные ресурсы:

Исходный код, видеоуроки и прочие электронные ресурсы для этой главы можно загрузить с веб-страницы https://www.exploringarduino.com/content2/ch10.

Исходный код для проектов этой главы можно также загрузить на вкладке Downloads веб-страницы издательства Wiley для этой книги: https://www.wiley.com/go/exploringarduino2e.


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

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


Примечание

На веб-странице электронных ресурсов книги для этой главы (https://www.exploringarduino.com/content2/ch10) можно просмотреть учебный видеофильм о шине I2C.

История создания протокола I2C

Работу коммуникационного протокола намного легче понять, если знать, как он эволюционировал с течением времени. Протокол I2C был разработан компанией Philips Semiconductors в начале 80-х годов прошлого столетия для обеспечения сравнительно низкоскоростной связи между разными микросхемами. К 90-м годам прошлого столетия протокол был стандартизирован, и другие компании начали использовать его, выпуская совместимые с ним микросхемы. Этот протокол часто называют двухпроводным протоколом, поскольку для обмена данными в нем предусмотрено всего лишь два провода: для данных и для сигнала тактирования. Хотя не все устройства законно используют для связи двухпроводный протокол (поскольку их производители не уплатили за это), обычно их все равно называют I2C-устройствами. Можно провести аналогию с копировальными аппаратами, которые называются ксероксами, хотя они не выпускаются компаний Xerox, которая была первой, создавшей копировальный аппарат электрографического типа с порошковым красящим элементом под этим торговым названием. Поэтому, если для устройства указывается, что оно использует двухпроводный протокол связи, то можно быть в большой степени уверенным, что этот протокол работает, как описано в этой главе.

Вам, возможно, также встретятся устройства, применяющие другой двухпроводный протокол, называющийся SMBus (System Management Bus — системная управляющая шина). Этот протокол разработан компаниями Intel и Duracell на основе протокола I2C и очень похож на него. Но в нем заданы немного другие пределы электрических сигналов, определен алгоритм обнаружения ошибок, а также реализована явная поддержка необязательной сигнальной линии для прерываний, позволяющая ведомым устройствам уведомлять ведущее об определенных событиях. Обычно, устройства SMBus и I2C можно без проблем одновременно подключать к одной шине, если четко соблюдать требования, изложенные в справочных листках.

Схема подключения устройств I2C

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

image1

Рис. 10.1. Стандартная схема организации связи через шину I2C (Рисунок создан в программе EAGLE)

Взаимодействие и идентификация устройств

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

Все команды и запросы, отправляемые ведущим устройством, могут приниматься всеми ведомыми устройствами шины. Поэтому необходимо каким-либо образом обеспечить связь только с тем устройством, которому предназначены посылаемые данные. Эта задача решается присвоением каждому ведомому устройству уникального 7-разрядного адреса или идентификационного номера (ID-номер). Когда ведущее устройство инициирует сеанс связи, оно передает ID-номер требуемого ведомого устройства. Ведомые устройства реагируют на данные в шине только тогда, когда эти данные обозначены их ID-номером. Некоторые устройства I2C имеют настраиваемый адрес, тогда как другим присваивается постоянный адрес при изготовлении. Таким образом, чтобы подключить к шине несколько экземпляров устройства одного типа, необходимо, чтобы каждое из них имело уникальный ID-номер.

Поэтому, например, датчики температуры выпускаются с разными заранее запрограммированными адресами шины I2C, поскольку обычно к одной шине необходимо подключить несколько таких датчиков. Для экспериментов этой главы мы будем применять датчик температуры линейки TC74. Из справочного листка на этот датчик можно увидеть, что он предлагается с несколькими разными адресами. (рис. 10.2.) Для описанных далее экспериментов мы возьмем датчик температуры TC74A0-5.0VAT с адресом 1001000. Данный датчик является версией этой микросхемы с питанием 5 В и корпусом типа TO-220.

image2

Рис. 10.2. Возможные адреса для датчика температуры TC74 (Источник: © Microchip Technology Incorporated. Репродукция с разрешения)

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

Другие микросхемы I2C, например AD7414 and AD7415 (другой I2C цифровой датчик температуры, выпускаемый компанией Analog Devices), оснащаются контактами выбора адреса (AS — address select), посредством которых им можно присвоить определенный I2C-адрес. На рис. 10.3 приводится фрагмент справочного листка для микросхемы датчика AD7414, на котором показана ее цоколевка, а также таблица присвоения ей адреса I2C.

image3

Рис. 10.3. Настройка адреса I2C для микросхемы датчика температуры AD7414 (Источник: Авторские права принадлежат компании Analog Devices, Inc. с 2019 г. Все права сохраняются)

Как можно видеть на рис. 10.3, предлагается четыре варианта микросхемы AD7414: два с контактом выбора адреса AS и два без такого контакта. Для микросхем с контактом выбора адреса AS можно задать один из трех адресов, подключив этот контакт к шине питания, шине земли или оставив его неподключенным.

РЕКОМЕНДАЦИИ ПО ВЫБОРУ КОМПОНЕНТОВ ДЛЯ РАЗРАБОТЧИКА УСТРОЙСТВ

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

Если вы планируете изготовить большое количество этих печатных плат, тогда большую роль в выборе компонентов может сыграть такой фактор, как экономия затрат. Стоимость микросхемы AD7414 при покупке одного экземпляра составляет $2,59, но при покупке партии в 3000 шт. уменьшается до $1,16 за экземпляр. Если вы планируете изготовить несколько тысяч таких плат, то можете сэкономить большую сумму денег, установив на каждую плату три экземпляра одного устройства, а не три разных устройства[1].

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

Аппаратные требования и повышающие резисторы

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

Опубликовано

Последовательный обмен данными с использованием двух протоколов последовательной связи: TTL Serial и USB

По материалам книги Т.Иго «Умные вещи: Arduino, датчики и сети для связи устройств: Пер. с англ. 3-е изд.»  (глава 2 «Простейшая сеть»)

Умные вещи: Arduino

Устанавливаем соединение: нижние уровни

Мы уже знакомы с одним примером последовательного обмена данными — между микроконтроллером и персональным компьютером. В частности, в главе 1 мы подключили микроконтроллерный модуль к персональному компьютеру через порт USB. Это подключение является примером асинхронного последовательного обмена данными с использованием двух протоколов последовательной связи: TTL Serial и USB.

Первый из них — это протокол, понимаемый микроконтроллером, и называется он последовательный ТТЛ (TTL[1] Serial). Этот протокол можно разделить на следующие концептуальные уровни:

  • Физический. Определяет контакты, используемые контроллером для обмена данными. В модуле Arduino данные принимаются на контакт, обозначенный RX (от Receive, прием), а передаются с контакта, обозначенного TX (от Transmit, передача).
  • Электрический. Определяет напряжения для представления битов данных. В некоторых микроконтроллерах применяется напряжение 3,3 В, в других — 5 В.
  • Логический. Высокий уровень напряжения (3,3 или 5 В) представляет логическое значение 1, а низкий (0 В) — логическое значение 0.
  • Уровень данных. Обмен данными обычно осуществляется со скоростью 9600 битов в секунду. Для представления одного символа требуется один байт, который содержит 8 битов данных, а также стартовый и стоповый биты (которые мы никогда не будем использовать).
  • Уровень приложений. На этом уровне мы отправляем один байт от ПК на микроконтроллер, который обрабатывает его и возвращает один байт на ПК.

Но это еще не все. Импульсы напряжения не идут на ПК напрямую. Сначала они поступают на TTL/USB микросхему на плате, которая преобразовывает последовательные TTL-сигналы в последовательные USB-сигналы. На некоторых микроконтроллерных платах — например, на Arduino Uno, преобразователь USB сигналов в сигналы ТТЛ реализован в виде отдельной микросхемы. На других же — например, на MKR1000 и Arduino 101, эта функциональность встроена в микросхему микроконтроллера.

Обработка преобразованных в формат USB сигналов осуществляется с использованием соответствующего протокола USB[2], который во многом отличается от протокола последовательного обмена TTL. Он разбивается на следующие концептуальные уровни:

  • Физический. Шина USB состоит из двух проводов для передачи данных: Data+ и Data– и двух проводов питания (+5 В и общего).
  • Электрический. Сигнал на линии Data– всегда противоположен сигналу на линии Data+, в результате чего сумма напряжений этих сигналов всегда равна нулю. Эта особенность используется приемником для проверки на наличие ошибок электрического сигнала — для этого он складывает напряжения обеих этих линий. Если полученная сумма не равна нулю, приемник отбрасывает такой сигнал.
  • Логический. Логическое значение 1 представляется сигналом напряжения +5 В (на линии Data+) или –5 В (на линии Data–), а логическое значение 0 — сигналом напряжения 0 В.
  • Уровень данных. Уровень данных модели протокола USB более сложный, чем соответствующий уровень протокола последовательного обмена ТТЛ. В USB скорость обмена данными может достигать 480 мегабит в секунду. Один символ представляется одним байтом, который содержит 8 битов данных, а также стартовый и стоповый биты. Несколько устройств USB под управлением ПК могут использовать для обмена данными одну и ту же пару проводов (набор проводов для обмена сигналами называется шиной). Поскольку к одной шине может быть подсоединено несколько устройств, операционная система присваивает каждому из этих устройств однозначный адрес и обеспечивает обмен данными между каждым подсоединенным к шине устройством и его соответствующим приложением на компьютере.
  • Уровень приложений. На уровне приложения преобразователь USB/TTL-Serial на плате Arduino отправляет операционной системе компьютера несколько байтов, чтобы идентифицировать себя. Операционная система использует эти байты для того, чтобы сопоставить плату с программой ее драйвера, который другие программы могут использовать для обмена данными с этим устройством.

Все это управление прозрачно для пользователя, так как контроллер USB компьютера передает ему только те байты, которые предназначены для него. Микросхема преобразователя USB/TTL-Serial на плате Arduino представляет себя операционной системе компьютера в качестве последовательного порта и отправляет данные через разъем USB с выбранной пользователем скоростью (9600 битов в секунду — как в примере из главы 1).

 

Кабель-переходник USB/TTL-Serial компании FTDI

 

Рис. 2.4. Кабель-переходник USB/TTL-Serial компании FTDI

Распиновка разъема TTL

Рис. 2.5. Распиновка разъема TTL кабеля USB/TTL-Serial компании FTDI. Кроме линий передачи, приема и питания он также имеет линии для аппаратного управления обменом данных: RTS (Request-to-send, запрос на передачу) и CTS (Clear-to-send, готовность к передаче). Некоторые устройства используют эти линии для управления потоком последовательных данных

Есть и еще один протокол — если вы используете микроконтроллерный модуль BASIC Stamp или другой микроконтроллерный модуль с интерфейсом иным, чем USB, он, скорее всего, оснащен 9-контактным разъемом для подключения к компьютеру или к адаптеру USB/RS-232 (распиновка разъемов USB и RS-232 показана на рис. 2.6). Этот разъем называется DB-9 или D-sub-9 и является стандартным разъемом для другого последовательного протокола: RS-232. Протокол RS-232 был стандартом для последовательного интерфейса компьютеров до протокола USB и все еще встречается на некоторых специализированных периферийных устройствах. Этот протокол состоит из следующих концептуальных уровней:

  • Физический. Данные в разъеме RS-232компьютера принимаются на контакт 2, а передаются с контакта 3. Контакт 5 — «земля».
  • Электрический. Данные в стандарте RS-232 передаются двумя уровнями напряжения: от +3 В до +25 В и от –3 В до –25 В.
  • Логический. Высокий уровень напряжения (от +3 В до +25 В) представляет логическое значение 0, а низкий (от –3 В до –25 В) — логическое значение 1. Как можно видеть, эта схема построена на основе отрицательной (или инвертированной) логики.
  • Уровень данных. Такой же, как и в протоколе TTL, — 8-битовый байт данных с дополнительными стартовым и стоповымбитами.

Распиновка разъемов: USB и RS-232

Рис. 2.6. Распиновка разъемов: USB и RS-232

 

Спрашивается, как же подключать некоторые микроконтроллеры — например, BASIC Stamp, непосредственно к последовательному порту RS-232? Поскольку микроконтроллеры обычно не могут создавать отрицательные напряжения, для преобразования выходных сигналов ТТЛ микроконтроллера в уровни RS-232 обычно используется отдельная специальная микросхема. Протокол RS-232 намного проще, чем протокол USB, но, к сожалению, он, по большому счету, сильно устарел. Большинство современных микроконтроллеров оснащены встроенным преобразователем USB/TTL-Serial.

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

Преобразователи USB/Serial

Большинство современных электронных модулей, с которыми вам придется иметь дело, будут, скорей всего, оснащены каким-либо последовательным интерфейсом для взаимодействия с микроконтроллерами. Самым распространенным из таких интерфейсов является последовательный TTL-интерфейс — TTL-Serial. Например, большинство модулей системы GPS[5] (с одним из которых мы познакомимся в главе 8) оснащены интерфейсом TTL-Serial.  Для любого, кто интересуется созданием современных электронных устройств, преобразователь USB/TTL-Serial станет одним из самых необходимых инструментов.

На рынке доступен ряд микросхем преобразователя USB/Serial. Одной из наиболее популярных является микросхема FT232RL, изготавливаемая уже упомянутой ранее компанией FTDI. Но основе этой микросхемы компания делает кабель-переходник, другие компании также используют эту микросхему для изготовления плат-преобразователей. Кабель-переходник компании FTDI (см. рис. 2.4) приобрел такую популярность, что его распиновка (см. рис. 2.5) была принята в качестве де-факто стандарта на рынке любительской электроники  и используется во многих устройствах.

Кроме кабеля-преобразователя компании FTDI, преобразовательные платы изготавливают такие компании как Adafruit, SparkFun, Parallax и ряд других. Микросхемой FT232RL также оснащаются многие устройства, включая адаптеры XBee компании Digi и платы-клоны Arduino RedBoard компании SparkFun.

Эта микросхема удобна тем, что она может обрабатывать последовательные TTL-сигналы разных напряжений:  5 В и 3,3 В. Компания SparkFun изготавливает отдельные версии плат для каждого напряжения,  а у платы FTDI Friend компании Adafruit на тыльной стороне предусмотрен ряд перемычек, перепаивая которые можно менять рабочее напряжение контактов для приема и передачи последовательных сигналов. Кроме того, эта плата также способна работать с уровнями напряжения сигналов RS-232. Для работы с RS-232 предназначена  и адаптерная плата компании Parallax, оснащенная к тому же разъемом DB-9.

Использование адаптера USB/TTL-Serial не представляет собой ничего сложного. Контакт передачи (TX) этого адаптера подсоединяется к контакту приема (RX) устройства и наоборот. Общий («земляной») контакт платы подключается к соответствующему контакту устройства, а при питании устройства от адаптерной платы контакт питания VCC платы подключается к контакту питания устройства. Прежде чем запитывать устройство от адаптера, необходимо убедиться в том, что устройство может работать на уровне напряжения, подаваемого адаптером. Напряжение питания большинства адаптеров USB/TTL-Serial составляет 5 В, что может повредить устройства с питанием 3,3 В. В главе 1 мы узнали, как с помощью адаптера USB/TTL-Serial компании FTDI подключиться через монитор порта к плате Raspberry Pi (см. рис. 1.17). Но в том случае плата микроконтроллера не запитывалась от адаптерной платы.

Чтобы использовать с компьютером любой из адаптеров USB/Serial, на компьютер нужно установить драйверы микросхемы этого адаптера. Качество работы адаптера USB/TTL-Serial во многом зависит от качества его драйвера. Драйверы более дешевых адаптеров обычно совместимы с более узким диапазоном платформ. Поэтому имеет смысл немного переплатить, но приобрести устройство с доступными, качественными и многоплатформенными драйверами. В этом отношении особенно выделяется компания FTDI —драйверы от этой компании всегда вовремя обновляются для поддержки текущих версий Windows, macOS и различных дистрибутивов Linux.

Но кроме компании FTDI, адаптеры USB/TTL-Serial изготавливаются и другими компаниями —  например, компаниями Prolific (адаптер PL2303), Silicon Labs (адаптер CP2102), Jiangsu Heng Qin (адаптер CP340) и другими. Драйверы для упомянутых адаптерных плат этих компаний можно загрузить со следующих веб-сайтов:

  • ftdichip.com/FTDrivers.htm (FTDI);
  • silabs.com/products/mcu/Pages/USBtoUARTBridgeVCPDrivers.aspx (Silicon Labs);
  • prolific.com.tw/US/Show-Product.aspx?pcid=41 (Prolific);
  • wch.cn/download/CH341SER_ZIP.html (Jiangsu Heng Qin).

В плате Arduino Uno в качестве адаптера USB/TTL-Serial используется микроконтроллер общего назначения Atmel 16U2, запрограммированный под эту задачу. Для этого адаптера не требуются драйверы под macOS и Linux, а драйверы USB для Windows устанавливаются автоматически установщиком Windows. Исходный код адаптера USB/TTL-Serial для Arduino Uno можно загрузить из каталога hardware/arduino/avr/firmwares/atmegaxxu2 репозитория https://github.com/arduino, а дополнительную информацию о конструкциях устройств USB вы найдете на веб-сайте www.usb.org/developers/usbfaq.

При использовании адаптера USB/TTL-Serial для программирования микроконтроллера вам, вероятно, нужно будет также задействовать выводы CTS (clear-to-send, готовность к передаче) и RTS (request-to-send, запрос на передачу). Большинство микроконтроллеров, полагающихся на адаптеры USB/TTL-Serial, — такие, как адаптерная плата Huzzah! на микросхеме ESP8266 компании Adafruit или плата ESP8266 Thing компании SparkFun, оснащены контактами для этих выводов, так что вам не нужно беспокоиться об этом. Дополнительную информацию по использованию адаптеров USB/TTL-Serial для программирования микроконтроллеров ищите в руководстве по программированию вашей платы.

Использование платы Arduino в качестве адаптера USB/TTL-Serial

Если у вас нет под рукой отдельного адаптера USB/TTL-Serial, вместо него можно воспользоваться совместимой с Arduino платой, запрограммировав ее должным образом.

В частности, для этой цели подойдут платы MKR1000 или Arduino 101. Обе платы используют одинаковые процессоры, оснащенные встроенными средствами работы с USB, и последовательные порты этих плат, отображаемые в мониторе порта, подключены непосредственно к процессору. Для обращения к выводам TX (передача) и RX (прием) платы обычно используется объект Serial1. Далее приводится скетч для реализации этой задачи. В нем вывод передачи USB перенаправляется на вывод приема (RX) платы, а вывод приема USB — на вывод передачи (TX) платы. Таким образом, любая микроконтроллерная плата на микроконтроллере со встроенными средствами работы с USB превращается в адаптер USB/TTL-Serial.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void setup() {
 
// инициализируем оба последовательные подключения:
Serial.begin(9600);  // USB
 
Serial1.begin(9600); // TTL
}
 
 
 
void loop() {
 
// считываем RX TTL, отправляем на USB:
 
if (Serial1.available()) {
 
char c = Serial1.read();
 
Serial.write(c);
 
}
 
 
 
// считываем USB, отправляем на TX TTL:
 
if (Serial.available()) {
 
char c = Serial.read();
 
Serial1.write(c);
 
}
 
}

Микроконтроллеры более старых плат — например, Arduino Uno, не имеют встроенных средств для работы с USB. Поэтому, чтобы позволить таким платам взаимодействовать с компьютером через порт USB, они оснащаются отдельной микросхемой адаптера USB/TTL-Serial. Выход передачи (TX) такого адаптера подсоединен к контакту приема (RX) микроконтроллера и наоборот. Это означает, что здесь можно обойти микроконтроллер и напрямую использовать плату Arduino в качестве адаптера USB/TTL-Serial. Для этого в микроконтроллер нужно загрузить скетч, который ничего не делает:

1
2
3
void setup() {}
 
void loop() {}

Затем подсоединить требуемое последовательное устройство следующим образом  (обратите внимание: на первый взгляд может казаться, что подключение должно выполняться наоборот):

  • контакт приема внешнего устройства — к контакту RX (0) платы Arduino;
  • контакт передачи внешнего устройства — к контакту TX (1) платы Arduino.

Теперь наше устройство может обмениваться данными напрямую с адаптером USB/TTL-Serial платы Arduino, обходя микроконтроллер. Когда же снова нужно будет использовать микроконтроллер, просто отсоедините устройство и загрузите требуемый скетч.

 

 

[1] TTL, Transistor-Transistor Logic — транзисторно-транзисторная логика (ТТЛ).

[2] USB, Universal Serial Bus (protocol) — протокол универсальной последовательной шины.

[3] TTY, Teletype Unit — телетайпное устройство.

[4] CU, Сalling Unit — вызывающее устройство.

[5] GPS, Global Positioning System — система глобального позиционирования.[/vc_column_text]

USB — неисчерпаемый источник последовательных портов

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

Например, если к компьютеру подсоединить три модуля Arduino через USB-хаб, в операционной системе появится три новых последовательных порта. На машинах под Mac OS они будут отображаться примерно так:

/dev/cu.usbmodem1441

/dev/cu.usbmodem1461

/dev/cu.usbmodem1471

В системах POSIX, включая macOS, порты часто указываются дважды: один раз как /dev/tty.usbmodemXX и еще раз как /dev/cu.usbmodemXX. Эта особенность является пережитком эпохи телефонных модемов: порты TTY[3] служили для коммутации входящих звонков, а CU[4] — для исходящих. Для устройств USB/TTL-Serial, которые применяются в этой книге, тип используемого порта не имеет существенной важности.

На машинах под Windows эти порты будут отображаться, например, так: COM8, COM9, COM10.

Большинство современных микроконтроллерных плат оснащены встроенным модулем преобразователя USB/TTL-Serial. Для тех плат, которые не имеют встроенного преобразователя, на рынке предлагаются отдельные модули ценой порядка $15–20. Один из наиболее популярных таких преобразователей с разъемом для макетных плат, который удобно использовать для подсоединения устройств, оснащенных последовательным интерфейсом технологии TTL, выпускает компания FTDI (Future Technology Devices International), сайт которой находится по адресу www.ftdichip.com. Этот преобразователь можно прибрести в разделе макетных плат и кабелей магазинов фирм Maker SHED, SparkFun, Adafruit и многих других. Доступен он в двух версиях: 5 В и 3,3 В — любую из них можно использовать для всех проектов этой книги. Кабель-переходник USB/TTL-Serial компании FTDI показан на рис. 2.4, а распиновка его разъема TTL — на рис. 2.5.

[/vc_column][/vc_row]
Опубликовано

Уровни согласования взаимодействия устройств

По материалам книги Т.Иго «Умные вещи: Arduino, датчики и сети для связи устройств: Пер. с англ. 3-е изд.»  (глава 2 «Простейшая сеть»)

Умные вещи: Arduino

Самая простая сеть — это соединение двух объектов один к одному. В этой главе подробно рассматривается двусторонняя связь, и начнем мы с характеристик, которые нужно оговорить прежде всего. Мы познакомимся с некоторыми логистическими элементами сетевой связи: протоколами данных, управлением потоками и адресацией. Эти теоретические понятия мы применим на практике, создав два устройства, реализующих примеры использования последовательной связи между микроконтроллером и персональным компьютером. Мы также рассмотрим модемную связь и узнаем, как заменить кабель, соединяющий микроконтроллер и компьютер, на приемопередатчики беспроводной связи Bluetooth. Наконец, мы научимся программировать микроконтроллеры низкого уровня с тем, чтобы распределять вычислительные потребности наших проектов между разными процессорами.

Уровни согласования

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

  • Физический. Каким образом вводы и выводы каждого устройства соединяются с другими? Сколько необходимо соединений между двумя устройствами для возможности обмена сообщениями?
  • Электрический. Какие уровни напряжения использовать для представления битов данных? 5 вольт? 3,3 В? Какое-либо другое напряжение?
  • Логический. Какую схему логики использовать — положительную или отрицательную? Схема, при которой высокий уровень напряжения представляет логическую 1, а низкий — логический 0, называется положительной, а когда значения уровней инвертированы: высокий уровень напряжения представляет логический 0, а низкий — логическую 1, — отрицательной.
  • Уровень данных. Как осуществляется синхронизация битов? Сколько битов считывается за раз: 8, 9, 10 или больше? Обозначаются ли группы битов в начале и в конце специальными битами?
  • Уровень приложений. Как организовываются группы битов для создания сообщений? Каков порядок обмена сообщениями для того, чтобы что-то сделать?

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

Какой бы сложной ни была бы сеть, никогда не забывайте о том, что связь между электронными устройствами — это всего лишь электрические импульсы. Устройства, осуществляющие обмен данными по последовательному каналу, соединены между собой электрически. Посылающее устройство изменяет уровень напряжения на соединяющей линии через согласованные интервалы времени, и каждый такой интервал представляет собой один бит данных. Чтобы отправить значение 0 или 1 очередного бита, отправитель меняет уровень напряжения, а получатель определяет уровень полученного сигнала: высокий он или низкий.

Отправитель и получатель могут согласовывать скорость отправки битов двумя способами (рис. 2.3). Скорость асинхронного последовательного обмена данными согласовывается между обеими сторонами обмена и синхронизируется (иногда говорят: тактируется) отправителем и получателем независимо друг от друга. А скорость синхронного последовательного обмена данными управляется отправителем, который подает постоянный сигнал синхронизации (тактирования) на отдельную линию (на рис. 2.3 показаны два интерфейса синхронного последовательного обмена: интерфейс SPI и интерфейс I2C). Синхронный последовательный обмен данными в основном применяется для связи между интегрированными схемами (например, между процессором компьютера и его микросхемами памяти). В этой главе рассматривается только асинхронный последовательный обмен данными, так как именно этот тип последовательной связи лежит в основе сетей, которым посвящена эта книга: от Ethernet-соединений по проводам до беспроводной радиосвязи.

Асинхронный обмен данными

Асинхронный обмен данными: каждое устройство использует свой  собственный генератор тактовых (синхронизирующих) сигналов, обмен данными осуществляется с заранее согласованной скоростью

Синхронный обмен данными (интерфейс SPI, Serial Peripheral Interface)

Синхронный обмен данными (интерфейс SPI, Serial Peripheral Interface): ведущее устройство подает  сигнал тактирования на ведомое устройство и инициирует обмен, подавая сигнал выбора схемы. Обмен данными происходит по смене уровня напряжения сигнала тактирования на обратное

Синхронный обмен данными (интерфейс I2C)

Синхронный обмен данными (интерфейс I2C): ведущее устройство подает сигнал тактирования на ведомое устройство, выбирая ведомое по его адресу. Обмен данными происходит по смене уровня напряжения сигнала тактирования на обратное

Рис. 2.3. Типы последовательной связи