Программирование PC Использование библиотек LibUSB и V-USB в проектах QT Mon, September 25 2017  

Поделиться

нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


Использование библиотек LibUSB и V-USB в проектах QT Печать
Добавил(а) Евгений Воронцов   

Библиотека Qt и сопутствующая ей среда разработки Qt Creator составляют очень удобное в использовании средство для создания кроссплатформенных программ на С++. Хорошую документацию и множество примеров можно найти как на английском, так и русском языках (например, [1-3]), и сама IDE Qt Creator хорошо русифицирована. Механизм слотов и сигналов, который лежит в основе Qt, отлично подходит для создания хост-программ управления USB устройствами на базе микроконтроллеров AVR (производитель Atmel). Для решения такого рода задач успешно используются библиотеки V-USB [8] и libusb [9]. Однако примеров использования libusb совместно Qt для управления USB-устройствами на основе V-USB на просторах Интернета найти довольно трудно. В этой статье описывается разработка программы для компьютера (далее она будет называться для краткости ПО хоста), которая управляет макетной платой с микроконтроллером AVR (простое управление светодиодом). Приводятся два варианта ПО хоста – консольный и с оконным интерфейсом.

[Особенности установки библиотеки libusb в случае ее использования в проектах Qt]

Библиотека libusb позволяет осуществлять связь между компьютером (хостом) и USB устройством. Установка библиотеки libusb в WinXP хорошо описана в статье [4]. Поэтому вкратце остановлюсь на основных моментах, связанных с Qt. Для использования libusb в Qt проектах необходимо:

1. Скачайте библиотеку libusb-win32-bin-1.2.6.0 (или более свежую), см. [9] или возьмите distrib\libusb-win32-bin-1.2.6.0.zip из архива [10].
2. Распакуйте libusb-win32-bin-1.2.6.0.zip в любую папку, например, C:\temp.
3. Из папки \bin\x86 скопируйте файл libusb0_x86.dll в папку c:\WINDOWS\system32, и переименуйте в libusb0.dll, а файл libusb0.sys скопируйте в папку c:\WINDOWS\system32\drivers\ (процедура описана в файле \bin\libusb-win32-bin-README.txt).
4. В корне C:\ создайте каталог libusb и скопируйте туда папку \include. Папка include содержит заголовочные файлы, ссылающиеся на функции библиотеки libusb. Также создайте в каталоге libusb папку \lib и скопируйте туда файл \lib\gcc\libusb.a. Это двоичный код библиотеки libusb, который будет использоваться в программах Qt.
5. Скачайте драйвер фильтра libusb-win32-devel-filter-1.2.6.0, см. [9], или distrib\libusb-win32-devel-filter-1.2.6.0.exe. После запуска инсталлятора у Вас в системе появится программа мастера Filter Wizard. Она позволяет накладывать на устройства USB специальный драйвер фильтра. Он нужен для нормальной работы библиотеки libusb с устройствами USB. Процесс установки фильтра хорошо описан в [4].

Теперь немного о системе лицензирования Qt. В настоящее время существуют бесплатная (с лицензией LGPL) и коммерческая версии Qt. Между ними есть отличия в функционале [5]. В частности, в бесплатной версии нет возможности статической линковки. А это значит, что файлы библиотек, используемых в конкретном проекте, приходится вручную складывать в папку с программой. Иначе она не запустится на другом компьютере (где не была установлена Qt). Если просто вручную скопировать все необходимые dll в каталог исполняемого файла программы Qt, то можно перенести скомпилированную программу на другой компьютер (об этом далее).

Для разработки проектов, описанных здесь, применялся пакет QtSDK 1.2.1 [6]. Его установка не вызывает проблем [7]. Нужно просто скачать инсталлятор (доступен в offline и online режимах работы, см. скриншот окна браузера).

QT-installator-select

После того, как скачаете пакет инсталлятора QT, запустите его. В окне выбора элементов установки нужно не забыть выбрать установку компилятора MinGW (расставьте галочки, как на скриншоте ниже, у пунктов Desktop -> Qt 4.8.1 -> Desktop Qt 4.8.1 - MinGW).

QT-install-setup

[Управляемое из Qt устройство USB HID]

Для создания готового устройства USB удобно воспользоваться готовым решением, которое представлено в библиотеке V-USB [8] - пример простейшего устройства USB HID, проект hid-custom-rq (см. distrib\vusb-20121206.zip или папку firmware в архиве [10]). V-USB является реализацией драйвера USB для устройств на базе микроконтроллеров AVR, т. е. можно делать USB-устройства разных стандартных классов на обычных микроконтроллерах AVR. Программное обеспечение для этих устройств USB пишется на языке С.

Для получения исходного кода библиотеки V-USB вместе с примерами программ следует скачать архив с библиотекой vusb-20121206.zip с сайта obdev.at (или взять его в архиве [10], см. distrib\vusb-20121206.zip) и распаковать его в любом удобном месте. В директории с библиотекой нужно найти папку examples, а в ней hid-custom-rq. Исходный код для микроконтроллера AVR лежит в папке \examples\hid-custom-rq\firmware. Для того, чтобы Вы смогли скомпилировать исходный код AVR, Вам потребуется пакет WinAVR (инструментарий GCC для разработки программ на C для микроконтроллеров AVR). Процесс установки WinAVR и компиляция проекта подробно описана в статье [4]. Если Вы не хотите пока в этом разбираться, можете воспользоваться готовыми прошивками (файлы *.hex), которые находятся в папке firmware\hex архива [10].

AVR-USB-MEGA16-common-view

В нашем случае макетная плата AVR-USB-MEGA16, прошитая firmware hid-custom-rq, и есть то USB устройство, которым будем управлять из Qt. Задача состоит в том, что бы научиться включать/выключать светодиод (он расположен на плате AVR-USB-MEGA16) с помощью сигналов, передаваемых по USB интерфейсу от компьютера. Эти сигналы будет обрабатывать микроконтроллер AVR, смонтированный на плате (ATmega32A).

[Консольный вариант ПО хоста на Qt]

Для создания консольного ПО хоста, достаточно код примеров из папки \examples\hid-custom-rq\commandline просто добавить в новый консольный проект Qt и сделать несколько настроек. Алгоритм создания консольной программы управления светодиодом по шагам:

1. В программе Qt Creator создайте новый проект вида "Простой проект на языке С".

QT-project-create

2. Перенесите в проект файлы set-led.c и opendevice.c из папки \examples\hid-custom-rq\commandline\ в проект. Для этого используется окно проектов в окне Qt Creator. Нужно выбрать проект и щелкнуть правой кнопкой мышки. В появившемся меню выберите «Добавить существующие файлы».

QT-add-files-to-project

3. В файле set-led.c удалите все имеющиеся директивы #include и замените их на

#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#include "opendevice.h"
#include "requests.h"
#include "usbconfig.h"
#include < lusb0_usb.h >

4. В файл проекта Qt (имеет расширение .pro) добавьте строки

win32: LIBS += C:/libusb/lib/libusb.a
win32: INCLUDEPATH += C:/libusb/include
win32: DEPENDPATH += C:/libusb/include
win32: PRE_TARGETDEPS += C:/libusb/lib/libusb.a

Это позволит линковщику найти правильные пути к файлам заголовков (*.h) и к двоичному коду библиотеки libusb (файл libusb.a). Убедитесь, что указанные здесь пути соответствуют реально существующим.

5. Скопируйте заголовочные файлы opendevice.h из папки \examples\hid-custom-rq\commandline\ и файлы requests.h, usbconfig.h из папки \examples\hid-custom-rq\firmware\ в папку C:\libusb\include (которая была ранее создана на диске и добавлена в пути файла проекта Qt). В файле opendevice.h замените строку "#include < usb.h >" на "#include < lusb0_usb.h >":

//#include < usb.h > 
#include < lusb0_usb.h >

6. Теперь проект готов к компиляции. Зайдите в меню "Сборка" и выберите "Собрать все". Затем в том же меню – Запустить.

QT-project-compile

Для передачи в командную строку параметров вызова программы setled (status, on, off) нужно указать их в поле «Параметры» во вкладке «Проекты->Запустить».

QT-set-command-line-options

Вид консольного окна для работы с программой set-led-console.exe:

set-led-console-usage

[Создание ПО хоста Qt с графическим интерфейсом (GUI)]

Среда Qt предоставляет широкие возможности для создания пользовательского интерфейса. Для этого можно использовать специальную утилиту Qt Designer. Но в данном случае удобно использовать классы компоновки Qt. Они представляют собой своеобразный холст, на котором располагаются все интерфейсные элементы. Кроме того, классы компоновки содержат в себе методы, задающие взаимное расположение элементов. Более подробную информацию о компоновках Qt можно найти в книге [3].

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

1. Создайте новый проект «Qt Widget->GUI приложение Qt» на основе базового класса QDialog.

Название файла исходников можно заменить на dialog.cpp. Галочку "Создать форму" нужно убрать. Таким образом будет создан новый проект. В нем уже есть готовые файлы main.cpp, dialog.cpp, dialog.h, SetLedGUI.pro.

2. В файле main.cpp добавьте директивы #include:

#include "opendevice.h"
#include "requests.h"
#include "usbconfig.h"
#include < lusb0_usb.h >

3. В функцию main необходимо поместить код для инициализации устройства:

usb_dev_handle *handle = NULL;      //указатель на устройство
const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID}, 
            rawPid[2] = {USB_CFG_DEVICE_ID};
char vendor[] = {USB_CFG_VENDOR_NAME, 0}, 
        product[]={USB_CFG_DEVICE_NAME, 0};
int vid, pid;
usb_init();
vid = rawVid[1] * 256 + rawVid[0];
pid = rawPid[1] * 256 + rawPid[0];
 
// Функция usbOpenDevice реализована в модуле opendevice.c.
if(usbOpenDevice(&handle, vid, vendor, pid, product, NULL, NULL, NULL) != 0)
{
   int n = QMessageBox::critical(0, "Error",
           QString("Could not find USB device with \
           vid=0x%1 pid=0x%2 "
).arg(vid,0,16).arg(pid,0,16), QMessageBox::Cancel); if (n==QMessageBox::Cancel) exit(1); }

4. Вся логика программы реализована в слоте SetLEDSlot(void) (что такое слоты и сигналы Qt, см. в [3] или в справочной документации [1, 2]).

При каждом нажатии на кнопку в МК посылается запрос - горит ли светодиод (LED)?

сnt = usb_control_msg(Dev,
                      USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_ENDPOINT_IN, 
                      CUSTOM_RQ_GET_STATUS,
                      0,
                      0,
                      buffer,
                      sizeof(buffer),
                      5000);

По результатам запроса выставляется флаг isOn:

isOn = buffer[0] ? 0: 1;

Затем посылается команда на включение или выключение светодиода.

cnt = usb_control_msg(Dev,
                      USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_ENDPOINT_OUT,
                      CUSTOM_RQ_SET_STATUS,
                      isOn,
                      0,
                      buffer,
                      0,
                      5000);

5. Для создания интерфейса используется класс компоновки QHBoxLayout.

В конструкторе класса dialog происходит инициализация интерфейса и соединение сигнала нажатия кнопки со слотом SetLEDSlot().

Dialog::Dialog(usb_dev_handle* handleDev,QWidget *parent)
    : QDialog(parent, Qt::WindowCloseButtonHint)
{
  Dev = handleDev;                           // инициализация устройства
  SetLEDButton = new QPushButton("Set LED"); // создание кнопки
  QHBoxLayout* MainL = new QHBoxLayout;      // создание компоновки
  MainL->addWidget(SetLEDButton);            // располагаем кнопки на компоновке
  setLayout(MainL);
  // соединение сигнала нажатия кнопки со слотом обработки
  connect(SetLEDButton, SIGNAL(clicked()), this, SLOT(SetLEDSlot())); 
}

Вот и вся программа. Компиляция GUI-проекта Qt проводится точно так же, как и для консольного варианта. Если все собрано верно, то после запуска выполняемого файла (software\GUI\exe\release\set-led-gui.exe) появится маленькое окошко с кнопкой. Если её нажимать, то будет зажигаться и гаснуть светодиод на подключенной макетной плате AVR-USB-MEGA16.

set-led-gui-window

[Как сделать программу Qt переносимой]

Полезно знать - что нужно сделать, чтобы можно было готовую скомпилированную программу Qt перенести на другой компьютер (с сохранением работоспособности, конечно). Обычно для этого может использоваться статическая линковка всех используемых библиотек Qt, либо создание инсталлятора, который позволит автоматически установить на компьютере все нужные библиотеки Qt. Как уже было упомянуто выше, бесплатная версия Qt не позволяет осуществлять статическую линковку. Это конечно неудобно. Не устанавливать же Qt на каждом компьютере, где вы собираетесь запускать программу! В Интернете умельцы описывают различные способы исправления этого недостатка (естественно без покупки лицензии). Но если не стремиться к "красивым решениям", то можно просто скопировать все используемые библиотеки, с которыми связан проект, в одну папку с программой (где находится исполняемый файл *.exe), и уже эту папку переносить на любой компьютер в любое удобное место (обычно это место c:\Program Files).

Для определения зависимостей от библиотек существуют специальные программы (например, Dependency Walker [11]). Некоторые из сборок популярного файлового менеджера TotalCommander также позволяют узнать зависимости файлов exe (через встроенный просмотрщик файлов). Запустите Total Commander, установите курсор на интересующей программе и нажмите F3. На экране появится окошко, где нужно выбрать вкладку "Dll Dependency". В списке указаны пути к файлам библиотек, которые использует программа при работе. Теперь их легко найти и скопировать в папку с исполняемым файлом exe.

TotalCommander-DLL-dependency-show

В архиве [10] предоставлены исходные коды проектов Qt и откомпилированные версии программ, вместе со всеми библиотеками.

[Ссылки]

1. Qt Documentation site:qt-project.org.
2. Qt документация (на русском языке) site:doc.crossplatform.ru
3. М. Шлее Qt 4.5 Профессиональное программирование на С++.
4. Разработка устройства USB - как начать работу с библиотеками V-USB и libusb.
5. Почему выбирают коммерческую лицензию Qt? site:digia.com.
6. Qt SDK 1.2.1 site:developer.nokia.com.
7. Установка Qt SDK под Windows site:github.com.
8. V-USB site:ru.wikipedia.org, V-USB site:obdev.at.
9. libusb-win32 site:sourceforge.net.
10. 130705QT-and-LibUSB.zip - архив с документацией, исходным кодом, библиотеками, прошивками микроконтроллера AVR.
11. Dependency Walker - помощник в разрешении зависимостей.

 

Комментарии  

 
0 #1 ATH 27.04.2014 13:06
Спасибо, будет ли написанная программа на gt работать на linux?

microsin: будет, просто перекомпилируйт е на Linux.
Цитировать
 

Добавить комментарий


Защитный код
Обновить

Top of Page