- Подписка на печатную версию:
- Подписка на электронную версию:
- Подшивки старых номеров журнала (печатные версии)
LXF141:Intefaces
Материал из Linuxformat.
- Оборудование Налаживаем связь вашего компьютера с внешним миром
Содержание |
Интерфейсы: Подключим ВСЕ!
- Андрей Боровский расскажет, как подключить к современному компьютеру любое устройство, снабженное проводом (утюги не предлагать).
В прошлый раз мы сумели заставить простое устройство USB делать то, что нужно нам (а не то, что задумал производитель). Теперь я расскажу вам, как использовать специальные периферийные устройства для расширения функциональных возможностей вашего компьютера.
Расширение возможностей ПК – занятие чрезвычайно увлекательное, причем в последнее время оно становится увлекательнее, чем когда-либо прежде. Я объясню. Сегодня мы не только имеем широчайший спектр периферийных устройств (и обильные возможности делать их самостоятельно). Сегодня у нас также есть огромный спектр компьютерной техники, которая может этими устройствами управлять. Одно дело – тепловизор, присоединенный к обычному стационарному ПК (еще несколько лет назад это был единственной вариант), другое дело – тот же тепловизор, но подключенный к ноутбуку, третье – все тот же девайс под управлением карманного компьютера, и уж совсем четвертое – та же периферия, но под управлением компьютера, встроенного в любительский робот-вездеход. И все это стало возможно, в том числе, благодаря тому, что сегодня все компьютеры, от самых больших и сложных до самых маленьких и простых, оснащаются портами USB.
В эпоху портов типа LPT такие нестандартные устройства, как датчик размыкания или термодатчик, можно было легко изготовить самим, подсоединив выводы датчика к разъемам соответствующего порта. Сегодня вы тоже без труда можете сделать устройство, показывающее температуру у вас за окном или уровень pH в вашем аквариуме (а может быть, робота, который будет засыпать корм рыбкам в установленное время), но для присоединения такого устройства к современному компьютеру вам понадобится посредник: устройство, способное перевести поток сырых данных на язык протокола USB. Мы рассмотрим несколько таких устройств.
Velleman VM110
Платы Velleman vm110 поставляются в двух вариантах: в собранном виде и как набор деталей «сделай сам» (этот набор идет под названием k8055). Второй вариант стоит немного дешевле, но если вы не любитель сидеть с паяльником, лучше предпочесть первый.
Какими способами компьютер может общаться с окружающим миром? Путем передачи и приема электрических сигналов, разумеется. Ну, а сигналы бывают цифровыми или аналоговыми. Разработчики интерфейсной платы Velleman VM110 (http://www.vellemanusa.com/us/enu/product/view/?id=522053#) предусмотрели оба случая.
Устройство вообще должно порадовать тех, кто искал средство сопряжения компьютера с электронной техникой. К вашим услугам – 5 цифровых входов, 2 аналоговых входа с возможностью усиления или ослабления сигнала, 8 цифровых выходов, два аналоговых выхода, объединенных параллельно с выходами ШИМ. Если одной платы вам окажется мало, разработчики предусмотрели простую возможность использования до четырех плат Velleman одновременно (можно использовать и больше, но это будет сложнее в реализации). Единственная проблема может возникнуть с нагрузкой, поскольку платы могут питаться только от шины USB.
Особо стоит отметить возможности самотестирования платы. Многочисленные светодиоды позволят вам проверить работу выходов даже в отсутствие внешней нагрузки, а с помощью установленных на плате переключателей вы сможете проверить работу и входов. Все это здорово упрощает отладку программ, предназначенных для взаимодействия с платой-посредником.
К плате прилагается бумажное описание (приятная неожиданность по нынешним временам) и компакт-диск с софтом. Диск содержит весьма устаревшее программное обеспечение (плата все-таки 2003 года выпуска), предназначенное, естественно, для Windows. Впрочем, это не проблема, так как сторонние разработчики уже написали необходимое ПО для Linux, OS X и даже iPhone, да и, как мы дальше увидим, написать свою собственную программу взаимодействия с платой совсем не трудно.
В системе плата регистрируется как устройство класса HID, так что мы можем задействовать библиотеку libusb для управления ею.
Выше говорилось об упрощенной возможности использования четырех плат одновременно. Дело в том, что для каждой вашей платы вы можете самостоятельно выбрать одно из четырех предустановленных значений PID. Делается это с помощью выбора комбинации перемычек на плате (подробности описаны в инструкции). Таким образом, значение VID для нашей платы составляет 0x10CF, а допустимые значения PID – 0x5500, 0x5501, 0x5502, 0x5503 соответственно. При подключении большего числа плат их можно будет различать по серийным номерам, что, конечно, не так наглядно.
Устройство поддерживает одну-единственную конфигурацию и один интерфейс, в котором, помимо точки доступа 0x00, определены еще две точки доступа: 0x01 для передач данных устройству и 0x81 для чтения данных, передаваемых устройством. Обмен информацией между платой и компьютером осуществляется с помощью прерываний USB. Сразу после инициализации в системе плата начинает посылать поток прерываний, которые содержат информацию о состоянии входов. Само наличие этого потока сигнализирует о том, что плата подключена (полезная особенность, если учесть, что libusb пока что не умеет самостоятельно определять момент отключения устройства). Состояния выходов также устанавливаются с помощью прерывания, которое компьютер посылает устройству.
Формат прерывания, которое плата посылает хосту, выглядит следующим образом:
D A1 A2 0x00 0x00 0x00 0x00 0x00
Прерывание передает 8 байт, из которых первый байт представляет собой маску состояния цифровых входов, а второй и третий байты содержат значения аналогового сигнала (значения отображаются в область 0 – 255).
Прерывание, предназначенное для установки значений выходов платы, выглядит несколько иначе:
0x05 D A1 A2 0x00 0x00 0x00 0x00
Первый байт – волшебное число; далее следует байт-маска состояния восьми цифровых выходов, затем два байта, задающие значения сигнала на аналоговых выходах устройства. Остальные байты не используются.
Для демонстрации взаимодействия с платой-адаптером мы напишем небольшую программу. Программа k8055demo, которую вы найдете на диске, позволяет считывать значения аналоговых входов адаптера и устанавливать значения аналоговых выходов. Кроме того, программа переключает значения цифровых выходов, используя светодиоды-индикаторы как двоичный счетчик. При поступлении сигнала с любого цифрового входа платы этот двоичный счетчик сбрасывается, а значения сигналов аналоговых выходов обнуляются.
Рассмотрим для примера несколько фрагментов листинга программы k8055demo. Для взаимодействия с устройством программа использует библиотеку libusb, с который мы познакомились в прошлый раз. Процедура find_devices() ищет на шине USB устройства Velleman по допустимым значениям PID.
unsigned short ALLOWED_PIDS[4] = {0x5500, 0x5501, 0x5502, 0x5503}; typedef struct _devdesc { short pid; libusb_device * device; libusb_device_handle * handle; } devdesc; devdesc found[4]; int already_found = 0; libusb_device **list; libusb_context *ctx; int find_devices() { libusb_init(&ctx); ssize_t count; int i, j; already_found = 0; if ((count = libusb_get_device_list(ctx, &list)) < 0) { printf(“error: device enumeration failed\n”); return 0; } for (i = 0; i < count; i++) { libusb_device *device = list[i]; struct libusb_device_descriptor desc; libusb_get_device_descriptor(device, &desc); if (desc.idVendor == DEV_VID) { if (already_found == 4) break; for (j = 0; j < 4; j++) { if (desc.idProduct == ALLOWED_PIDS[j]) { found[already_found].pid = desc.idProduct; found[already_found].device = device; already_found++; break; } } } } printf(“k8055: %i devices found\n”,already_found); return already_found > 0 ? 1 : 0; }
Массив found, рассчитанный на 4 устройства, заполняется структурами devdesc. Количество найденных устройств сохраняется в переменной already_found.
А вот как выглядит функция read_status(), которая возвращает состояние входов устройства. Первый аргумент функции – индекс устройства в массиве found, второй аргумент – указатель на массив из 8 байтов, в который записываются данные о состоянии устройства, полученные с помощью прерывания.
int read_status(int index, unsigned char * data) { int ret; if (!libusb_interrupt_transfer(found[index].handle, 0x81, data, 8, &ret, 100)) return 1; return 0; }
Было бы странно, если бы за время существования платы Velleman vm110/k8055 я оказался единственным, кто написал бы Linux-ПО для столь замечательного устройства. Программист Rouven Spreckels подошел к вопросу гораздо более основательно и создал целый программный пакет k8055utils (сайт http://k8055utils.sourceforge.net; в настоящее время доступна уже версия 2.2.0 этого продукта). Пакет состоит из программы-демона, которая, собственно, и управляет устройством, а также клиентов, которые могут взаимодействовать с демоном с помощью <over>корня мандрагоры</over> именованных каналов Linux и каналов TCP/IP.
Мосты USB
Где-то в начале 2000‑х производители железа столкнулись с серьезной проблемой. Нет, речь идет вовсе не о пресловутой Y2K. Проблема заключалась в том, что именно в это время стандарт USB наконец-то начал внедряться в широкие компьютерные массы. А для широких масс, на первых порах, внедрение USB было связано, прежде всего, с проблемами обратной совместимости. С одной стороны, у людей было много устройств, которые взаимодействовали с компьютером только через порты COM и LPT, причем речь тут идет не только об оборудовании для широкого потребления, замена которого происходит довольно быстро вследствие запланированного морального износа. Главная проблема заключалась во всяком специализированном контрольно-измерительном оборудовании, которое совсем не так просто было заменить. С другой стороны, существовало огромное количество программ и целых программных комплексов, которые могли взаимодействовать со своим железом только через COM или LPT. Переделка всего этого добра могла обернуться гораздо более серьезными затратами.
Для спасения ситуации было предложено логичное технологическое решение. Ряд компаний представил на рынок устройства-переходники. С одного конца у этих переходников был обычный разъем для подключения к USB. С другого конца у них были интерфейсы, логически (а зачастую и электрически) совместимые с RS-232 и IEEE 1284, так что разработчики оборудования могли включать эти адаптеры в свои устройства с минимальными конструктивными изменениями (переходники могли быть настоящими кабелями с двумя штекерами, а могли быть и модулями для установки внутрь корпуса устройства). Самое интересное происхо- дило на уровне взаимодействия такого адаптера с компьютером.
После установки соответствующего драйвера компьютеру такой девайс представлялся как внешний (или виртуальный) порт COM и LPT. В результате разработчики убивали обоих зайцев: оборудование и программы, ориентированные на старые порты, могли работать практически без изменений.
В случае с эмуляцией COM-порта эта схема оказалась настолько живучей, что используется до сих пор, в том числе и в новых устройствах. Фактически, рассмотренный нами далее адаптер MMUSB245RL для таких целей и предназначен. А учитывая то, что устройство, использующее внутренний переходник USB-RS232, не обязано регистрировать в системе виртуальный COM-порт, таких устройств в природе существует гораздо больше, чем мы думаем.
С интерфейсами LPT все оказалось несколько сложнее. В отличие от последовательных интерфейсов COM, к которым подключали все, что только можно, начиная с мышей и модемов и заканчивая системами управления сигнализацией, порт LPT использовался в основном для подключения принтеров и сканеров. В результате на рынке появилось множество специализированных «принтерных» переходников. Со стороны компьютера такой переходник выглядит не как LPT-порт, а как USB-принтер. Со стороны принтера мы имеем настоящий разъем LPT, но частью логики LPT управляет встроенный в переходник контроллер, так что управлять уровнями сигнала на отдельных выводах LPT, как это было бы возможно с настоящим LPT-портом, у нас не получится.
Настоящие внешние LPT-порты с подключением по USB и полной функциональностью стандартного порта тоже встречаются, но это – большая редкость.
MMUSB245RL
Второе устройство, о котором я расскажу вам, принадлежит к несколько иному типу, нежели плата Velleman. Модуль MMUSB245RL фирмы Propox (http://www.propox.com) – это один из USB-мостов, главная задача которого – добавить возможность подключения к USB в устройства, изначально рассчитанные на работу по протоколу RS232. Для нас MMUSB245RL интересен прежде всего тем, что, в отличие от многих его собратьев, он не является просто конвертором между USB и RS232. Чтобы понять, о чем я говорю, сравним устройство MMUSB245RL и, например, ioMate. USB1 уважаемой фирмы chip45. Устройство ioMate.USB1 – это переходник USB-RS232 в самом точном смысле слова. Подключив модуль к USB-разъему, вы получаете на выходе все стандартные линии RS232 (RTS, CTS, DTRи т. д.). Что же касается модуля MMUSB245RL, то в самом грубом приближении это такая штука, у которой с одной стороны – разъем USB тип B, а с другой – 24 вывода, 8 из которых предназначены для передачи данных, а остальные – для управления этой передачей. Кроме того, на плате модуля есть несколько перемычек, с помощью которых вы можете настроить, например, режим питания модуля (от шины или от собственного источника) и уровни сигналов (3,3 вольта либо 5 вольт).
Управлять устройствами на базе MMUSB245RL можно двумя способами: во-первых, при подключении к компьютеру такое устройство определяется как виртуальный COM-порт (причем специальных драйверов не требуется ни для Linux, ни даже для Windows). Например, при подключении модуля MMUSB245RL к системе с Linux в системе появится устройство /dev/ttyUSB0. Далее обмениваться данными с этим устройством можно будет так же, как с любым устройством, подключенным к последовательному порту (и для этого подойдет любое соответствующее ПО). Второй режим предполагает использование фирменного программного обеспечения, и о нем мы поговорим позже. Что же представляет собой MMUSB245RL с точки зрения разработчика электроники?
Подробные схемы вы найдете, естественно, в руководстве к модулю. Продемонстрируем логику работы MMUSB245RL на простом примере. Допустим, вашему устройству нужно передать байт данных в компьютер. Модуль содержит два буфера FIFO – для приема и передачи данных. Если мы хотим передавать данные, надо сначала убедиться, что соответствующий буфер не заполнен (иначе придется ждать, пока компьютер считает данные). О том, что бу-фер не заполнен, свидетельствует низкий уровень напряжения на выводе TXE (вывод 2). Отлично. Теперь устанавливаем уровни сигнала на выводах D0–D7 соответственно битовой маске передаваемого байта и сбрасываем напряжение на выводе WR. В этот момент байт с выводов D0–D7 будет перемещен в буфер вывода, а после возвращения значения уровня на выводе WR в исходное состояние устройство будет готово к приему нового байта.
Все это я описал для того, чтобы продемонстрировать, что устройство, передающее или принимающее данные с помощью MMUSB245RL, должно быть достаточно умным, чтобы проверяться и изменять состояния управляющих выводов. По сравнению с ioMate.USB1 такая сложность может быть и минусом. Действительно, если вам нужно всего лишь зажигать светодиод по сигналу с компьютера, то в ioMate.USB1 это проще сделать, используя управляющие сигналы RS232. В MMUSB245RL все управляющие сигналы интерфейса от вас спрятаны, зато вы можете сосредоточиться на передаче потока байтов. Впрочем, тупое устройство можно сделать и с помощью MMUSB245RL. Вероятно, это устройство займет второе место на конкурсе самых тупых устройств. Почему только второе? Ну, вы поняли. Для передачи каких-нибудь данных в компьютер с помощью MMUSB245RL достаточно связать выводы GND и WR через резистор 400 Ом и переключатель. При размыкании-замыкании переключателя буфер вывода будет считывать значения с выводов D0–D7, что бы там ни было, и посылать их на линию. Сам факт появления данных на входе COM-порта может сообщить компьютеру, что нечто произошло.
Я обещал рассказать о дополнительных возможностях программного взаимодействия с MMUSB245RL. Вместе с модулем поставляется библиотека libftd2xx (в версиях для Windows и Linux), которая реализует проприетарный протокол взаимодействия (думаю, что обратный инжиниринг этого протокола не составит особого труда, но это отдельная тема). Возможности libftd2xx могут показаться избыточными, но при грамотном и применении можно добиться очень интересных результатов.
Во-первых, libftd2xx позволяет обмениваться данными с модулем, минуя механизм виртуального порта RS232. Во-вторых, библиотека позволяет перепрограммировать EEPROM (то бишь, ЭСППЗУ) модуля, заменяя различные его параметры, включая VID, PID и серийный номер. Кстати, libftd2xx позволяет временно изменить VID и PID и другими способами. Все вместе это означает, что модуль MMUSB245RL может представиться системе совсем не тем, чем он является на самом деле. Иногда это хорошо. Если вы крупный разработчик оборудования и используете MMUSB245RL для сопряжения устройств с компьютером, вам может быть совсем ни к чему, чтобы ваши устройства система определяла как виртуальный COM-порт производства компании FTDI (именно эта фирма производит чип контроллера). Вы можете захотеть приписать устройству свою марку, и FTDI не возражает против такой подмены (кроме того, замена PID может быть просто необходима для правильной загрузки драйверов, и тут FTDI вообще идет вам навстречу и готова предоставить уникальные значения PID из собственных закромов). Параметры модуля можно, конечно, подменять и с более интересными целями: например, чтобы выдать его за девайс какой-нибудь известной фирмы. Однако распространяться на эту тему мы не будем.
Мы достаточно подробно рассмотрели устройства, которые могут быть органами управления нашим умным домом; пришло время еще раз взглянуть на центр управления им. Но это будет темой для следующей статьи.