Программирование usb порта
Программирование USB в Linux
Одной из популярных тем считается взаимодействие USB-устройств с этой операционной системой. Печатной литературы на русском языке на эту тему не существует, однако имеется много зарубежных источников.
С общими принципами организации работы с USB можно познакомиться в работах Павла Агурова, а здесь будет рассмотрена только одна простая схема, комментирующая принцип работы с любым USB-устройством. В простейшем виде USB-устройство можно представить как некую древовидную структуру, включающую в себя «Конфигурации» (configurations), «Интерфейсы» (interfaces) и «Конечные точки» (endpoints).
«Конечная точка» устройства — это программная сущность, у которой есть свой уникальный идентификатор и которая может иметь буфер с некоторым числом байтов для приема-передачи информации. Но чтобы добраться до нее, приложению (под управлением хоста) нужно программным путем пройти через уровни «Устройства», «Конфигурации» и «Интерфейса». Каждый из них описывается стандартной программной структурой, и есть возможность выбирать, какие именно интерфейсы следует использовать, чтобы попасть в требуемую конечную точку.
Важная особенность USB — наличие только одного Мастера (ведущего), которым обычно является компьютер. Само USB-устройство всегда отвечает на разные запросы компьютера, о чем бы ни шла речь и в какую бы сторону ни передавалась информация.
Разработчик может написать полноценный драйвер для работы со своим USB-устройством, применяя уже имеющийся в системе заголовочный файл linux/usb.h.
Дело в том, что большинство низкоуровневых задач в Linux уже решены, и любая написанная программа будет иметь прикладной характер, хотя формально и получит название драйвера. Справедливо также заметить, что с каждой новой версией ядра Linux работа с USB становится проще.
Драйвер, написанный для поддержки USB-устройства, призван решать следующие задачи:
- регистрация и удаление драйвера;
- регистрация и удаление устройства;
- обмен данными с устройством.
Но можно точно назвать один важный и естественный недостаток, который несет в себе программный модуль уровня драйвера, — платформенная непереносимость.
А как быть, если нет времени писать драйвер, но надо срочно создать программу, работающую с USB-устройством, которая сама будет решать, как, когда и с каким из таких устройств ей работать? Да к тому же хотелось бы, чтобы она легко переносилась на другие платформы (Windows, Mac OS и т.д.) хотя бы с минимальными изменениями в тексте или вовсе без них.
При этом ее требуется писать на Паскале или даже на С#. Возможно ли это? Вполне. Но для этого необходима библиотека libusb (http://www.libusb.org/). Если в дистрибутиве Linux нет такого «зверя» (ничего не отображается в ответ на команду locate libusb.so), то существует несколько путей:
- поставить этот пакет с помощью штатного инсталлятора, к примеру, для Fedora написать в консоли: yum install libusb;
- самостоятельно скачать RPM-пакет (http://sourceforge.net/projects/libusb/) и попробовать его установить;
- скачать пакет «исходников» (http://sourceforge.net/projects/libusb/files/) и собрать на своей машине библиотеку.
Важное замечание. На сайте libusb.org выложены две ветки проекта — версии 1.0 и 0.1. В статье описана работа со старой стабильной версией, по этому будьте внимательны: при использовании версии 1.0, есть расхождения в API.
Чтобы понять, имеются ли в системе устройства, соответствующие USB-интерфейсу, можно, например, воспользоваться утилитой usbview (http://usbview.sourceforge.net) либо ее продвинутым аналогом — usbview2 (http://usbview2.sourceforge.net/), хотя в любом современном Linux найдутся встроенные консольные команды для таких целей.
В этой статье мы ограничимся основами и попробуем разобраться в алгоритме создания аналогичной программы для просмотра устройств USB, только работать она будет в консоли.
А за основу мы возьмем простую программу вот отсюда — http://www.linuxquestions.org/linux/answers/Programming/Developing_Linux_Device_Drivers_using_Libusb_API. Внесем в нее русские комментарии и откомпилируем в режиме программы С++. При этом в настройках компилятора укажем на использование библиотеки libusb.so (листинг 1).
Как видно, этот пример полностью соответствует описанной ранее логической схеме — мы начинаем работу с общего перебора устройств и заканчиваем конкретными логическими точками. В данном примере идет простой перебор всего, что содержится в системе и что имеет отношение к USB. Но так делать необязательно. Для работы с конкретным устройством нас может интересовать определенный код изготовителя продукта (idVendor) и код продукта (idProduct). Если в этом примере уже указанный заголовочный usb.h заменить на , то это будет уже совсем другая библиотека, которую используют для создания полноценных (непереносимых на другие типы систем) драйверов в среде Linux.
Аналогичный пример нетрудно найти в Сети для языка Free Pascal, а значит, несложно написать собственную графическую утилиту, аналогичную usbview, и в среде Lazarus (http://www.lazarus.freepascal.org/).
Для этого потребуется скачать файл libusb.pp (например, здесь http://www.sciencetronics.com/download/fpc_libusb.tgz).
Фрагмент программы, написанной в Lazarus для чтения списка устройств USB (листинг 2) представлен на стр. 58.
Итак, мы выяснили, что в нашем распоряжении языки Си, C++ и Паскаль. Но это не предел, рассмотрим простой пример на языке С# (листинг 3).
В данном примере (который успешно запускается в среде Linux с помощью платформы Mono) для доступа к библиотеке libusb.so применяется специальная .NET-обертка под названием #USBlib. Разработчики утверждают, что она одинаково подходит как для libusb.so, так и для своего собрата, функционирующего под управлением Windows (http://libusb-win32.sourceforge.net/). Кстати, важно отметить, что наборы функций libusb-win32 и libusb совпадают, а особые платформенные различия указаны в документации. Это и есть основное достоинство библиотеки libusb — блестящая платформенная переносимость исходного кода.
В заключение стоит напомнить, что та конкретная задача, над которой мы трудились, используя разные языки и инструментарии, — вывод списка устройств USB, решается в Linux с помощью встроенных команд
Книга: Интерфейс USB (практика использования и программирования)
Хорошая книга, многое объясняет. Пригодится тем, кто хочет понять как происходит передача данных по шине USB.
Обложка:
Обложка
Содержание
Введение 1
Для кого эта книга : 2
Что вы найдете в книге 2
Программные требования 3
Аппаратные требования 4
О программном коде 4
Краткое описание глав 4
Обозначения 6
Благодарности 7
ЧАСТЬ I. ВВЕДЕНИЕ В USB 9
Глава 1. Что такое USB 11
1.1. История USB 11
1.2. Сравнение USB с другими интерфейсами 14
1.3. Основные понятия USB 16
1.3.1. Общая архитектура шины 16
1.3.2. Физическая и логическая архитектура шины 16
1.3.3. Составляющие USB 18
1.3.4. Свойства USB-устройств 18
1.3.5. Свойства хабов 19
1.3.6. Свойства хоста 20
1.4. Примеры USB-устройств 20
1.4.1. Мышь и клавиатура., 21
1.4.2. Мониторы 21
1.4.3. Переходники USB-to-COM и USB-to-LPT 22
1.4.4. Сканеры 23
1.4.5. Модемы 23
1.4.6. Звуковые колонки 24
1.4.7. Флеш-диски 25
1.4.8. Хабы 28
1.4.9. Измерительная техника 28
1.4.10. Экзотические устройства 29
1.5. Сетевое соединение через USB 30
1.5.1. Конвертер USB-Ethernet 31
1.5.2. Прямое соединение через USB-порт 31
1.6. Передача данных 31
1.6.1. Принципы передачи данных 32
1.6.2. Механизм прерываний 32
1.6.3. Интерфейсы хост-адаптера 32
1.6.4. Возможность прямого доступа к памяти 34
1.6.5. Режимы передачи данных 34
1.7. Установка и конфигурирование USB-устройств 35
1.7.1. Настройки BIOS для USB 38
1.7.2. Устранение проблем 41
1.8. Ограничения USB 45
1.9. Если вы покупаете компьютер 46
1.9.1. HS и USB 2.0 — не одно и то же! 46
1.9.2. Системная плата 47
1.9.3. Корпус 48
1.9.4. USB для “старых” моделей компьютеров 48
1.10. Интернет-ресурсы к этой главе 49
Глава 2. Аппаратное обеспечение USB 51
2.1. Кабели и разъемы 51
2.1.1. Типы кабелей 52
2.1.2. Длина кабеля 53
2.1.3. Разъемы 53
2.2. Физический интерфейс 55
2.2.1. Кодирование данных 57
2.2.2. Идентификация устройств 58
2.3. Питание 59
2.3.1. Типы питания USB-устройств 59
2.3.2. Управление энергопотреблением 60
2.3.3. Вход в режим низкого энергопотребления 61
2.4. Интернет-ресурсы к этой главе 61
ЧАСТЬ II. ВНУТРЕННЯЯ ОРГАНИЗАЦИЯ USB 63
Глава 3. Внутренняя организация шины 65
3.1. Логические уровни обмена данными 65
3.1.1. Уровень клиентского ПО 66
3.1.2. Уровень системного драйвера USB 67
3.1.3. Уровень хост-контроллера интерфейса 68
3.1.4. Уровень шины периферийного устройства 68
3.1.5. Уровень логического USB-устройства 69
3.1.6. Функциональный уровень USB-устройства 69
3.2. Передача данных по уровням 69
3.3. Типы передач данных 71
3.4. Синхронизация при изохронной передаче 73
3.5. Кадры 77
3.6. Конечные точки 78
3.7. Каналы 79
3.8. Пакеты 81
3.8.1. Формат пакетов-маркеров IN, OUT, SETUP и PING 83
3.8.2. Формат пакета SOF 83
3.8.3. Формат пакета данных 84
3.8.4. Формат пакета подтверждения
Программирование USB (примеры)
Раздел форума:
admin 17 января, 2000 — 11:12
Автор темы:
Может быть кто-нибудь знает парочку-другую сайтов, посвященных программированию USB, желательно с примерами.
Страницы
Клава 18 января, 2000 — 17:43
МSDN рекомендует www.usb.org.
Юрий 18 января, 2000 — 20:09
Меня в первую очередь интересуют примеры.
И тем не менее, спасибо.
Дмитрий 14 июня, 2002 — 21:27
Savely 15 июня, 2002 — 12:26
2 Дмитрий: Контроллеры USB делают счас все приличные производители. Навскидку — www.cypress.com,
Там погуляй, поищи доки — к этим контроллерам можно прицепить любой свой — на AVR, PIC и т.п.
А теперь вопрос от себя — кто-нибудь в этой стране имеет опыт программирования USB с нуля со стороны хоста (компьютера)? Копал исходники драйверов Linux, исходники Award BIOS, вроде все делаю как надо, но не выходит. Так что есть вопросы.
P.S. Пишущим дрова для USB-устройств под Windows (кроме NT 4.0) просьба не беспокоиться — у вас все по-другому. :-)))
Андрей 8 июля, 2002 — 22:12
Radix 24 декабря, 2002 — 17:28
Savely 26 декабря, 2002 — 11:48
Инкогнито 28 марта, 2003 — 10:26
Vladimir 20 ноября, 2003 — 14:17
Те видео перехват с камеры USB. Зарание благодарен за любую информацию 🙂 — Спосибо
kennobi 23 июня, 2004 — 19:17
Сергей 10 августа, 2004 — 19:20
Андрей 22 декабря, 2004 — 07:52
Может существую какие комоненты под Borland C++ Builder, с помощью которых упрощалась бы задача обращения к USB устройствам?
Заранее благодарен за любую информацию.
Инкогнито 9 мая, 2005 — 21:29
Руслан 11 мая, 2005 — 18:51
Student 14 октября, 2005 — 11:44
написана на асме- под винды, закачиват мелодии через USB в мобилу, там можно вычитать, работает с телефонами моторола
Инкогнито 18 октября, 2005 — 14:31
Интерфейс USB. Практика использования и программирования (+ CD-ROM) (8.4 mb формат djvu) без диска. Пишите на
Инкогнито 13 мая, 2006 — 12:45
mike 13 мая, 2006 — 17:03
В сарае на Купалы исчо есть. С диском. Поспешайте!
Magvays 11 декабря, 2006 — 22:39
Savely 12 декабря, 2006 — 08:28
Savely 12 декабря, 2006 — 08:28
TOMson 4 февраля, 2008 — 15:33
Savely 4 февраля, 2008 — 21:42
Возможно, брежу (дю?). Но вроде как так. Как минимум — я бы начинал копать так.
Savely 4 февраля, 2008 — 21:46
mike 5 февраля, 2008 — 05:30
А зачем различать?
Savely 5 февраля, 2008 — 06:24
Ну, автор про параллельность клавиатур зачем-то упомянул.
TOMson 5 февраля, 2008 — 07:52
в конце это, по идеи должна быть дллка, что бы подключить к лабвью.
Savely 6 февраля, 2008 — 09:09
Вот это совсем не факт. Главное — отличать одну клавиатуру от другой. Интерфейс ее подключения должен быть «по барабану», хоть через RS-232. Т.е. работать надо где-то на уровне Keyboard Сlass драйвера. Или, по аналогии с PS/2, фильтра драйвера USB-клавиатуры (я не совсем представляю весь стек драйверов в случае USB-клавы, для PS/2 — это 8042prt.sys, пример его фильтра есть в DDK).
В принципе можно пробовать сделать наоборот — поставить на PS/2 фильтр-драйвер, который будет говорить «этот код — с PS/2», соотв., остальные коды — с USB.
Но вот практических рекомендаций дать не могу — нет времени и USB-клавиатуры.
Программирование usb порта
Управление USB-устройствами под Windows
Автор: Serg1987, axentfly@yandex.ru
Опубликовано 16.12.2016
Создано при помощи КотоРед.
Написать данный мануал меня сподвигло желание помочь окружающим в вопросе написания программ под Windows для управления USB устройствами, т.к. в сети на этот счет очень мало сколь более менее толковой информации. «Мало??» — удивятся некоторые. Да, мало.. Нет, есть конечно инструкции по написанию софта с использованием всяких внешних библиотек, типа libusb и т.д. Когда передо мной стала задача написания софта под Windows, я тоже смотрел в сторону данных библиотек. Но меня жутко не устраивал тот факт, что при переносе программы на другой компьютер также необходимо было и перекачивать прилагающуюся usb-либу. Многие согласятся, что это весьма неудобно, особенно, если свой продукт вы собираетесь куда-то продвигать. Поэтому было принято решение — сделать всё средствами Windows. Тем более поставляющиеся драйвера и ресурсы от Майкрософта позволяют программистам делать ПО для USB устройств без всяких там libusb или ещё черт знает каких рудиментов. И такие программы без проблем запустятся на других машинах. Кроме установщика ничего копировать не придется. Что ж..
Для начала.. Статья ориентирована на более продвинутых пользователей, нежели чем на начинающих. В статье отсылок к коду будет мало. Для этого смотрите сам проект. Софт писался для устройства USB класса Custom-HID. Оговорюсь об используемом средстве разработки. У меня это C++ Builder Embarcaderro XE7. В Visual Studio настройка проекта и т.п. может быть немножко по другому. Но общий принцип не меняется — и там и там код по сути одинаков. ОС — Windows 7. Проект я прикрепил в архиве. Напоминаю, данный проект работает только в C++ Builder XE7 и выше. Для того, чтобы открыть в более старых версиях, нужно будет выкинуть из кода инициализации некоторые инклуды и описатели (реализация C++ Builder старых и новых версий отличается). В старых версиях проще создать свой проект и скопировать туда приложенный в моем проекте код.
Это было предисловие. Поехали..
Для начала, для того чтобы программировать под Windows для USB вам нужно скачать пакет для разработчиков от Майрософта Windows WDK по ссылке https://www.microsoft.com/en-us/download/details.aspx?id=11800
Качаем и устанавливаем. Пути оставляем по умолчанию. После этого открываем наш Builder. Заходим в свойства Tools->Options и далее в Environment Options->C++ Options->Paths And Directories.. ищем строку System Include Path.. и добавляем следующие пути для хидер-файлов из WDK. У меня пути для h-файлов такие:
Потом добавляем путь для библиотек lib. Всё тоже самое, но на этот раз ищем строку System Library Path.. В данном блоке должны быть прописаны пути:
C:WindowsSystem32
C:WindowsSysWOW64 (нужно также добавить, если у вас ОС 64 бит)
Готово. Переходим непосредственно к программе. В софте имеются 3 кнопки (Connect, Disconnect и Check). Нас интересует прежде всего волшебная кнопка Connect, а именно тот код, который она выполняет. Итак.. Открываем файл Unit2.cpp и смотрим Инициализация USB и поиск устройства осуществляется с помощью функций Windows, подробное описание которых приведено на сайте MS. Все базовые функции для работы с HID на уровне Windows и указатели на них объявляются в начале программы.
Код инициализации (и поиска нашего устройства) — это функция enumd()
Данная функция инициализирует требуемый класс устройств. Более подробно о ней я писать не буду. Если знаете английский, то исчерпывающую информацию можете узнать с сайта мелкомягких.
Далее получаем размеры структур инфы об устройствах и интерфейсе:
dInf.cbSize = sizeof(SP_DEVINFO_DATA);
dIntDat.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
А дальше в хитроумной цикле while поочередно получаем инфу о каждом USB-устройстве, пока те не закончатся)) Из этого перебора читаем данные (VID и PID или ещё чего), с и ищем нужное нам устройство (сравниваем полученные данные с теми, что нам нужны . -> функция connecthid()).
В функции connecthid мы поочередно пытаемся открыть каждое обнаруженное системой устройство. Многие знающие заметят, что тут используются функции, знакомые некоторым по работе с COM-портом. Те же CreateFile и CloseFile. Да, USB устройство открывается как объект файла. А также как и для COM-порта для USB-девайса создаются потоки записи и чтения.
Функция getinfo сравнивает значение VID и PID текущего устройства с искомым. Если такового нет, то ненужное устройство отключается функцией disconhid(), если мы вдруг с ним соединились (не всякое HID устройство можно открыть методом CreateFile). Если устройство успешно найдено, то индикатор на форме меняет цвет с красного на зеленый, а надпись Off внутри него на On. Искомые VID и PID (а также я добавил строку продукта) определены в переменной:
VID и PID тут представлены в десятичном, а не hex-виде.
Это краткий мануал для тех, кто хочет писать ПО для своих девайсов на более низком и качественном уровне, без всяких рудиментарных дополнительных библиотек. Как я и говорил, статья рассчитана на более продвинутых пользователей, но если что — вопросы можете задавать.
Ссылка для скачки самого проекта — внизу.
Исправлено и дополнено (06.07.2017): Друзья, нюанс в данном коде был найден давно. Но я решил дополнить статью сейчас, чтобы некоторые не наступили на те грабли, что и я. Вопрос касается самого порядка инициализации девайса. В проекте инициализация происходит так:
-получаем путь каждого устройства, после чего пытаемся открыть (CreateFile) данное устройство. -После этого считываем методом GetAttribute его VID и PID. -И если устройство не то, то закрываем его (CloseFile).
Друзья, как оказалось, так делать не рекомендуется. Во превых, постоянным вызовом Create/CloseFile расходуются ресурсы памяти, во вторых — при отключении нашего девайса по нажатию на кнопку Disconnect, программа может закрыть потоки другого какого-либо устройства. С целью исправления данной ошибки порядок инициализации должен быть следующим:
1) Находим устройство, получаем его путь в строке. Данная строка в проекте передается как аргумент в функцию connecthid
2) Найдя путь, вычленяем из строки пути искомые VID и PID. Работаем чисто со строкой, девайс не открываем! Для того чтобы понять, какое положение значения VID и PID занимают в строке, советую вывести её куда-либо (какой-нибудь MEMO или StringList). Копируем полученные значения VID и PID в переменные и сравниваем с исходными. Здесь вся работа целиком со строками.
3) Если по пункту 2. VID и PID совпали с искомыми то только сейчас! мы вызываем функцию CreateFile и открываем наше устройство!
V-USB — программная реализация USB для AVR
Содержание статьи
Разработка различных устройств на основе микроконтроллеров — занятие, достойное настоящего компьютерного гика. Несомненно, полезной фишкой любого гаджета будет USB-интерфейс для подключения к компьютеру. Но что делать, если в микросхеме AVR не предусмотрена аппаратная поддержка USB?
V-USB: размер имеет значение
При разработке собственного гаджета часто встает проблема его подключения к компьютеру. Надо сказать, что порты LPT и COM — теперь экзотика на материнских платах ПК, не говоря о ноутбуках, у которых эти интерфейсы исчезли давным-давно. Поэтому у современных компьютеров практически не осталось альтернатив интерфейсу USB.
Если ресурсы чипа используются на все сто процентов, то лучше сразу смотреть в сторону устройств с аппаратной поддержкой универсальной последовательной шины (такие микроконтроллеры присутствуют в линейке любого производителя). В остальных случаях можно использовать софтовый USB.
Для микроконтроллеров Atmel существует замечательный проект V-USB, который предлагает программную реализацию низкоскоростного устройства USB 1.1. Код V-USB будет работать на любом устройстве AVR, у которого есть хотя бы 2 Кб Flash-памяти и 128 байт ОЗУ, с тактовой частотой 12; 12,8; 15; 16; 16,8 или 20 МГц.
Использование продукта возможно как в рамках open source лицензии GPL, так и на коммерческой основе. Для того чтобы разрабатывать собственные USB-устройства, обычно также нужно покупать что-то вроде лицензии. Но ребята из V-USB позаботились и об этом, приобретя пару Vendor ID — Product ID и разрешив их использовать любому желающему.
Аппаратная обвязка для подключения USB-шины к микроконтроллеру очень простая. Если устройство потребляет не слишком много, то запитать его можно прямо от шины (считается, что линия питания USB компьютера способна отдавать ток до 500 мА). Так как информационные линии (D+ и D–) используют уровень сигнала 3,6 В, кроме токоограничивающих резисторов, необходимы стабилитроны для согласования с 5-вольтовой логикой чипа. Чтобы обозначить тип подключения, нужно «подтянуть» напряжение питания через сопротивление 1,5 кОм к линии D–.
Подключение USB к микроконтроллеру ATtiny2313
Хакер #171. 3D-принтеры
Альтернативный вариант сопряжения по USB — снизить напряжение питания контроллера посредством соответствующей микросхемы стабилизации или просто парой диодов. Последнюю схему можно найти на сайте проекта V-USB.
Программатор USBtiny
Для микроконтроллеров AVR существует множество различных программаторов. USBtiny здесь упоминается, в частности, потому, что содержит программную реализацию USB, аналогичную V-USB. Схема этого программатора проста: версия 2 содержит две микросхемы, а первая версия — лишь одну (собственно чип ATtiny2313). Благодаря подробному описанию на сайте и простым комплектующим устройство легко сделать даже начинающему. USBtiny совместим с популярной программой avrdude, используемой для программирования микроконтроллеров AVR.
Единственная проблема заключается в заливке прошивки в чип программатора — для этого нужен… программатор. Если есть компьютер с LPT-портом, то можно сделать один из вариантов FBPRG ака «пять проводков», который железно
Готовим санки
Программный инструментарий, необходимый для реализации простейшей прошивки USB-гаджета, предельно аскетичен: компилятор gcc-avr, библиотека avr-libc, программатор avrdude и набор binutils для AVR. В Debian/Ubuntu все, что нужно, устанавливается одной командой:
Работа с программатором avrdude
На безбрежных просторах интернета несложно найти очень подробное руководство по V-USB и libusb (на английском). Согласно мануалу, для добавления поддержки USB в проект потребуется папка usbdrv из архива с последней версией V-USB. В корне этой папки есть шаблон конфигурации usbconfig-prototype.h. Нужно сделать копию этого файла, назвав ее usbconfig.h. Далее — исправить usbconfig.h, указав порт (D), линии которого будут использоваться для ввода-вывода, непосредственно номера линии D+ (2) и D– (3), а также частоту (12 МГц), на которой работает чип (ATtiny2313):
Чтобы воспользоваться лицензией V-USB для устройства, числовые идентификаторы производителя и устройства изменять не надо. А вот символьные имена можно выбрать по своему вкусу (они позволят отличить несколько устройств на основе V-USB, подключенных к одному и тому же компьютеру):
Разнообразные гаджеты
У тебя есть идея какого-нибудь устройства? Не спеши паять и кодить, а поищи, возможно, кто-то подобное уже делал. Если не получится воспользоваться готовыми схемами и исходниками, то хотя бы не придется начинать все с нуля.
Например, проект V-USB благодаря лицензионной политике накопил приличную базу готовых (в том числе и свободно распространяемых) решений. Здесь можно найти различные реализации клавиатур, USB-адаптеров для джойстиков, геймпадов (в том числе и раритетных, например SNES/NES, Nintendo 64, ZX Spectrum джойстик, Sony PlayStation 1/2) и тому подобное. Адаптеры DMX, виртуальные порты COM и UART, i2c, Servo, беспроводные интерфейсы DCF77, IR — все, что поможет подключить к ПК больше новых устройств. Логгеры, платформы для датчиков и сенсоров, адаптеры для LCD-дисплеев, программаторы и загрузчики также могут оказаться полезными в хозяйстве.
Программа для чипа — элементарно!
При взаимодействии по шине USB компьютер — это главное устройство, которое периодически отправляет управляющие сообщения-запросы. Контроллер, соответственно, подчиненное и должен отвечать на запросы. Формат управляющего сообщения определяется структурой usbRequest_t из файла usbdrv.h:
Создадим файл main.c на одном уровне с папкой usbdrv и опишем в нем необходимые заголовочные файлы, определения и переменные:
Далее научим контроллер принимать данные (DATA_IN) и отправлять их компьютеру (DATA_OUT). Тип запроса указывается в поле bRequest управляющего сообщения.
В main.c переопределим функцию usbFunctionSetup, которая вызывается автоматически при получении нового запроса:
Как видно из листинга, самый простой способ отправить данные компьютеру — установить в usbFunctionSetup значение указателя usbMsgPtr на буфер ОЗУ (replyBuf), где находятся данные, а затем вернуть его длину. Размер буфера не должен превышать 254 байта. Для ATtiny2313 c его 128 байтами ОЗУ этого достаточно. Для более функциональных устройств есть второй способ — переопределение функции usbFunctionRead.
Чтобы получить данные, во-первых, нужно в функции usbFunctionSetup извлечь длину сообщения из поля wLength запроса и сохранить ее в глобальной переменной dataLength. Во-вторых, в main.c требуется переопределить функцию usbFunctionWrite, предназначенную для обработки получаемых данных и вызываемую автоматически (и очевидно, несколько раз), если usbFunctionSetup возвращает значение USB_NO_MSG (255):
Собственно, функция usbFunctionWrite занимается тем, что заполняет буфер replyBuf полученными данными.
Кстати, чтобы этот метод работал, нужно внести изменения в usbconfig.h:
Ну и последняя функция прошивки — main:
Задействуем USART/UART
Хорошая альтернатива программному/аппаратному USB — использование в чипе популярного интерфейса USART/UART со сторонним преобразователем этого протокола в USB, который можно выполнить, например, на основе микросхемы FT232RL.
Libusb: и не одетая, и не обнаженная
Ты спросишь: а придется ли писать драйвер для операционной системы компьютера, чтобы подключить USB-устройство? Если использовать libusb, то можно обойтись без реализации полноценного модуля ядра. Libusb — это open source библиотека, которая позволяет быстро запрограммировать, во-первых, поиск устройства на шине, а во-вторых — обмен данными с ним.
Под Linux библиотеку и необходимые заголовочные файлы можно получить из исходных кодов. А лучше воспользоваться стандартным репозиторием твоего дистрибутива. Для Debian/Ubuntu, например, так:
Существует также порт libusb под Windows — libusb-win32. Вопреки названию проекта, также поддерживаются 64-битные ОС от Microsoft (начиная с версии 1.2.0.0).
Но libusb — это отдельная тема разговора. Думаю, с программированием для ПК ты знаком и сможешь в этом разобраться сам. Поэтому буду краток. Создаем файл usbtest.c и начинаем наполнять его контентом. Сначала необходимые заголовочные файлы и определения:
Функция usbOpenDevice для инициализации устройства:
Как видно, параметрами usbOpenDevice выступают числовые идентификаторы производителя и устройства. В случае если устройство присутствует на шине, возвращается его дескриптор. Если устройств на V-USB будет несколько — придется дописать проверку символьных имен вендора и продукта.
И функция main консольной утилиты usbtest:
Здесь правит бал функция usb_control_msg, которая объявлена во включаемом файле usb.h. Она имеет кучу параметров и собственно создает те управляющие сообщения, обработка которых реализована в прошивке микроконтроллера.
Proteus отдыхает
Всенародно любимый симулятор электрических схем Proteus ISIS бесполезен при разработке устройств с программной реализацией USB. Его эмулятор USB поддерживает только чипы с аппаратной поддержкой универсальной последовательной шины (например, AT90USB646 или AT90USB1286).
Собираем, прошиваем, тестируем
Ниже приведен небольшой, но очень полезный Makefile, c помощью которого командой make из main.c и usbtest.c легко получить прошивку для чипа — main.hex и бинарник утилиты usbtest:
Чтобы залить прошивку в микроконтроллер с помощью программатора usbtiny, набираем команду:
В avrdude фьюзы задаются не слишком наглядно, но их можно легко рассчитать в одном из online-калькуляторов.
Online-калькулятор фьюзов
Подключаем устройство к компьютеру и проверяем, как оно работает (usbtest c параметром out считывает строку, in — записывает указанную строку в буфер чипа):
Тестирование взаимодействия с ATtiny2313 по USB (заливаем в чип строку, а затем cчитываем ее)
Ложка дегтя
Софтовый USB не есть панацея. Программные реализации обычно имеют ряд упрощений, таких как отсутствие проверки контрольной суммы и симметричности канала, что отрицательно сказывается на помехозащищенности. Также обычно софтовые библиотеки используют низкоскоростные режимы работы USB. Да и код USB-библиотеки «кушает» и без того небольшую память чипа.
Подглядываем…
На уровне логики протокол USB — это, по сути, многоуровневая пакетная передача данных. В этом нетрудно убедиться (а заодно узнать много интересного про USB), воспользовавшись анализатором сетевых протоколов Wireshark. Предварительно необходимо загрузить драйвер USB-монитора:
Теперь в списке интерфейсов Wireshark можно выбирать шины USB. Посмотреть номер шины устройства можно, например, в логах.
Перехват USB-пакетов в Wireshark
- Сайт проекта V-USB;
- сайт проекта libusb;
- сайт проекта libusb-win32;
- руководство про V-USB и libusb (англ.);
- статья про libusb, часть 1;
- статья про libusb, часть 2;
- устройства на основе V-USB;
- сайт проекта USBtiny;
- сайт проекта AVReAl;
- online-калькулятор фьюзов.
Заключение
Надеюсь, после того, как ты научился пересылать данные между компьютером и микроконтроллером AVR, твоя страсть к электронике воспылает с новой силой, породив немало оригинальных и полезных устройств. Остается лишь пожелать тебе успехов на этом сложном, но интересном поприще.