Портал для радиолюбителей
   Работа с USB HID устройствами в Windows
    Главная -> Статьи -> Компьютерная электроника -> Работа с USB HID устройствами в Windows


<< Назад в раздел   Распечатать Дата добавления: 2011-04-10 | Просмотров: 46798

П. ВЫСОЧАНСКИЙ, г. Рыбница, Приднестровье, Молдавия

В связи с постепенным исчезновением СОМ- и LPT-портов из современных компьютеров радиолюбителям приходится искать альтернативные интерфейсы для связи разрабатываемых ими микроконтроллерных устройств с компьютером. Обычно выбирают порт USB, поскольку он присутствует в каждом современном компьютере. Этому способствует наличие недорогих и доступных микроконтроллеров со встроенным модулем USB. A при достаточной производительности и свободных ресурсах можно реализовать работу USB программными средствами микроконтроллера.

Разработка драйвера USB-устройст-ва для компьютера не каждому под силу, так как это требует немалых знаний и специального набора компьютерных программ. Выходом из данной ситуации может быть создание USB-уст-ройств класса HID (Human Interface Device — устройство взаимодействия человека с компьютером), драйверы для которых имеются в операционной системе.

К НЮ относятся, в частности, USB-кла-виатуры, мыши, джойстики и другие средства ручного ввода информации. Тип устройства должен быть задан в специальной логической структуре, называемой дескриптором сообщения. Спецификацией НЮ предусмотрен тип "нестандартное устройство", которым можно пользоваться для обмена произвольной информацией. Это позволяет создавать различные конструкции с интерфейсом USB — термометры, программаторы, вольтметры, которые компьютер воспринимает как НЮ, хотя фактически они таковыми не являются. Для работы с НЮ в операционных системах семейства Windows предусмотрены так называемые API-функции, находящиеся в системных библиотеках "hid.dir, "setupapi.dll", "kernel32.dll" и некоторых других. Эти функции позволяют не только работать с НЮ, но и узнавать некоторые параметры его кон-Г.турации, которые требуются, напри-

мер, для определения оптимального объема буферов приема и передачи.

Чтобы упростить работу с НЮ, был разработан компонент приложения — динамическая библиотека подпрограмм (DLL), названная "HID_Lib_Plus". Она создана в среде PureBasic 4.41 на основе исходного текста разработанной мной ранее библиотеки пользовательских функций "HIDJJb". Собственно, поэтому ей и было дано такое имя. В

отличие от "HID_Lib", которая предназначена исключительно для PureBasic, "HID_Lib_Plus" можно использовать в любой среде программирования, поддерживающей вызовы функций из динамических библиотек, например в Visual Studio или Delphi.

Библиотека HID_Lib_Plus содержит 16 функций, рассматриваемых ниже.

Функция HID DeviceTest(PID, VID, VersionNumber, Index) определяет, подключено ли к компьютеру устройство с требуемыми идентификаторами. Их задают в первых трех аргументах. Эти идентификаторы можно увидеть в окне свойств устройства "Диспетчер устройств" Windows. В приведенном на рис. 1 примере подключенное устройство имеет VID — АВ80, РЮ — F4EF, VersionNumber — 2. Учтите, все эти значения — шестнадцатеричные числа. Аргументом Index указывают требуемое устройство, когда к компьютеру их подключено несколько с одинаковыми иден-

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

Функция HI DO pen Device (PID, VID, VersionNumber, Index) открывает доступ к устройству перед началом работы с ним. Назначение ее аргументов и их размерность такие же, как и у функции HID_DeviceTest. При успешном получении доступа (устройство должно быть доступно для записи и чтения) функция возвращает целое число, так называемый handle — идентификатор устройства, назначенный операционной системой. Он необходим для работы большинства других функций библиотеки, имеющих одноименный аргумент. Такой подход позволяет одновременно работать с несколькими НЮ.

Функция HID CloseDevice(Handle) завершает работу с НЮ и освобождает все ресурсы компьютера, использовавшиеся при работе с ним. Ее параметр — идентификатор устройства, полученный ранее с помощью функции HID_OpenDevice. В случае успешного выполнения заданной операции будет возвращено число, не равное нулю.

Функция HID_ReadDevice(Handle, "buffer, Len) читает информацию из НЮ, точнее, из его конечной точки типа INPUT. Она помещает полученную информацию в буфер, созданный в оперативной памяти компьютера. Указатель на начало буфера нужно передать этой функции во втором аргументе. Третий аргумент — объем буфера в байтах. Его значение должно быть на единицу больше заданного в дескрипторе сообщения устройства. Если это условие не соблюдено, произойдет ошибка. Функция возвращает число принятых байтов. Как правило, оно равно заданному объему буфера, но может отличаться от него в случае ошибки приема.

Функция HID_WriteDevice(Handle, *buffer, Len) передает информацию устройству через конечную точку типа OUTPUT из указанного вторым аргументом буфера. В остальном логика ее работы аналогична функции HID_Read Device.

Особенность функций HID_ReadDevice и HID_WriteDevice заключается в том, что они не возвращают управление вызвавшей их программе до завершения чтения или записи информации. Это приводит, например, к тому, что при чтении программа "зависает", пока от НЮ не поступит весь ожидаемый информационный пакет. Поэтому для чтения и обработки информации рекомендуется создать в программе отдельный поток.

Функции GetlnputReport(Handle, *buffer, Len) и НID_SetOutputReport (Handle, *buffer, Len) — альтернатива рассмотренным выше функциям НЮ_ ReadDevice и HID_WriteDevice. Они не ожидают завершения чтения или записи, но доступны только в операционных системах, начиная с Windows XR При успешном выполнении функция возвращает число, не равное нулю (как правило, 1).

Функции HID_GetFeature(Handle, *buffer, Len) и HID_SetFeature(Handle, *buffer, Len) выполняют операции соответственно чтения и записи информации, если HID для обмена информацией использует FEATURE-сообщения, передаваемые через нулевую конечную точку. Эти функции ожидают завершения приема и передачи, но, благодаря специальному механизму обмена, зависания программы при приеме не происходит. При успешном выполнении функции возвращают число, не равное нулю (как правило, 1).

Функция HID_GetCaps(Handle, *Ca-pabilities.HIDP_CAPS) позволяет получить некоторые сведения о конфигурации НЮ. Они будут помещены в стандартную структуру HIDP_CAPS, указатель на которую должен быть передан во втором аргументе. В табл. 1 приведено описание структуры на языке C++. На интернет-сайте www.microsoft.com можно найти подробные сведения о ней.

Наибольший интерес в этой структуре представляют члены InputReportByte Length, OutputReportByteLength и FeatureReportByteLength. Они позволят правильно рассчитать размеры буферов приема и передачи информации.

Функция HID_GetNumlnputBuffers (Handle) позволяет узнать размер буфера, в котором временно хранится информация, отправленная устройством, но еще не прочитанная программой.

Функции HID GetManufacturerString (Handle), HID_GetProductString(Handle) и HID_GetSerialNumberString(Handle) позволяют получить сведения соответственно о разработчике устройства, его названии и серийном номере. Каждая из них возвращает указатель на строку содержащего запрошенную информацию текста в кодах ASCII или Unicode (в зависимости от версии использованной библиотеки "HID_Lib_Plus").

Функция HID_Devicelnfo(*Struct. HID_Devicelnfo) помещает в структуру HID_Devicelnfo, указатель на которую должен быть передан в качестве аргумента, список всех НЮ, подключенных к компьютеру и их конфигурацию. Описание структуры HID_Devlcelnfo на языке PureBasic приведено в табл. 2. Переменные с префиксом w имеют тип Word и

занимают по два байта памяти компьютера, а переменные с префиксом s — строкового типа. В приложении к статье можно найти утилиту "HIDJnfo", основанную на использовании данной функции.

В качестве примера рассмотрим работу с несложным USB HID, схема которого показана на рис. 2, собранном на микроконтролле-

ре ATmega8-16PL Программа микроконтроллера была разработана в среде BASCOM-AVR версии 1.11.9.8 с использованием USB-драйвера swusb.LBX. В программную память микроконтроллера следует загрузить файл Demo_ Device.HEX, а конфигурацию установить в соответствии с рис. 3.

С этим устройством работает компьютерная программа, названная Demo_Device, несколько модификаций которой можно найти в приложении к статье. Окно этой программы показано на рис. 4. Нажатиями на имеющиеся в нем экранные кнопки можно включать и выключать светодиод HL1 (см. рис. 2). Контролируется и состояние кнопки SB1 (0 — не нажата, 1 — нажата).

Исходный текст этой программы на языке PureBasic приведен в табл. 3. Константами #USB_PID и #USB_VID заданы идентификаторы устройства. По ним его будет опознавать операционная система компьютера Далее

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

Прежде всего, функция Open Library пытается открыть библиотеку HID_Lib_Plus.dll. Если сделать это не удается, на экран выводится сообщение об этом и работа программы завершается. При успешном открытии библиотеки имеющиеся в ней функции объявляются с помощью операторов Prototype и вызовов функции GetFunction.

По таймеру каждые 400 мс вызывается процедура FindDevice_Timer, а при каждом ее вызове с помощью функции HID_DeviceTest определяется, подключено ли устройство НЮ к компьютеру. Если подключение зафиксировано, программа с помощью функции HID_OpenDevice получает два идентификатора этого устройства — для чтения и для записи.

Необходимость в отдельных идентификаторах связана с тем, что функция чтения HID_ReadDevice после вызова ждет поступления информации от устройства. Наличие разных идентификаторов позволяет выполнять запись информации, не дожидаясь завершения чтения.

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

Процедура ReadDevice_Thread, работая в отдельном потоке, читает информации из устройства. В начале работы она создает локальный массив переменных байтового типа (на что указывает префикс Ь). Этот массив — буфер для хранения принятой информации. Прием выполняется в бесконечном цикле Repeat—ForEver.

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

Процедура SendDevice отправляет информацию устройству. Буфером передачи служит массив OutBuffer. В его нулевой элемент также заносится идентификатор сообщения, равный нулю, а в первый элемент помещается предназначенный для передачи байт из переменной Led. Функция HID_WriteDevice передает информацию из буфера в устройство.

В основной части программы создаются главное окно программы (функцией OpenWindow) и элементы ее пользовательского интерфейса. После этого активируется таймер, который каждые 400 мс в отдельном потоке, созданном с помощью функции CreateThread, запускает процедуру ReadDevice_Thread.

В цикле Repeat—Until располагается обработчик событий программы. Идентификатор текущего события он определяет с помощью функции Wait WindowEvent. Обрабатываются три типа событий:

— срабатывание таймера (вызывается процедура FindDevice_Timer);

— нажатие на экранную кнопку (вызывается процедура SendDevice, передающая информацию HID);

— закрывание окна (выполняется заданное в операторе Until условие выхода из цикла, что прерывает цикл и завершает работу программы).

Библиотека "HID_Lib_Plus" была скомпилирована в четырех вариантах: для 32- и 64-разрядных операционных систем Windows и с кодированием текста ASCII и Unicode Работа библиотек проверена в операционных системах Windows 98 SE (только HID_Lib_Plus.dll), Windows XP и Windows 7. При выборе версии библиотеки следует исходить из типа создаваемого приложения. Например, если требуется создать Unicode-приложение для 64-разрядной операционной системы, следует использовать библиотеку, хранящуюся в файле HID_l_ib_Plus_Unicode_x64.dll.

В папке "Примеры" приложения к статье есть несколько программ с исходными текстами на языке PureBasic, которые демонстрируют основные возможности рассматриваемой библиотеки. Это уже упомянутая программа Demo_Device, разновидность которой есть также на языках Delphi 7 и VB.NET Программа Demo_Device_lnfo отображает сведения о демонстрационном устройстве, используя для этого функции HID_GetCaps, HID_GetManufacturer String, HID_GetProductString и HID_ GetSerialNumberString.

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

Программа PicKit2_Test демонстрирует работу с программатором PICkit 2 фирмы Microchip, который также для компьютера представляет собой HID. После ее запуска на секунду включится светодиод "Target" программатора. Затем он будет выключен, а программа завершит работу, не создавая никаких окон.

Программа USBJHID предназначена для работы с устройством, описанным в статье С. Сурова "Обмен информацией с USB HID устройством" ("Радио", 2010, № 3, с. 25—28). При его повторении не удалось приобрести микроконтроллер ATmega88, поэтому пришлось немного модифицировать программу микроконтроллера, чтобы она работала на имеющемся в наличии ATmega8. Загрузочный файл модифицированной программы USB_HID_ATmega8.hex имеется в приложении. Внесенные изменения не затронули работу USB и протокол обмена информацией, поэтому программа USBJHID будет работать как с оригинальной версией устройства на ATmega88, так и с модифицированной на ATmega8.

От редакции. Файлы-приложения к статье находятся на нашем FTP-сервере по адресу <ftp://ftp.radio.ru/pub/2011/04/HID_Lib_Plus.zip>.


Добавил:  Павел (Admin)  
Автор:  П. ВЫСОЧАНСКИЙ, г- Рыбница, Приднестровье, Молдавия (Радио №4, 2011 г.)  

Вас может заинтересовать:

  1. Соединение компьтеров через COM порты по двум проводам
  2. Устройства чтения СИМ карт (3 варианта)
  3. Автоматическое включение персонального компьютера
  4. Дистанционное управление (ДУ) на инфракрасных (ИК) лучах
  5. Связь на IRDA(для подключения к материнке)


    © PavKo, 2007-2018   Обратная связь   Ссылки views: 6901 -- users: 6765 -- web3   Яндекс.Метрика