Книга: Интерфейс USB (практика использования и программирования). Основы разработки и программирования простейших USB-устройств Классы Java для работы с USB в Android API

  • 25.01.2022

Шина USB (Universal Serial Bus – универсальная последовательная шина) появилась 15 января 1996 года при утверждении первого варианта стандарта фирмами – Intel, DEC, IBM, NEC, Northen Telecom и Compaq.

Основная цель стандарта, поставленная перед его разработчиками – создать возможность пользователям работать в режиме Plug&Play с периферийными устройствами. Это означает, что должно быть предусмотрено подключение устройства к работающему компьютеру, автоматическое распознавание его немедленно после подключения и последующей установки соответствующих драйверов. Кроме этого, желательно питание маломощных устройств подавать с самой шины. Скорость шины должна быть достаточной для подавляющего большинства периферийных устройств. Контроллер USB должен занимать только одно прерывание независимо от количества подключенных к шине устройств, то есть решить проблему нехватки ресурсов на внутренних шинах IBM PC совместимого компьютера.

Практически все поставленные задачи были решены в стандарте на USB и весной 1997 года стали появляться компьютеры, оборудованные разъемами для подключения USB устройств. Сейчас USB стала настолько активно внедряться производителями компьютерной периферии, что, например, в компьютере iMAC фирмы Apple Computers присутствует только USB в качестве внешней шины.

Возможности USB 1.0 следующие:

1. высокая скорость обмена данными (full-speed) – 12 Мбит /с;

2. максимальная длина кабеля для высокой скорости обмена – 5 метров;

3. низкая скорость обмена данными (low-speed) – 1,5 Мбит /с;

4. максимальная длина кабеля для низкой скорости обмена – 3 метра;

5. максимальное количество подключенных устройств – 127;

6. возможное одновременное подключение устройств с различными скоростями обмена;

8. максимальный ток потребления на одно устройство – 500 мА.

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

Сигналы USB передаются по 4-х проводному кабелю, схематично показанному на рисунке ниже:

Рисунок 2.6.1 – Сигнальные провода USB

Здесь GND – цепь общего провода для питания периферийных устройств, Vbus - +5 В также для цепей питания. Шина D+ предназначена для передачи данных по шине, а шина D- для приема данных.
Кабель для поддержки полной скорости шины (full-speed) выполняется как витая пара, защищается экраном и может также использоваться для работы в режиме минимальной скорости (low-speed). Кабель для работы только на минимальной скорости (например, для подключения мыши) может быть любым и неэкранированным.
Разъемы, используемые для подключения периферийных устройств, делятся на серии: разъемы серии «A» (вилка и розетка) предназначены только для подключения к источнику, например, компьютеру, разъемы серии «B» (вилка и розетка) только для подключения к периферийному устройству.

USB разъемы имеют следующую нумерацию контактов, показанную в таблице 2.6.1.

Таблица 2.6.1 – Назначение и маркировка контактов USB

В 1999 году тот же консорциум компьютерных компаний, который инициировал разработку первой версии стандарта на шину USB, начал активно разрабатывать версию 2.0 USB, которая отличается введением дополнительного высокоскоростного (Hi-speed) режима. Полоса пропускания шины увеличена в 40 раз, до 480 Мбит/с, что сделало возможным передачу видеоданных по USB.
Совместимость всей ранее выпущенной периферии и высокоскоростных кабелей полностью сохраняется. Контроллер стандарта 2.0 уже интегрирован в набор системной логики программируемых устройств (например, материнская плата персонального компьютера).

В 2008 году компаниями Intel, Microsoft, Hewlett-Packard, Texas Instruments, NEC и NXP Semiconductors создана спецификация стандарта USB 3.0. В спецификации USB 3.0 разъёмы и кабели обновлённого стандарта физически и функционально совместимы с USB 2.0, однако в дополнение к четырем линиям связи, добавлены ещё четыре. Тем не менее, новые контакты в разъёмах USB 3.0 расположены отдельно от старых на другом контактном ряду. Спецификация USB 3.0 повышает максимальную скорость передачи информации до 5 Гбит/с - что на порядок больше 480 Мбит/с, которые может обеспечить USB 2.0. Кроме того, увеличена максимальная сила тока с 500 мА до 900 мА на одно устройство, что позволяет питать некоторые устройства, требующие ранее отдельного блока питания.

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

1. разработка полнофункционального драйвера операционной системы;

2. использования интерфейса специального класса USB – устройств, называемых HID (Human Interface Device) устройствами.

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

Второй способ заключается в следующем. Существует поддерживаемый современными операционными системами интерфейс для устройств взаимодействия компьютера и человека или HID-устройств, таких как:

1. клавиатуры, мыши, джойстики;

2. различные датчики и считыватели;

3. игровые рулевое управление и педали;

4. кнопки, переключатели, регуляторы.

Любое такое устройство, если оно выполняет требования к HID-устройствам, будет автоматически распознано системой и не потребует написания специальных драйверов. Кроме того, их программирование, как правило, намного проще написания специализированного драйвера устройства. К сожалению, способ имеет существенный недостаток: скорость обмена информации с HID-устройством сильно ограничена и составляет максимум 64 кБ/с.

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

Стоит отметить что, многие USB-приборы, с первого взгляда не попадающие под определение устройств взаимодействия с человеком, логичнее все же реализовать как HID-устройства. Такое явление часто встречается в области производственного оборудования, которая последнее время переживает массовое внедрение USB-технологий. К примеру, рассмотрим лабораторный источник питания с возможностью задания параметров его выходных сигналов с компьютера с помощью USB-интерфейса. Непосредственно источник питания без сомнений не является средством взаимодействия с человеком. Однако, в данном случае функции, реализуемые посредством USB-подключения, дублируют клавиатуру, регуляторы и индикаторы, установленные на самом приборе. А эти органы управления как раз попадают под определение HID. Соответственно блок питания с этими USB-функциями логичнее всего организовать как HID-устройство.

В рассмотренном примере для нормальной работы достаточно будет небольшой скорости передачи данных, в других же случаях приборы могут быть весьма требовательны к скорости обмена. Низкая скорость передачи является главным ограничением HID-варианта построения устройства, что в сравнении с 12 Мбит/сек полной скорости USB 1.0-шины выглядит большим минусом HID-технологии в вопросе выбора конкретной USB-реализации. Однако для многих задач коммуникации указанной скорости вполне хватает и HID-архитектура как специализированный инструмент занимает достойное место среди способов организации обмена данными.

HID-устройства бывают двух типов: участвующие (загрузочные) и неучаствующие в начальной загрузке компьютера. Наиболее ярким примером загрузочного USB-HID устройства является клавиатура, работа которой начинается со стартом компьютера.

При разработке HID-устройства необходимо обеспечить следующие требования, налагаемые спецификацией:

1. полноскоростное HID-устройство может передавать 64000 байт каждую секунду или по 64 байта каждые 1 мс; низкоскоростное HID-устройство имеет возможность передать вплоть до 800 байт в секунду или по 8 байт каждые 10 мс.

2. HID-устройство может назначить частоту своего опроса для определения того, есть ли у него свежие данные для передачи.

3. Обмен данными с HID-устройством осуществляется посредством специальной структуры, называемой репортом (Report). Каждый определенный репорт может содержать до 65535 байт данных. Структура репорта имеет весьма гибкую организацию, позволяющую описать любой формат передачи данных. Для того чтобы конкретный формат репорта стал известен хосту микроконтроллер должен содержать специальное описание – дескриптор репорта.

Реализуется USB взаимодействие непосредственно на микроконтроллере несколькими способами:

1. использованием контроллера с аппаратной поддержкой, например AT90USB*, фирмы atmega;

2. использованием программной эмуляции usb-интерфейса на любом микроконтроллере.

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

Обе достаточно простые в использовании, обеспечивают полную эмуляция USB 1.1 low-speed устройств за исключением обработки ошибок связи и электрических характеристик и запускаются практически на всех AVR контроллерах с минимум 2 килобайтами flash-памяти, 128 байтами RAM и частотой от 12 до 20 МГц.

Для написания приложений с поддержкой Windows USB HID устройств требуются заголовочные файлы hid*, входящие в состав WDK (Windows Driver Kit), или можно использовать свободно-распространяемую библиотеку hidlibrary или другую аналогичную.

Таким образом, в общем случае программирование USB достаточно сложная задача, требующая специального микроконтроллера с аппаратной поддержкой и написания драйвера операционной системы. Однако в практике при разработке устройств можно использовать значительно более просто интерфейс HID – устройств, поддержка которого реализована на уровне стандартного драйвера системы, а программирование упрощается использованием существующих библиотек функций.

Контрольные вопросы

  1. В чем отличие провода D- и GND в USB? Почему нельзя использовать один общий провод для питания и сигнала?
  2. Сколько режимов скорости работы USB существует на сегодняшний день (включая версию 3.0)?
  3. Что такое HID-устройство? Почему для их работы в современных ОС не требуется написание драйверов?
  4. Можно ли реалировать USB устройства с помощью микропроцессора, неимеющего встроенной поддержки интерфейса?
  5. Какие основные отличия USB 3.0 от предыдущих версий?

Рисунок 1

Интерфейс USB приобретает все большую популярность как интерфейс связи периферийных устройств с ПК и современные компьютеры зачастую не имеют привычного интерфейса RS-232. Популярность USB обусловлена многими причинами, вот основные из них:

  • высокая скорость обмена, высокая помехозащищенность
  • управление потоком данных, контроль целостности и исправление ошибок
  • возможность разветвления через хабы и подключения большого количества устройств.
  • возможность получения питания от шины
  • универсальность шины - возможность подключения разноплановых устройств (клавиатура, принтер, модем)
  • автоматическая идентификация и конфигурирование системы, Plug and Play

Однако существуют (зачастую необоснованные) факторы, сдерживающие массовое использование USB разработчиками микроконтроллерных приборов:

  • необходимость программирования драйверов для Windows
  • сравнительно малая распространенность микроконтроллеров со встроенным интерфейсом USB
  • Урок 2. Создание USB 2.0 совместимого HID-устройства типа джойстик.

Этот цикл статей призван показать, что преодолеть эти трудности довольно легко и каждый может провести "апгрейд" своего устройства с привычного RS-232 на USB или создать новое устройство с USB интерфейсом.

В качестве микроконтроллера в примерах будет рассматриваться микроконтроллер производства компании Microchip PIC18F4550 с интерфейсом USB 2.0 (поддерживает Low Speed и Full Speed).

Урок 1. USB без программирования Windows, виртуальный COM порт

Одна из задач, возникающих при разработке USB устройств, это переход с интерфейса RS-232 на USB, при этом, если производится модификация "старого" прибора или устройство должно быть совместимо с существующими протоколами и программным обеспечением ПК, то желательно избавиться от любой модификации программного обеспечения на компьютере. Одним из решений данной задачи является использование интерфейса USB в качестве виртуального COM-порта. Применение данного метода исключает необходимость модификации ПО компьютера, т.к. USB соединение видится персональным компьютером как дополнительный COM-порт. Другое важное преимущество заключается в том, что используются стандартные драйвера Windows и не требуется создание какого-либо своего драйвера.

Спецификация USB описывает класс коммуникационных устройств (Communication Device Class - CDC), который определяет множество режимов соединений для телекоммуникационных (модемы, терминалы, телефоны) и сетевых устройств (Ethernet адаптеры и хабы, ADSL модемы), включая эмуляцию последовательного порта.

Возьмем в качестве примера устройство, которое через RS-232 передает данные о напряжении с потенциометра и температуре с цифрового датчика TC77, а так же принимает команды для включения/выключения двух светодиодов (данный пример для простоты реализуем на плате PICDEM™ FS USB DEMONSTRATION BOARD, но можно собрать и более простую схему - см.ниже).

Отладочная плата PICDEM FS-USB предназначена для разработок и демонстрации устройств на микроконтроллере PIC18F4550 с шиной USB2.0. На плате установлен контроллер PIC18F4550 в корпусе TQFP44, имеющий следующие особенности:

  • Максимальная частота работы - 48 МГц (12 MIPS);
  • 32 Кб Flash памяти программ (технология Enhanced Flash);
  • 2 Кб памяти данных (из них 1 Кб двухпортового ОЗУ);
  • 256 байт памяти данных EEPROM;
  • Интерфейс FS USB2.0 с поддержкой скорости работы 12 Мбит/с, со встроенным приемопередатчиком и стабилизатором напряжения.

На плате установлены:

  • Кварц 20 МГц;
  • Интерфейс RS-232 для демонстрации возможности перехода с USART на USB;
  • Разъем для внутрисхемного программирования и отладки
  • Стабилизатор питающего напряжения с возможностью переключения на питание от шины USB;
  • Разъем расширения PICtail™;
  • Температурный датчик TC77, подключенный по I2C;
  • Переменный резистор, подключенный ко входу АЦП;
  • Светодиоды, кнопки.

Для данного устройства есть программа для ПК для управления устройством и индикации значений напряжения и температуры. Итак, мы можем подключить устройство к RS-232, выбрать доступный в системе COM-порт и установить скорость обмена с нашим устройством, число бит данных, количество стоповых бит, а так же параметры битов четности и управления потоком в соответствии с программой микроконтроллера (для этого мы должны знать параметры инициализации нашего контроллера)


Рис. 2

Приступим к подключению нашего устройства к USB.

Компания Microchip Technology Inc. Предлагает готовый пример применения AN956, в котором реализована поддержка USB CDC для микроконтроллера PIC18F2550, PIC18F2455, PIC18F4455, PIC18F4550. Программа построена по модульному принципу, что позволяет легкую модернизацию и интегрированию в готовые проекты.

После начальной инициализации контроллера программа может общаться с ПК через интерфейс USB посредством нескольких готовых функций:

Модифицируем нашу программу для передачи и приема данных через USB.

Фрагмент программы подготовки и передачи данных:

Прием данных:

if(getsUSBUSART(input_buffer,1)) { switch (input_buffer) { case "1" : mLED_3_On(); break; case "2" : mLED_3_Off(); break; case "3" : mLED_4_On(); break; case "4" : mLED_4_Off(); break; default: break; } }

После подключения устройства к USB система опознает новое устройство


Рис. 3

И устанавливает новое оборудование


Рис. 4

Выбираем установку с указанного места и указываем путь расположения файла mcpusb.inf из комплекта исходных кодов программы к AN956. После этого производится установка нового устройства в систему.


Рис. 5

Итак, новое устройство готово к работе. В системе появился новый виртуальный COM порт.


Рис. 6

Теперь в нашей программе мы можем выбрать появившийся виртуальный COM порт для общения с устройством …


Рис. 7

… и посмотреть что устройство действительно стало работать через появившийся в системе COM порт посредством USB соединения.

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

Окно программы PICDEM CDC


Рис. 8

При использовании микроконтроллеров PIC18Fxx5x со встроенным модулем USB 2.0 виртуальный COM порт может обеспечить скорость передачи данных до 80Кбайт в секунду (640Кбит/сек), что существенно превышает возможную скорость передачи через RS-232, при этом, как мы видим, переделки ПО для компьютера не потребовалось!

Примеры программ, документация и схема, использованные в уроке 1.

  1. Программа PICDEM CDC + исходные коды для Delphi загрузить
  2. Компонент Delphi для работы с COM портом загрузить
  3. AN956 + оригинальные исходные коды
  4. Файл user_uart.c (все изменения оригинальной программы из AN956 производились только в этом файле. Для запуска примера к урок 1, необходимо скопировать этот файл в каталог C:\MCHPFSUSB\fw\Cdc\user\, заменить в проекте файл user.c на user_uart.c, скомпилировать проект и прошить микроконтроллер)
  5. Упрощенная схема USB устройства


Рис. 9

Примечание: в оригинальной схеме платы PICDEM FS USB используется автоматическое определение источника питания платы (внешний источник или USB). Поэтому при использовании упрощенной схемы необходимо закоментарить строку #define USE_USB_BUSSENSE_IO в файле usbcfg.h

Урок 2. Создание USB 2.0 совместимого HID-устройства типа джойстик

Наиболее распространенными USB устройствами являются устройства интерфейса с человеком (HID - Human Interface Devices). Типичными представителями этого класса являются USB- клавиатуры, мыши, джойстики, панели настройки мониторов, считыватели штрих-кодов, карт-ридеры и т.п. Преимуществами HID устройств является:

  • простота реализации;
  • компактный код;
  • поддержка Windows (не нужны дополнительные драйвера).

На сайте компании Microchip есть пример реализации HID манипулятора мышь. Рассмотрим реализацию простейшего игрового манипулятора на основе этого примера. Для этого проекта будем использовать демонстрационную плату PICDEM FS-USB (DM163025). Отладочная плата PICDEM FS-USB имеет один переменный резистор и 2 кнопки, поэтому разрабатываемый джойстик будет иметь минимум элементов управления (2 кнопки и, например, регулятор газа).

В первую очередь нам нужно переписать дескриптор устройства под создаваемый джойстик. Для упрощения задачи можно воспользоваться программой HID Descriptor Tool, которую можно скачать с сайта www.usb.org

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


Рис. 10

Итак, в нашем случае будут использоваться несколько типов данных - это симуляция органа управления - Simulation Controls, а конкретно это ручка (педаль) газа (Throttle) и кнопки управления (Button). Для того чтобы операционная система "знала" как обращаться с этими типами данных, необходимо описать максимальные и минимальные значения и размер данных. В нашем случае "газ" это одно 8-и битное значение (report_size = 8, report_count = 1), а состояние кнопок определяется как поле однобитных значений. В примере используется только 2 кнопки, но необходимо выровнять поле до байтовой величины (report_size = 1, report_count = 8). Итого микроконтроллер при запросе данных от компьютера должен передать 2 байта - уровень газа и состояние кнопок в соответствии с сформированным дескриптором устройства (подробное описание возможных дескрипторов см. в спецификации на устройства HID www.usb.org). Созданное описание дескриптора устройства можно сохранить в разных форматах, в том числе и как заголовочный файл.h

Дополнительно нужно скорректировать в описании HID Class-Specific Descriptor размер полученного дескриптора устройства и в дескрипторе конечной точки изменить размер данных, передаваемых через конечную точку (в нашем случае передаем 2 байта, поэтому размер HID_INT_IN_EP_SIZE=2).

Перечисленных изменений хватит для того чтобы Windows опознала подключенное устройство как джойстик. Теперь можем скорректировать строковые данные, чтобы устройство имело то название, какое мы хотим (например "PIC18F4550 Joystick"). Для того чтобы присвоить устройству имя на русском языке необходимо прописывать строковый дескриптор в кодировке UNICODE. На этом описание джойстика заканчивается и нужно подготовить данные для передачи в PC.

ReadPOT(); // запуск измерения напряжения потенциометра buffer = ADRESH; // обработка состояний кнопок if(sw2==0) buffer |= 0x01; else buffer &= ~0x01; if(sw3==0) buffer |= 0x02; else buffer &= ~0x02; // передача данных Emulate_Joystick();

После компиляции проекта и программирования микроконтроллера можно подключить устройство к USB-порту. Плата определяется как HID игровое устройство, инсталлируется в систему и готово к работе.


Рис. 11

Через панель управления в Windows мы можем открыть доступные игровые устройства, выбрать наш джойстик, откалибровать его и проверить функциональность.


Рис. 12

При изменении конфигурации устройства - добавлении органов управления или кнопок, необходимо не только изменить описание дескриптора устройства, но и передавать данные строго в соответствии с созданным дескриптором. Так изменив в описании дескриптора устройства USAGE_MAXIMUM (BUTTON 2) максимальное число кнопок с 2 на 8, получим джойстик на 8 кнопок.


Рис. 13

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


Рис. 14

Примеры программ, документация и схема, использованные в уроке 2.

  1. Оригинальные исходные коды реализации HID-мыши.
  2. Исходные коды реализации HID-джойстика.

Урок 3. Составное USB устройство

Любое USB устройство может иметь несколько конфигураций и в каждой конфигурации несколько интерфейсов. Это свойство USB позволяет создаваемому устройству иметь возможность опознаваться компьютером как несколько USB устройств с разными интерфейсами. Мышка, например, может иметь встроенный карт-ридер и взаимодействовать с компьютером как два независимых устройства.

Структура дескриптора устройства:


Рис. 15

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

1. Создание дескриптора.

Изменим структуру дескриптора (файл usbdsc.h)

Устройство будет иметь 2 интерфейса, в каждом по одной конечной точке.

#define CFG01 rom struct \ { USB_CFG_DSC cd01; \ USB_INTF_DSC i00a00; \ USB_HID_DSC hid_i00a00; \ USB_EP_DSC ep01i_i00a00; \ USB_INTF_DSC i01a00; \ USB_HID_DSC hid_i01a00; \ USB_EP_DSC ep02i_i01a00; \ } cfg01
  1. В соответствии с измененной структурой нужно изменить дескриптор в файле usbdsc.c.
  2. В файле usbcfg.h определить идентификаторы интерфейсов, используемые конечные точки, размеры report дескрипторов.
  3. В файле hid.c нужно инициализировать дополнительные конечные точки (в функции HIDInitEP) и изменить функцию обработки HID-запросов (функция USBCheckHIDRequest).
  4. Каждое из устройств, мышка и джойстик, должны передавать данные каждый в свою конечную точку. Поэтому нам необходимо добавить функции передачи данных в конкретные конечные точки и проверки, что нужная конечная точка свободна (добавить функции аналогичные mHIDTxIsBusy и HIDTxReport в файле hid.c).

Тогда передача данных для мышки будет выглядеть как

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


Рис. 16


Рис. 17

Исходные коды составного HID устройства.

Замечание. Не забывайте менять PID при создании нового устройства или удалять из системы предыдущее устройство с тем же самым PID.

Урок 4. Опыты с программатором PICkit2

Компания Microchip Technology Inc. выпускает недорогой программатор разработчика PICkit2, который в первую очередь используется для программирования Flash-контроллеров. Отличительной особенностью этого программатора является доступность полной документации и исходных кодов прошивки для микроконтроллера, и программы оболочки для компьютера. PICkit2 получает питание от USB, формирует регулируемые напряжения программирования и питания, а так же имеет 3 линии входа-выхода для подключения к программируемому устройству. Для возможности обновления прошивки программатора в PICkit2 реализована программа бутлоадер.


Рис. 18

CDC-устройство на основе PICkit2

Используя все эти особенности, на основе программатора PICkit2 возможно создание и отладка своего USB-устройства с возможностью в любой момент откатиться назад к его функциям программатора. С помощью бутлоадера, который прошит в программатор, в PICkit2 можно прошить другие программы, например, программу поддержки виртуального COM-порта. Для этого берем пример CDC, переименовываем проект и делаем следующее

  1. в файле main.c меняем адрес расположения прошивки (бутлоадер PICkit2 передает управление пользовательской программе на адрес 0х002000.
    #pragma code _RESET_INTERRUPT_VECTOR = 0x002000
  2. в файле io_cfg.h убираем все про порт D (можно задать мигание светодиода на PORTC0).

    Так как PICKIT2 всегда питается от USB, то задаем

    #define usb_bus_sense 1 // device is always plugged in #define self_power 0 // device is powered from USB

  3. в файле usbcfg.h ставим комментарии на 2 строки
    //#define USE_SELF_POWER_SENSE_IO //#define USE_USB_BUS_SENSE_IO
  4. В файле user.c выводим в USB нужные нам данные
  5. подключаем файл линкера pickit2.lkr

После этого можно откомпилировать проект и через оболочку PICkit2 загрузить новую прошивку.

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

Исходные коды данного примера доступны по ссылке.

На основе данного примера и используя внешние выводы программатора PICkit2 можно получать данные с внешних устройств и передавать в компьютер через USB. Таким образом, используя PICkit2 можно сделать вывод данных на COG ЖК-индикаторы, считыватели I2C, SPI и 1-wire устройств, например датчиков температуры и др. устройств.

Радио HID клавиатура на основе PICkit2


Рис. 19

Рассмотрим еще один пример "нецелевого" использования программатора PICkit2 - эмулятор клавиатуры с радиоинтерфейсом. Такое устройство может использоваться, например, для проведения презентаций - для перелистывания слайдов вдали от компьютера.

Для реализации такого устройства нам понадобятся:

  • PICkit2
  • демо-плата из комплекта PICkit2 (DV164120)
  • радиоприемник (rfRXD0420) и радиопередатчик (rfPIC12F675) из комплекта rfPICkit.

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

PICkit2 будет выполнять следующие функции:

  • при подключении к компьютеру через USB определяться как HID-клавиатура
  • формировать напряжение питания +5В для демо-платы с приемником
  • опрашивать 2 внешних вывода контроллера приемника и при наличии лог. 1 отсылать в компьютер коды нажатия кнопок PageUp или PageDown.

Два виртуальнык COM-порта (Эмуляция микросхемы FTDI2232) на базе PICKit2

Этот пример предназначен только для изучения работы USB. Изучите требование лицензии на драйвер FTDI перед использованием!

Пример показывает как на базе микроконтроллера с USB портом сделать 2 виртуальных COM-порта.Для начало нужно установить драйвера для микросхемы FTDI2232. Затем для загрузки в PICkit2 нужно в оболочке PICkit2 выбрать пункт обновления прошивки и указать на файл TestVCP2.hex из архива. После перепрограммирования PICkit2 у вас в системе появятся 2 независимых последовательных COM порта.

Пример взят с сайта http://forum.microchip.com/tm.aspx?m=261649

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

Все приведенные выше примеры основаны на MCHPFSUSB Framework v1.3. С появлением контроллеров PIC24 и PIC32 с USB OTG, компания Microchip выпустила новую версию стека - USB stack v. 2.х.

В новой версии USB stack v. 2.3, помимо стеков USB device, реализующего функциональность USB-клиента, USB Embedded host, реализующего функциональность хоста, также добывлен стек USB dual role, реализующий функции и хоста, и клиента; и USB OTG, поддерживающий протокол согласования роли хоста (HNP), протокол запроса сеанса (SRP), и полностью соответствующий спецификации USB OTG. В примерах применения реализовано:

  • Embedded Host
    • Printer Class host - поддержка ESC/POS, PostScript® и PCL5 принтеров
    • CDC Class host - поддержка устройств ACM (abstract control model)
    • HID Клавиатура
  • Device
    • HID bootloader - добавлена поддержка семейств PIC32MX460F512L и PIC18F14K50
    • HID клавиатура, мышка
    • MSD internal flash demo - использование внутренней flash для хранения файлов
    • MSD + HID composite example - пример составного устройства MSD и HID
    • CDC - эмуляция COM-порта
    • поддержка семейства PIC32MX460F512L для всех демонстрационных проектов ПК
    • примеры HID, MCHPUSB и WinUSB теперь поддерживают функцию Microsoft Plug-and-Play (PnP) для автоопределения.
  • Документация
    • полное описание всех API расположено в папке "\Microchip\Help"

Microchip бесплатно предоставляет драйвера наиболее востребованных USB-классов:

  1. Интерфейс пользователя (HID). Этот режим обмена используется практически во всех клавиатурах, "мышках" и прочих устройствах ввода/вывода
  2. Коммуникационное устройство (CDC). Этот режим наиболее простой для перехода с последовательного интерфейса RS-232 на USB. На компьютерах с WinXP/2K производиться создание и эмуляция виртуального COM-порта при подключении микроконтроллера. Программы, работающие с портами COM1.. 4 будут работать без изменений и с виртуальным портом, но с большей скоростью (порядка 1 Мбит/с)
  3. Устройства массового хранения (MSD). Это устройства, работающие как накопители информации - флешки, SD/MMC-карты, диски и прочее
  4. Устройства класса "принтер" (Printer Class). Этот режим создан для использования USB-принтеров, что позволяет конечному устройству на PIC-микроконтроллере с модулем USB выводить необходимую информацию непосредственно на USB-принтер
  5. Резидентный загрузчик Microchip. Простейший режим, который используется только для обновления по USB программного обеспечения микроконтроллера. Со стороны ПК устанавливается небольшая программа, аналог драйвера
  6. Собственный драйвер (Custom). Наиболее полное использование ресурсов USB2.0 для продвинутых пользователей: возможность выбора режимов работы шины (изохронный, по прерываниям, объемный, управления), высокая скорость передачи. Требует глубоких знаний работы шины и навыки разработки ПО под Windows

Бутлоадер с USB Flash Drive

Обновление прошивки с обычного флэш диска.

Для обновления прошивки микроконтроллера с модулем USB-OTG (PIC24 или PIC32) не обязательно использовать специальное программное обеспечение. Наличие Host-режима позволяет подключать к микроконтроллеру обычные USB-накопители данных (Flash Drive). На сайте Microchip опубликован пример (бета версия), позволяющий обновить программное обеспечение микроконтроллера из подключенного USB-диска.

Для запуска примера вам нужно загрузить прошивку бутлоадера в плату PIC32 USB Board или Explorer 16 (c установленным процессорным модулем PIM PIC32 USB и дочерней платой USB PICtail Plus Daughter Board). Если подать питание на плату при нажатой кнопке, то контроллер перейдет в режим обновления прошивки. Если теперь подключить Flash накопитель с записанным файлом обновления прошивки, то микроконтроллер считает этот файл и перепишет в свою память программ.

Отладочные платы и средства разработки для USB

Программатор-отладчик PICkit2 (номер для заказа PG164120)

Наличие бутлоадера позволяет заливать свое программное обеспечения для освоения навыков работы с USB


Рис. 20

Отладочная плата PICDEM FS-USB (номер для заказа DM163025)

Предназначена для разработок и демонстрации устройств на микроконтроллере PIC18F4550 с шиной USB2.0. На плате установлен контроллер PIC18F4550 в корпусе TQFP44.


Рис. 21

Low Pin Count USB Develpment Kit (номер для заказа DM164127)

Отладочная плата Low Pin Count USB Development Kit предоставляет легкий путь для оценки возможностей микроконтроллеров 20-и выводных USB микроконтроллеров Microchip PIC18F14K50 и PIC18F13K50. Комплект включает все необходимое для начала работы с USB контроллерами (программное обеспечение, исходные файлы примеров, документацию).


Рис. 22

PIC18F87J50 Full Speed USB PIC18F87J50 FS USB Demo Board (номер для заказа MA180021)

Плата PIC18F87J50 FS USB Demo Board служит для отладки Full Speed USB 2.0 микроконтроллеров семейства PIC18F87J50. Помимо автономной работы плата так же может использоваться как процессорный модуль для платы PIC18 Explorer Board.


Рис. 23

PIC24 Starter Kit (номер для заказа DM240011)

Комплект разработчика PIC24F Starter Kit содержит все необходимое для начала работы с высокопроизводительными контроллерами семейства PIC24F. Этот недорогой комплект содержит интегрированный внутрисхемный отладчик и программатор, контроллер PIC24F с интерфейсом USB (на плате могут быть реализованы функции Host и Device), трехцветный светодиод, емкостная сенсорная панель и графический OLED дисплей. Демонстрационная программа через графическое меню позволяет осуществлять запись данных на внешний USB Flash Drive, осуществлять настройку сенсорной панели и запускать графические задачи.


Рис. 24

PIC32 USB Board (номер для заказа DM320003)

Позволяет освоить модуль USB-OTG в контроллерах PIC32


Рис. 25

Отладочная плата "Explorer 16 Development Board" (номер для заказа DM240001)

Это дешевое средство отладки для ознакомления и начала работы с высокопроизводительными семействами 16-и разрядных микроконтроллеров PIC24 и контроллерами цифровой обработки сигналов dsPIC33F.


Рис. 26

Дочерняя плата "USB PICtali Plus " (номер для заказа AC164131)

Совместно с USB процессорными Plug-In модулями позволяет разрабатывать и отлаживать USB устройства Host, Device, USB-OTG.


Рис. 27

Илья Афанасьев ,
Компания

Как уже упоминалось, операционные системы Windows обеспечивают программную под держку функционирования устройств, подключенных к шине USB. Обработку потоков данных устройств USB на уровне операционной системы выполняет стек стандартных драйверов, которые выполняют основные функции по управлению всеми устройствами USB и обмену данными между ними и системой.

Если вам необходимо написать программное обеспечение для какого либо устройства USB, которое расширяло бы его возможности по обработке данных, то можно избрать один из трех возможных путей:

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

написать драйвер фильтра, который бы обеспечивал требуемую функциональность, но располагался бы в стеке драйверов над системными драйверами. Таким образом, все стандартные функции обработки выполняли бы драйверы USB, установленные системой, а дополнительные функции обеспечивались бы вашим драйвером фильтра, с которым и взаимодействовала бы программа пользователя;

воспользоваться свободно распространяемыми библиотеками функций и драйвера

ми для доступа к USB устройству.

В большинстве случаев программный доступ к устройству USB может потребоваться, если данное устройство выполняет какую то очень специфичную функцию. Например, на базе USB разработаны «электронные осциллографы» или системы сбора данных, для работы с которы ми необходимо иметь доступ к самому устройству. В большинстве таких случаев можно вос пользоваться свободно распространяемыми библиотеками функций, которые будут работать практически во всех популярных средах программирования. Например, под эгидой GNU раз работано программное обеспечение, известное под названием LibUsb, включающее необхо димые драйверы и библиотеки функций для работы в операционных системах Windows и Linux. Эти библиотеки функций очень популярны и позволяют быстро разрабатывать про граммы, взаимодействующие с вашим устройством посредством набора стандартных функ ций. Это исключает необходимость написания собственного драйвера устройства, что суще ственно экономит время.

Кроме того, большинство пользователей не знакомо с методикой разработки драйверов,

а это очень сложная область программирования, поэтому наличие такого свободно распрос траняемого программного обеспечения окажет неоценимую помощь широкому кругу пользо вателей. На основе проекта LibUsb разработаны оболочки (wrappers) для работы с Visual Basic .NET и C# .NET, наиболее популярной из которых является LibUsbDotNet, также разра ботанная под эгидой свободно распространяемого программного обеспечения. Несмотря на кажущуюся сложность программирования USB устройств, перечисленное программное обес печение настолько упрощает эту задачу, что она становится под силу даже новичкам. Рас смотрим на практических примерах, как работать с вашими USB устройствами, и начнем с пакета программ LibUsb. Кстати, вышеперечисленное программное обеспечение можно бес платно загрузить с сайта www.sourceforge.net или из многочисленных дублирующих сайтов.

Как работать с библиотеками USB функций LibUsb? Библиотека построена таким обра

зом, чтобы можно было выполнять основные операции, связанные с USB устройством:

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

получение параметров устройства (идентификаторов устройства, данных о произво дителе и характеристиках устройства), для чего в библиотеке имеется целый ряд функций;

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

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

Рис. 6.10

Расположение драйвера libusb0.sys в стеке драйверов устройства

ций на практических примерах. Описание всех функций читатели смогут найти в со ответствующей документации. Напомню, что мы рассматриваем применение функций биб лиотеки libusb в операционных системах Windows.

При инсталляции дистрибутива с libusb в операционной системе Windows в системе инсталлируется драйвер фильтра libusb0.sys. Этот драйвер будет находиться в вершине сте ка драйверов системы, что легко увидеть, на пример, посмотрев сведения о драйверах для любого USB устройства (рис. 6.10).

Кроме того, для обращения к драйверу из программ пользователя в систему инсталли руется библиотека libusb0.dll, используя кото рую можно разрабатывать пользовательские программы.

Рис. 6.17

Вид окна приложения при удалении

USB устройства из системы

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

Вот сейчас мы и будем ее создавать.

Опять же в пакете Microchip solutions есть пример, для нашего контроллера, но я переписал его по своему. Во-первых я сделал без использования графического интерфейса, и размер кода уменьшился раза в 3-4. Что намного лучше для изучения. Тем не менее, принцип работы один. код в стандартном примере от microchip работает так же как этот.

Программа написана в C++. Проект собран в бесплатной студенческой версии Visual C++ express 2010. Я буду давать общие идеи и комментарии по коду, но подразумеваю, что вы уже имеете хоть какой-то опыт программирования в C++.

Итак, начинаем

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

Для того, чтобы читать и записывать данные через USB порт нам нужно получить указатель на наше устройство. Поскольку в отличие от старых портов, подключено может быть устройств свыше сотни, то получить этот указатель не так-то просто. Для того, чтобы это сделать мы будем обращаться к драйверам windows, а именно SetupAPI. Кстати, как только мы получим указатель, то будем общаться с USB портом, будто бы это файл.
Передача данных будет занимать лишь пару команд. Но вот подготовка!
Поскольку мы программируем в С++ то нам нужно быть очень аккуратными с типами данных.
Создаем консольный проект win32. И добавляем туда единственный файл main.cpp

Итак, нам необходимо подключить некоторые библиотеки.
#include
#include
#include

Так же подключаем внешнюю библиотеку:
#pragma comment (lib, "Setupapi.lib")

Первая описанная функция в программе - это getUSBHandle(). Ее описание - в комментариях кода. Да и вообще основные комментарии приведены в коде. Она служит для того, чтобы найти наше устройство и подготовить указатели, чтобы мы могли записывать в устройство и читать из него.
Если в двух словах, то она использует стандартные windows функции для доступа к драйверам USB и через них получает указатель на само устройство.
Если интересно, что все эти функции делают и как, то обращайтесь к MSDN или к книге Агурова, что лежит в оглавлении. Что важно знать: у каждого устройства есть путь, и нам важно получить его. Мы сначала проверяем, совпадает ли ID с устройством, что мы ищем. А потом находим путь устройства.Мы ищем только среди устройств HID класса. это определяется в переменной Guid. Остальное см в комментариях программы
Следующая функция - writeReadUSB. Это просто вспомогательная функция, которая записывает в наше устройство. Обращаю внимание, что запись и чтение устройства после того, как мы создали указатель на него реализуется с помощью стандартных комманд WriteFile и ReadFile
И после этого уже мы видим функцию main с которой и начинается выполнение программы. Она вызывает getUSBHandle, пока мы не получим указатель на устройство, потом читает с клавиатуры комманду и в зависимости от нее, передает и читает данные с USB устройства.
В проекте по ссылке выше лежит исходный код с комментариями и сама скомпилированная программа. Удачи.

В процессе поиска ошибки я наткнулся на библиотеку hidapi. Она является кроссплатформенной. И Только для работы с hid устройствами. Очень проста в использовании. Привожу проект под нее. ссылка .
Hidapi скачан с официального сайта. Для того чтобы начать проект нужно добавить setupapi.lib в линковщик. project->properties->linker->input и подписать туда setupapi.lib;
Удачи.
Нашел пристойное описание библиотеки здесь: http://microsin.net/programming/PC/multi-platform-hid-api.html.
Спасибо!

Но ведь мало только физически подсоединить устройство к компьютеру, нужно еще и наладить обмен данными между ними. Как же выбрать порт и организовать подключение? Несколько лет назад стандартным решением было использование COM-порта. Кстати, до сих пор различные специалисты доустанавливают на промышленные компьютеры по 8, по 16, а то и по 32 COM-порта (есть целая категория различных PCI-плат расширения последовательных портов, контроллеров и т. д.). Таким образом, если нужно подключить несколько внешних устройств с интерфейсом RS-232, могут потребоваться дорогие адаптеры и экзотические платы расширения, которые по старой традиции неделями плывут в Россию на пароходах. Кстати, название обычного переходника «адаптер DB9m/DB25f» у менеджера компьютерного магазина может вызвать разве что раздражение.

Что такое HID-устройство

Сейчас практически все устройства подключаются к компьютеру через USB-интерфейс. Поэтому во многих новых ПК COM-порт отсутствует вообще.

USB-интерфейс - типовое решение по сопряжению нового внешнего устройства с компьютером, точнее, это HID-интерфейс, базирующийся на протоколе USB 1.1.

Хотя многие и считают, что HID-интерфейс (Human Interface Device) предназначен исключительно для клавиатуры, мыши и джойстика, он годится для множества решений, связанных с сопряжением внешних устройств и компьютера.

Если пользователю необходимо производить низкоскоростной обмен данными (до 64 кбит/c) и при этом желательно сократить время на утомительной разработке собственных драйверов, то ему вполне подойдет HID. На выходе же получится простое и вполне современное решение на базе стандартного программного USB-интерфейса с гарантированной поддержкой на всех распространенных программных платформах.

Свойства HID-устройства

С точки зрения организации программной поддержки HID-устройства, все выглядит достаточно привлекательно: для работы под управлением Windows можно быстро создавать понятный компактный код на базе готовых проверенных алгоритмов. При этом у разработчика останется масса времени на реализацию собственного протокола обмена данными верхнего уровня, поскольку необходимый уровень абстрагирования уже организован за счет HID-протокола (см. таблицу). Кроме того, программисту легко проводить отладку написанного протокола обмена (разумеется, при наличии работающего HID-устройства) - благодаря относительной жесткости самого протокола достаточно просто разработать программу поддержки устройства компьютером. Еще бы! Массу работы уже взял на себя создатель HID-устройства.

Организация обмена данными между HID-устройством и компьютером

Чтобы описать взаимодействие HID-устройства с компьютером, употребим термин «хост». В данном случае под ним понимается управляющее устройство в общей физической архитектуре взаимодействия по USB-протоколу. Так, все порты в компьютере - хосты. К ним можно подключать различные USB-устройства (флэшки, мыши, веб-камеры, фотоаппараты и проч.), которые хоста не имеют. Хост обеспечивает обнаружение, подключение, отключение, конфигурирование устройств, а также сбор статистики и управление энергопотреблением.

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

Особенности программирования HID-устройств

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

В Windows за доступ к HID-устройствам отвечает системная служба HidServ. Подробнее о функциях запросов к HID-устройствам и других особенностях работы с HID-драйвером рассказывается в работе П. В. Агурова «Интерфейс USB. Практика использования и программирования» (СПб.: БХВ-Петербург, 2005).

Программирование HID-устройств на «верхнем уровне»

Нелегкую жизнь «прикладных» программистов, работающих на Паскале, облегчает проверенный модуль HID. PAS, программная оболочка для hid. dll (Hid User Library - как указано в свойствах файла). В комментариях к файлу сообщается, что в основе его лежат модули hidsdi.h и hidpi.h корпорации Microsoft. А сам файл HID. PAS - часть пакета JEDI ().

Для работы с HID-устройством в среде Delphi for win32 применяется компонент TJvHidDeviceController, представляющий собой удобный глобальный менеджер для доступа к HID-устройствам. А уже на его базе можно получить объектный экземпляр для работы с конкретным устройством.

Основные свойства и события компонента TJvHidDeviceController

Рассмотрим компонент TJvHidDeviceController более подробно. Событие OnArrival срабатывает на поступление (подключение) в систему HID-устройства, доступ к устройству предоставляется в обработчике этого события через экземпляр класса TJvHidDevice. Простое событие OnDeviceChange реагирует на изменение состояния устройства, оно только сигнализирует об изменениях в системе. Событие OnDeviceData срабатывает при поступлении данных от одного из HID-устройств и передает обработчику следующее: HidDev: TJvHidDevice; - устрой-ство, от которого были получены данные;

Событие OnDeviceDataError уведомляет об ошибке передачи данных, передавая в процедуру обработки параметры HidDev: TJvHidDevice; - HID-устройство и Error: DWORD; - код ошибки. Событие OnDeviceUnplug уведомляет об извлечении устройства из списка установленных в системе. Типы обработчиков событий на Plug и Unplug одинаковы (в исходном тексте: TJvHidUnplugEvent = TJvHidPlugEvent). В обработчик передается объект класса TJvHidDevice, соответствующий HID-устройству.

Для последовательного перечисления имеющихся в системе HID-устройств по вызову метода Enumerate предназначено событие OnEnumerate, т. е. в обработчике события найденные устройства последовательно передаются в виде объектов. Это событие принудительно инициируется методом Enumerate, использующимся для «проведения» имеющихся HID-устройств через обработчик, например при ревизии состояния HID-устройств по инициативе хоста (компьютера).

Событие OnRemoval срабатывает на физическое извлечение устройства из системы и имеет тот же тип обработчика TJvHidUnplugEvent, что и для OnDeviceUnplug. Функция CountByProductName выдает количество устройств, удовлетворяющих указанному в аргументе имени продукта, а CountByVendorName - указанному в аргументе имени производителя.

Основные свойства и события класса TJvHidDevice

Класс TJvHidDevice - виртуальное представление отдельно взятого HID-устройства. Новый объект этого класса можно получить, как было уже сказано, из события OnArrival или OnEnumerate. Функционал классов TJvHidDeviceController и TJvHidDevice частично дублируется, поскольку в первом из них интегрированы общий инструментарий для работы с набором имеющихся в системе HID-устройств и механизм доступа к одному из них. Устройство можно однозначно идентифицировать по свойствам SerialNumber, ProductName и VendorName. Чтобы получить сведения о поступлении данных с применением такого объекта, можно воспользоваться событием OnData. Отсылка данных ведется через метод WriteFile (в строгом смысле - через функцию). WriteFile - это оболочка системной функции WriteFile (kernel32).

Чтобы проконтролировать факт извлечения устройства, следует присвоить свой обработчик событию OnUnplug. Перед началом обмена данными с HID-устройством нужно удостовериться в самой возможности такого обмена с помощью HasReadWriteAccess. В этом классе на возникновение ошибки обмена данными даже есть отдельное событие OnDataError.

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

Метод ScanDevices (листинг 1) предназначен для инициирования процесса поиска в системе необходимого HID-устройства. Большая часть кода, за исключением вызова метода Enumerate, необязательна и обеспечивает гибкость приложения, например, для того, чтобы в эту же тестовую программу можно было добавить возможность работы по интерфейсу, отличному от HID. Метод AddError выводит в окно отладочную информацию в процессе работы программы.

В листинге 2 приведен обработчик события OnEnumerate для поиска необходимого внешнего устройства. Для простоты будем считать, что программа может работать только с одним устройством нужного ей типа.

Прежде чем рассматривать дальнейшую реализацию проекта, следует немного рассказать о принятом формате обмена данными верхнего уровня, т. е. о структуре, призванной быть посредником между методами приема-передачи данных и конкретной решаемой прикладной задачей. Дело в том, что здесь разработчику предоставляется возможность реализовать свои творческие способности. Вернее, разработчикам, потому что процесс создания нового протокола очень часто бывает двусторонним, и при этом первую скрипку играет тот, кому труднее реализовывать алгоритм обмена. В общем, каким бы ни был протокол обмена, всегда приятно делать каждую программную сущность максимально наглядной и самодостаточной, пусть даже в ущерб некоторым общепринятым традициям. Ибо лучшее решение - то, которое будет реализовано в сжатые сроки с минимальной привязкой к программной среде и с большими возможностями дальнейшего развития. На основе этих принципов был создан протокол обмена верхнего уровня, где главное понятие - «команда». Из листинга 3 видно, насколько автор любит строковые данные, не раз спасавшие его при отладке программных модулей. Как же замечательно, что у нас вообще есть тип String! Все команды протокола делятся на категории (классы), внутри которых существует код команды, однозначно характеризующий ее назначение. Параметр edParam служит для отсылки данных в устройство, а параметр edAnswerData содержит в себе полученные от устройства данные. Строковый тип описанных членов записи позволяет свободно и наглядно манипулировать данными в формате HEX-строки. И что самое приятное, формат описанной записи идеологически стоит где-то посередине между ее непосредственным назначением и различными формами ее представления (INI, HEX, XML и т. д.)

Выполнение команды, т. е. отсылка данных в устройство, реализовано с применением отсылки пакетов данных длиной 8 байт (листинг 4). Эта длина - не единственное решение, такой выбор продиктован требованиями протокола верхнего уровня и в каждом конкретном случае может быть другим. Это, что называется, дело вкуса. Странный флаг IsUSBMode в методе ExecuteCommand (листинг 5 на «Мир ПК-диске») оставлен как напоминание о том, что вместо работы с USB нам может потребоваться использовать COM-порт или какой-то другой интерфейс. В начале отсылаемой группы данных в устройство передается синхросерия произвольно выбранного формата (например, 3E3E3E2B), сообщающая устройству, что у него на входе вполне легальные данные. Напомню, что в данном случае речь идет не столько о HID, сколько о специфическом протоколе верхнего уровня, идеологически оторванном от «железа» и предназначенном для решения особых прикладных задач.

В обработчике GetDataExecutor полученных от устройства данных (пакет по 8 байт) использовано специально созданное событие OnNewInputData для передачи первично обработанных данных на дальнейшую обработку, причем с указанием их старого и нового значений (листинг 6 на «Мир ПК-диске»). Таким образом, события поступления необработанных данных и указание на дальнейшую обработку развязываются, позволяя добавлять какой-то специфический алгоритм предупреждения на раннем этапе ошибочной, повторной или ненужной входной информации.

Представленные здесь примеры работы с HID-устройством иллюстрируют общую идею статьи - относительную простоту программирования нестандартных HID-устройств средствами Delphi.