Как подключить usb atmega8

Управляем нагрузкой по USB с помощью ПК и ATMega8

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

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

Содержание / Contents

↑ Анализ

Для создания связи устройства через USB-порт с ПК я использовал аппаратный преобразователь USB-UART с использованием микросхемы FT232RL.

↑ Схема структурная

Тут все очень просто и почти не требует пояснения. Вся электрическая часть устройства состоит из следующих элементов:
a) Блок управления включения/выключения нагрузки
b) Микроконтроллер
c) Преобразователь USB – UART
d) ПК и программа управления устройством

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

↑ Схема электрическая принципиальная

↑ А как же это все должно работать?

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

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

↑ Прошивка для МК

Size after:
AVR Memory Usage
—————-
Device: atmega8

> Process Exit Code: 0
> Time Taken: 00:04

↑ Программа для ПК

↑ Сборка

Проект был собран на монтажной плате, ПП не разрабатывалась. Прилагаю к статье файл модели в Proteus 7.6 SP4.

↑ Заключение

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

Спасибо за внимание!

↑ Файлы

Исходники и прошивка МК:
▼ Файловый сервис недоступен. Зарегистрируйтесь или авторизуйтесь на сайте.

Программа управления по USBдля Win:
▼ Файловый сервис недоступен. Зарегистрируйтесь или авторизуйтесь на сайте.

Модель в Proteus 7.6 SP4:
▼ Файловый сервис недоступен. Зарегистрируйтесь или авторизуйтесь на сайте.

Источник

Как подключить usb atmega8

Я хотел создать свое собственное устройство USB на микроконтроллере AVR, поскольку точно знал, что такое возможно. Начал разбираться с проектами USBtiny [2] и V-USB. В процессе исследований оказалось, что достаточно простого руководства по этой теме нигде нет, поэтому решил написать свое (перевод статьи [1]).

Примечание: это руководство не для фанатов Arduino, а для тех, кто хочет самостоятельно с нуля разобраться в том, как работает микроконтроллер. Подразумевается, что читатель имеет представление о таких понятиях, как напряжение, ток, резистор, конденсатор, мультиметр, программатор, AVRDUDE, avr-gcc, make, makefile, фьюзы, USB, хост, дескриптор, энумерация и т. п., или хотя бы готов самостоятельно прогуглить эти термины и разобраться. Рассматривается работа в условиях операционной системы Windows, хотя многие вопросы могут быть решены и на операционных системах Linux (есть некоторые различия, касающиеся устройства программного обеспечения на стороне хоста).

[Питание микроконтроллера]

• Кабель USB и линейка из 4 контактов с шагом 2.54 мм.
• Маленькая макетная плата для навесного монтажа (breadboard) и несколько проводов для перемычек.
• Светодиод (LED) и резистор на 330 Ом.
• Микросхема линейного стабилизатора с низким падением напряжения на 3.3V (Low dropout voltage regulator), наподобие LD1086V33 или LE33CZ.

Кабель USB. Он нужен для того, чтобы подключить к порту USB компьютера наше устройство USB на микроконтроллере. Возьмите обычный стандартный кабель USB, и отрежьте со стороны коннектора USB Type A male кусок достаточной длины, чтобы удобно было подключать Вашу отладочную плату к компьютеру. Обрезанный конец зачистите, и 4 провода шнура распаяйте на линейку контактов. Ниже в таблице показана цоколевка кабеля и цвета проводов. Имейте в виду, что цвета и количество проводов на кабеле USB могут отличаться от приведенных в таблице данных (например, может быть экран кабеля, или другие цвета проводов), поэтому на всякий случай проверьте цоколевку кабеля мультиметром.

№ контакта Цвет провода Назначение
1 Красный VCC (+5V)
2 Белый D-
3 Зеленый D+
4 Черный Земля (общий провод, GND)

Примечание: если Вы хотите узнать больше про коннекторы USB и их электрические сигналы, рекомендую ознакомиться с руководством «USB in a NutShell» от компании Beyond Logic (перевод на русский язык этого замечательного руководства см. по ссылке [5]), и конечно же стандарт USB 2.0. На данный момент достаточно знать, что шина USB может предоставить небольшую мощность для питания подключаемого устройства USB от примерно 5V постоянного тока (обычно не больше 100 мА; максимум может быть 500 мА, если у дескрипторах устройства USB прописано соответствующее значение).

Простой тест кабеля и платы макетирования. Давайте теперь попробуем проверить наш кабель в работе. Рекомендую сначала подключить кабель к хабу USB (или к компьютеру), и мультиметром измерить напряжение на контактах 1 и 4 кабеля (красный VCC и черный GND). Мультиметр должен показать напряжение около 5V (допустимый диапазон около 4.8V..5.2V). После этого на плате макетирования соберите простейшую схему из светодиода и резистора 330 Ом, и подключите туда наш кабель, чтобы провода VCC и GND подали напряжение на светодиод через резистор. Светодиод должен зажечься. Если светодиод не загорелся, то проверьте, не перепутали ли Вы у него полярность, и правильно ли Вы запаяли контакты и собрали схему.

Поздравляю! Теперь если захотите получить 5V питание от USB, не превышая при этом ограничение по току, то Вы знаете как это сделать.

Получение 3.3V. В то время как питание USB осуществляется напряжением 5V, сигналы данных шины USB (D+, D-) требуют логических уровней 3.3V. Если мы подадим питание 5V на микроконтроллер, то он будет работать с логическими уровнями 5V, что будет несовместимым с уровнями сигналов шины USB. В общем случае, как это рекомендуется в руководстве библиотеки V-USB, можно решить проблему согласований уровней сигналов следующими способами:

• Ограничить напряжение питания, поступающее от USB, уровнем 3.3V.
• Подать питание на схему внешнего источника постоянного напряжения 3.3V.
• Использовать резисторы, диоды или стабилитроны (диоды Зенера), чтобы преобразовать уровни сигналов 5V к сигналам уровня 3.3V.

Предлагаю выбрать первый вариант. Второй вариант Вы можете использовать на свое усмотрение, используя понравившийся источник питания. Вариантов много: это может быть 9V батарейка с регулятором напряжения 3.3V, зарядное устройство для мобильного телефона с регулятором напряжения 3.3V, лабораторный блок питания с выставленным выходным напряжением 3.3V, 3 последовательно соединенные батарейки AA и 2 диода (чтобы погасить лишнее напряжение 1.4..1.5 вольта). Для третьего варианта Вы можете взять за основу примеры схем организации интерфейса USB из библиотеки V-USB, или просто прогуглите картинки по ключевым словам zener diode usb. На страничке V-USB wiki есть хороший обзор этих опций (см. [4]).

В этой статье как пример будет рассмотрено использование микросхемы линейного регулятора LD1086V33. Как можно узнать из даташита на эту микросхему, у неё вывод 1 должен быть подключен к общему, минусовому проводу (земля, GND, шасси компьютера), вывод 2 будет выходом стабилизатора (выдает напряжение 3.3V) и вывод 3 вход (на него должно быть подано напряжение +5V от интерфейса USB, красный провод, подключенный к выводу 1 коннектора USB, см. таблицу выше).

Для снижения помех (пульсаций напряжения питания) на входе и выходе регулятора можно подключить фильтрующие (блокировочные) конденсаторы номиналом 1..22 мкф. Получится такая схема:

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

Добавьте в схему фильтрующие конденсаторы на 10..22 мкф рабочим напряжением не менее 6.3V (соблюдая полярность!). Еще раз проверьте правильность всех соединений, и подключите шнур к порту USB.

Светодиод должен загореться. Проверьте мультиметром напряжение на выходе стабилизатора (напряжение между выводами 1 и 2 микросхемы LD1086V33), оно должно быть 3.3V. Теперь все готово к тому, чтобы подать питание на Ваш первый AVR-проект, работающий как устройство USB.

[ATtiny2313, V-USB]

В этом руководстве для создания устройства USB был использован AVR-микроконтроллер ATtiny2313 и библиотека V-USB. Для экспериментов понадобятся следующие детали:

• Макетная плата побольше и дополнительные провода для перемычек.
• Микроконтроллер ATtiny2313.
• Кварцевый резонатор на 12 МГц.
• Два маленьких керамических конденсатора на 22..27 пф (для стабилизации работы кварцевого генератора).
• Два резистора на 68 Ом (они будут подключены между ножками микроконтроллера и сигналами D+ и D- интерфейса USB).
• 1 МОм pull-down резистор для сигнала D+ и pull-up резистор 1.5 кОм для сигнала D-.
• 6-pin коннектор для программирования ATtiny2313 и pull-up резистор 4.7 кОм для вывода RESET микроконтроллера.

READ  Samsung ps42b430p2w как подключить флешку

Примечание 1: по даташиту использование ATtiny2313 на частоте 12 МГц и напряжении питания 3.3V будет вне гарантированного рабочего диапазона (тактовые частоты больше 10 МГц требуют напряжения питания 4.5V или выше). Но обычно микроконтроллер все равно нормально работает в условиях питания 3.3V и тактовой частоты 12 МГц. Если у Вас это не получилось, то используйте напряжение питания 5V, и согласование уровней D+ и D- с помощью стабилитронов на 3.6V (диоды Зенера 3V6).

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

Соединения на плате должны быть выполнены по вот этой схеме:

Для программирования микроконтроллера нужно подключить коннектор ISP.

Сборку можно осуществлять в любом удобном порядке, например так:

1. Соберите схему стабилизатора напряжения на LD1086V33 в одном из углов платы. Вместо подключения 5V от USB к положительной шине питания платы, подключите 5V непосредственно к ножке входа микросхемы стабилизатора.

2. Используйте провода перемычек, чтобы соединить выход генератора и общий провод GND с шинами питания платы.

3. Если на плате есть несколько шин питания, то вы можете соединить их друг с другом для удобства.

4. Дважды проверьте правильность подключения микросхемы регулятора напряжения и полярность подключения электролитических конденсаторов.

5. Подключите USB, и мультиметром проверьте наличие напряжения 3.3V на шинах питания платы.

6. Установите микроконтроллер в плату, и выполните проводами соединения цепей питания, pullup резистора сброса, и 6-pin коннектора программирования.

7. Ваш программатор может подавать питание на программируемый микроконтроллер, то отключите эту возможность.

8. Используйте программатор, чтобы проверить нормальный отклик микроконтроллера (это подтвердит, что микроконтроллер получает нужное питание и работает должным образом).

10. Подключите pulldown и pullup резисторы 1 МОм и 1.5 кОм к сигналам D+ и D- соответственно.

11. Через резисторы 69 Ом соедините D+ и D- с портами PD2 и PD3 соответственно.

12. Подключите кварцевый резонатор 12 МГц к выводам PA1 и PA0 микроконтроллера, и подключите к ним на GND керамические конденсаторы 27 пФ, как это показано на принципиальной схеме.

В результате получится примерно такая конструкция:

На фото ниже показано подробнее, как собран стабилизатор питания, и как подключен кабель от USB. Обратите внимание, что напряжение 5V подключено только ко входу регулятора напряжения и входному фильтрующему конденсатору, и никуда более.

[Простейший тест, мигающий светодиодом]

Если Вы еще не тестировали свой макет с ATtiny2313 на работоспособность, то самое время заняться этим. Самый простой способ тестирования: скомпилировать и прошить в память микроконтроллера вот такую программу:

Эта программа хороша не просто тем, что проста, она дает хорошую возможность понаблюдать, как ускорится программа, когда мы фьюзами переключим тактовую частоту микроконтроллера с 1 Мгц на 12 МГц: светодиод будет мерцать в 12 раз быстрее.

По умолчанию фьюзы микроконтроллера ATtiny2313 (в том состоянии, в каком он приходит с завода Atmel) установлены так, что тактирование происходит от внутреннего тактового генератора 8 Мгц, частота которого поделена на 8. В результате получается тактовая частота 1 МГц. Чтобы в 12 раз ускорить работу программы, нужно, во-первых, фьюзами отключить делитель тактовой частоты (его коэффициент деления должен быть 1) и во-вторых переключить тактирование на внешний генератор с частотой выше 8 МГц и временем запуска 14 тактов + 4.1 мс. Это означает, что в младший байт фьюзов должно быть записано значение 0xEF, что делается следующей командой:

Если Вы используете другой микроконтроллер, или хотите сами разобраться, для чего нужны биты фьюзов и как получить байты значений фьюзов для командной строки AVRDUDE, то пользуйтесь замечательным ресурсом AVR Fuse Calculator [6].

После того, как программатором Вы обновили значение байта lfuse, выключите и включите питание схемы, и проверьте, что светодиод теперь мигает 12 раз в секунду. Теперь обновите значение F_CPU на значение 12000000L, чтобы отразить новую тактовую частоту проекта, перекомпилируйте его и запишите в память микроконтроллера, и светодиод опять начнет мигать с частотой 1 Гц.

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

[Добавление библиотеки V-USB к проекту]

Сначала скачайте последнюю версию библиотеки V-USB с сайта OBdev [3]. Следуйте ссылке Download, и найдите в списке последний по дате ZIP-архив. Дата создания релиза библиотеки представлена в имени файла архива в формате vusb-YYYYMMDD.zip (где YYYY год, MM месяц, DD дата).

Примечание: на момент перевода статьи последняя версия библиотеки V-USB была в архиве vusb-20121206.zip. Если Вы работаете под управлением Linux-системы, то возможно Вам удобнее будет скачать архив в формате tar.gz (файл vusb-20121206.tar.gz).

Также будет хорошей идеей убедиться, что библиотека V-USB укажет в дескрипторах информацию для компьютера, что устройство получает питание от шины USB (т. е. не имеет собственного источника питания), и потребляет максимальный ток 50 мА (по умолчанию обычно задано 100 мА):

Вы наверное знаете, что в каждом устройстве USB имеются специальные лицензируемые идентификаторы VID и PID, которые характеризуют фирму-производителя устройства и его продукт. Мы воспользуемся идентификаторами, любезно предоставленными компанией OBdev, так что здесь нет необходимости что-то менять в конфигурации. Однако Вы можете захотеть поменять имя производителя (vendor name) и имя устройства (device name). Обратите внимание, что в этом примере обратный слеш используется для того, чтобы для удобства разделить имя на 2 части и разместить эти части в 2 строках:

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

Этот код довольно прост для понимания. Здесь выполняется следующее:

• Заголовочный файл usbdrv.h подключается, чтобы можно было получить доступ к функциям V-USB.

• Реализуется функция usbFunctionSetup(), в которой обрабатываются запросы USB от хоста (мы это рассмотрим подробнее).

• В функции main на период 1 секунду настраивается сторожевой таймер (watchdog), который автоматически сбросит микроконтроллер, если вызовами wdt_reset() не сбрасывать сторожевой таймер в течение 1000 мс.

• Вызов usbInit() для инициализации библиотеки V-USB.

• Принудительная повторная энумерация устройства USB с использованием вызова usbDeviceDisconnect(), задержки 500 мс (во время этой задержки сторожевой таймер сбрасывается каждые 2 мс) и вызова usbDeviceConnect().

• Бесконечный цикл, внутри которого постоянно сбрасывается сторожевой таймер и вызывается функция библиотеки обработки протокола USB: usbPoll().

Этот makefile комбинированный, т. е. он используется как для компиляции ПО хоста, так и для компиляции прошивки микроконтроллера, и для управления программатором микроконтроллера, чтобы можно было записать прошивку.

Вы можете использовать отдельные файлы makefile для ПО хоста и для микроконтроллера, за основу берите примеры из пакета библиотеки V-USB [3].

Примечание: имейте в виду, что отступы слева в тексте makefile должны быть обязательно сделаны с помощью символа табуляции, ни в коем случае не пробелов, иначе утилита make будет работать некорректно. Помните об этом, когда редактируете makefile Вашим текстовым редактором (в редакторе текста должны быть заданы специальные настройки, позволяющие использовать символы табуляции).

[Как устройство USB отвечает на запросы управления]

Прежде чем рассматривать программирование на стороне ПО хоста (т. е. программы компьютера, которая обменивается данными с устройством USB), давайте допишем код устройства USB (программа микроконтроллера, т. е. firmware) так, чтобы оно реагировало на 2 основные команды, которые будут посланы через USB: включить светодиод и выключить светодиод. Обмен по шине USB всегда начинается по инициативе хоста, когда он посылает запрос по шине USB. Есть несколько разновидностей запросов, в данном примере будут использоваться так называемые управляющие запросы (control messages). Эти запросы по стандарту используются для того, чтобы устройство могло вернуть хосту свое имя и другие различные параметры, которые хранятся в дескрипторах устройства USB. Стандарт оставляет место и для специальных управляющих сообщений, функцию которых определяет сам производитель (так называемые vendor-specific control message). Давайте определим два таких сообщения:

Библиотека V-USB написана так, что она автоматически вызовет функцию usbFunctionSetup(), когда устройство USB получит vendor-specific control message. В параметре функции data передается указатель на область памяти (буфер, массив из 8 байт), который в действительности содержит структуру usbRequest_t (эта структура определена в файле usbdrv.h). Предлагаю Вам ознакомиться с содержимым структуры. В этот момент нас интересует поле bRequest структуры, которое будет равно либо 0 (что соответствует запросу USB_LED_OFF, погасить светодиод), или 1 (USB_LED_ON, зажечь светодиод). Впоследствии мы увидим, как в ПО хоста создаются такие управляющие запросы, так что ничего магического тут не происходит. Просто со стороны компьютера ПО хоста генерируется заранее известные запросы, и они заранее известным образом интерпретируются на стороне устройства USB. Вот модифицированный вариант функции usbFunctionSetup(), которая будет зажигать или гасить светодиод LED:

Конечно же, чтобы светодиод действительно зажегся, нам нужно было ранее настроить ножку порта PB0 как выход (это делается в начале функции main(), до входа в бесконечный цикл). Советую это сделать сразу после строки «uchar i;»:

READ  Как подключить ксенон на дэу нексия

Скомпилируйте код (для этого выполните сначала команду make clean и затем make hex). Теперь все готово для записи программы в память микроконтроллера. Запишите полученный файл main.hex в память FLASH ATtiny2313. Если у Вас подключен к компьютеру и к микроконтроллеру программатор, соответственным образом сконфигурированный в makefile, то можно просто выполнить команду make flash, и скомпилированный код запишется в память микроконтроллера.

Примечание: чтобы код работал правильно, микроконтроллер должен быть фьюзами сконфигурирован на работу с тактовой частотой 12 МГц (с использованием внешнего кварцевого резонатора).

[Windows: заморочки с драйвером LibUSB]

Если Вы работаете под операционной системой Linux, то поздравляю: все что нужно, это просто скачать библиотеку LibUSB и скомпилировать её вместе с исходным кодом, чтобы получить работоспособное ПО хоста, которое обменивается данными с Вашим новым устройством USB. Однако на Windows для библиотеки LibUSB нужен специальный настраиваемый драйвер устройства (custom device driver). Самое неприятное, что иногда по этой причине старые примеры ПО хоста из библиотеки V-USB не работают под 64-bit Windows 7 (сейчас все поменялось к лучшему, см. примечание ниже). Поэтому я обрисую в общих чертах основные шаги по созданию и установке этого драйвера.

Прим. переводчика: проблема раньше была связана с тем, что есть задержка с появлением совместимых с Windows 7 версий библиотеки LibUSB и драйвера фильтра, и в отсутствии цифровой подписи драйвера. Как декларируется на сайте libusb-win32 [7], начиная с версии 1.2.0.0 библиотека LibUSB поддерживает операционные системы Vista/7/2008/2008R2 64 bit благодаря тому, что Microsoft KMCS (Kernel-Mode Code Signing Walkthrough, система проверки цифровой подписи в режиме ядра) принимает цифровую подпись, встроенную в драйвер ядра libusb0.sys. По крайней мере, лично у меня описанная ниже процедура нормально работает на Windows 7 64 бита. Так что единственное неудобство в том, что эту процедуру нужно проделать, и устанавливать драйвер каждый раз, когда Вы переключаете свое устройство в другой порт USB.

Необходимость в наличии специального драйвера под Windows даже для устройств USB HID это особенность именно библиотеки LibUSB. Есть множество других библиотек под Windows (см. [8]), для которых не нужно устанавливать драйвер, однако эти библиотеки работают по-другому, и для них по-другому пишется ПО хоста.

Итак, процесс установки драйвера по шагам:

1. Перейдите на главную страничку проекта libusb-win32 [7].

2. Найдите заголовок «Device driver installation» (установка драйвера устройства) и следуйте инструкциям для загрузки последней версии. Сейчас текущая последняя версия libusb-win32-bin-1.2.6.0.zip (913.2 кбайт). Распакуйте содержимое архива в отдельную папку с именем libusb, которую создайте в каталоге проекта.

3. Подключите свое устройство USB к компьютеру.

4. Запустите программу inf-wizard.exe, которая находится в подкаталоге bin, и следуйте инструкциям. Эта программа создаст драйвер для Вашего USB-устройства. Рекомендую Вам сохранить этот драйвер в подкаталоге driver, созданном в корневом каталоге Вашего проекта.

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

• Вы можете использовать Менеджер Устройств Windows (Device Manager) чтобы деинсталлировать неправильно установленные драйверы Вашего устройства USB.

• Если Вы получаете сообщение системы об не опознанном устройстве «Unknown device», то возможно проблема в схеме или в прошивке устройства, или следует обновить драйвер устройства.

• При установке драйвера выберите вариант ручного указания пути для драйвера («Browse my computer for driver software»), и укажите Windows папку, в которую Вы сохранили драйвер (в этой папке находится созданный мастером inf-файл). Не обращайте внимания на предупреждения об отсутствии сертификата драйвера («drivers not certified»), и подтвердите установку драйвера без сертификата.

• Обычно Windows корректно запоминает (кэширует) подключение устройства к одному и тому же порту USB, так что не нужно беспокоиться о том, что устройство подключено и отключено к порту USB множество раз. Однако иногда это не так, и переключение устройства к другому порту USB или к другому хабу требует повторной установки драйвера.

• Также для сброса кэша помогает перезагрузка компьютера.

Ниже приведены скриншоты, которые Вы будете наблюдать при запуске мастера создания драйвера (INF-wizard, bin\inf-wizard.exe:

В этом окне можно вручную поменять параметры устройства, если что-то пошло не так (обычно не нужно ничего менять).

После того, как кликните на последнем скриншоте Next, Вам предложат сохранить сгенерированный драйвер (укажите папку driver, созданную в корневом каталоге Вашего проекта). После этого появится окно, где хорошей идеей будет нажать на кнопку «Install now. «, чтобы избежать последующей ручной процедуры установки драйвера. Установка драйвера может длиться довольно долго (нужно подождать 5 минут или более).

[ПО хоста: передача команд в устройство USB]

В предыдущей секции, когда мы разбирали установку драйвера LibUSB, мы уже установили libusb-win32, и все нужные библиотечные и заголовочные файлы есть в наличии (это то, что Вы распаковали в подкаталог libusb проекта). Теперь просто сделайте копию файла со странным именем lusb0_usb.h (копии дайте имя usb.h) в папке libusb/include, все готово к началу работы.

Примечание: для тех, кто захочет лучше разобраться в управляющих сообщениях (control messages), рекомендую на удивление удобный для пользователя стандарт USB 2.0. Раздел, посвященный control messages, начинается на странице 248, и первая таблица должна быть 9-2 (стандарты USB можно найти на сайте usb.org). В стандарте приведены довольно простые и понятные значения констант, которые полностью отражаются операторами #define в библиотеке LibUSB, так что все будет понятнее, если Вы сравните константы и их описание из стандарта с константами, которые будут приведены далее в коде примера.

Если Вас интересует, что делает вспомогательная функция после вызова usb_control_msg, то она просто проверяет возвращаемое значение и длину ответа, и преобразует их из кодировки UTF16-LE к кодировке Latin1 (то же самое, что и ASCII при отсутствии специальных символов). Возвращаемый формат дескриптора USB жестко регламентирован, чтобы исключить любую ошибочную интерпретацию. Все это описано в части 9.5 стандарта USB. Вот код вспомогательной функции (это в основном немного исправленная версия вспомогательной функции, которая используется в примере V-USB PowerSwitch):

Теперь эту вспомогательную функцию мы будем использовать при последовательном просмотре списка всех устройств USB в системе, чтобы распознать именно то устройство USB, которое нам нужно, по vendor name «codeandlife.com» и device name «USBexample». Документация по API библиотеки libusb-win32 дает нам хорошую начальную точку в секции examples. Не буду слишком долго останавливаться на описании, как это работает, основная логика в том, что по циклу опрашивается каждое устройство USB на шине, открывается к нему доступ, и запрашиваются имена device и vendor в устройстве, и в случае совпадения будет успешный возврат, а если совпадения не было, то происходит опрос следующего устройства в системе:

Число 0x0409 код языка для English, это также можно найти в стандарте USB. Обратите внимание, как должны быть получены имена vendor и device с помощью нашей вспомогательной функции – стандартный дескриптор устройства в dev говорит только о значениях параметра, которые нам нужны для использования usbGetDescriptorString(), чтобы получить соответствующие имена (поля iManufacturer и iProduct). Это понятно, поскольку у дескриптора устройства длина постоянная, но у имен vendor и device длина может быть разная.

Обратите внимание, что второй параметр для вызова usb_control_msg теперь использует USB_TYPE_VENDOR, чтобы показать, что теперь отправляются специальные управляющие сообщения, которые определены самим производителем, т. е. нами (vendor-specific control message). Как можно увидеть, параметры request, value и index (здесь USB_LED_ON/OFF, 0, 0) можно свободно использовать в нашем коде на стороне устройства USB.

Вы можете взять этот готовый код в архиве [10]. В файле usbtest.c архива есть две строки с #defines (для USB_LED_OFF, USB_LED_ON) которые соответствуют используемым константам main.c. Скомпилировать код можно, если выполнить команду make usbtest.exe. В действительности можно выполнить просто make, потому что usbtest.exe является одной из целей по умолчанию (makefile default targets). Теперь Вы можете управлять свечением светодиода в устройстве USB, вводя в консоли команды «usbtest on» и «usbtest off». Еще раз обращаю Ваше внимание, что для компиляции кода ПО хоста у Вас должны быть установлен MinGW, и команда gcc в консоли должна запускать компилятор. Компиляция, которая происходит при запуске в консоли команды «make», запустит вот это:

[ПО хоста: передача данных от устройства USB к хосту]

Если Вы внимательно рассмотрели наш код ПО хоста, то вероятно заметили, что для переключения светодиода использовались управляющие сообщения USB_ENDPOINT_IN, и в нашем распоряжении есть буфер размером 256 байт, чтобы получить любые данные, которые отправляет устройство. До сего момента мы не получали данные, и возвращаемое из функции usb_control_msg значение, сохраняемое в переменной nBytes было равно 0. Давайте теперь это изменим.

Если Вы читали документацию в файле usbdrv/usbdrv.h, особенно комментарии, относящиеся к usbFunctionSetup(), которую мы использовали на стороне нашего устройства USB со светодиодом LED, то можете увидеть, что есть два способа вернуть данные из usbFunctionSetup():

READ  Как подключить принтер чтобы он печатал с разных компьютеров

1. Установкой глобального указателя usbMsgPtr на блок памяти (static RAM, статическая оперативная память), где размещены данные, и возвратом длины данных из функции usbFunctionSetup (ранее мы из неё возвращали 0).

2. Создать код функции usbFunctionRead(), чтобы сделать это самостоятельно.

Мы будем использовать первый метод. Сначала определим дополнительное управляющее сообщение USB_DATA_OUT (ранее мы определили сообщения USB_LED_OFF и USB_LED_ON), и статический буфер, чтобы сохранить в нем данные, которые мы хотим отправить из устройства к компьютеру:

Затем добавим еще одну ветку case в функцию usbFunctionSetup() на стороне устройства USB, чтобы передать содержимое буфера к компьютеру:

Неужели так просто. Да, это так, библиотека V-USB берет на себя всю остальную работу.

Теперь выполните make clean и make hex чтобы получить новую прошивку для микроконтроллера, и запрограммируйте её в память ATtiny2313 (или просто выполните make flash, если у Вас подключен программатор, описанный в makefile проекта микроконтроллера).

Теперь всего лишь осталось обновить нашу утилиту командной строки (ПО хоста), чтобы она понимала дополнительную команду «out». Сделайте копию оператора #define USB_DATA_OUT 2 в начало файла usbtest.c (сразу за имеющимися определениями для USB_LED_OFF и USB_LED_ON) и добавьте третий оператор if в функцию main:

Выполните make clean и make, чтобы получить новый исполняемый файл usbtest.exe. Теперь попробуйте выполнить команду usbtest out, что получится? У микроконтроллера ATtiny2313 есть в распоряжении всего лишь 128 байт RAM, и библиотека и сам код программы устройства USB уже частично задействовали эту память, так что нельзя организовать буфер максимального размера из 254 байт (реализуйте функцию usbFunctionRead() так, чтобы она передавала большие блоки данных по частям), однако даже 16 байт это довольно много! И конечно Вы можете соединить в цепочку несколько запросов управления, чтобы передать больше данных.

[Как передать больше данных от хоста к устройству USB]

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

Тем же самым способом, которым мы передали команду для управления светодиодом, можно передать до 4 полезных байт информации, для этого используют параметры wValue и wIndex запроса. Давайте рассмотрим, как это делается. Определите новое управляющее сообщение USB_DATA_WRITE. По нашему замыслу это сообщение будет менять часть «USB!» сообщения на любые другие 4 символа. Как обычно, сначала добавьте новый оператор #define в файлы main.c (программа для микроконтроллера) и в usbtest.c (ПО хоста).

Примечание: Вы наверное заметили, что неудобно каждый раз дублировать один и тот же код сразу в двух местах, как в этом случае, когда мы определяем новые запросы. Поэтому можно создать отдельный заголовочный файл userctrlmessages.h, поместить определения #define для наших запросов (USB_LED_OFF, USB_LED_ON, USB_DATA_OUT, USB_DATA_WRITE) туда, и подключать этот файл директивой #include. Удобство в том, что если нужно изменить управляющие сообщения (или добавить новые), то нужно только отредактировать файл userctrlmessages.h.

Затем нужно добавить новую ветку case в код программы микроконтроллера:

На стороне утилиты ПО хоста добавьте новый оператор «else if», который будет передавать для упрощения просто фиксированный набор из 4 символов (TEST):

Снова, как в прошлый раз, перекомпилируйте firmware для микроконтроллера, прошейте микроконтроллер, перекомпилируйте ПО хоста. Попробуйте выполнить команду usbtest write. Обратите внимание, что в ответ на эту команду ничего не будет напечатано, и результат действия этой команды Вы можете увидеть, если запустите другую команду: usbtest out (до команды usbtest write, и после неё). Будет видно, как изменился буфер ответа командой usbtest write. Также обратите внимание на то, что измененное содержимое буфера «Hello, TEST» будет храниться до тех пор, пока Вы не сбросите или не переподключите устройство USB.

[usbFunctionWrite(): как передать в устройство USB больше 4 байт]

Использование wValue и wIndex подойдет для большинства приложений, но чтобы перезаписать весь 16-байтный буфер, нам потребуется как минимум 4 управляющих сообщения. Попробуем поступить по-другому, и теперь создадим наше первое сообщение USB_ENDPOINT_OUT. Код на стороне компьютера будет очень простым:

Обратите внимание, что размер буфера на 1 больше, чем длина аргумента 2 (т. е. передается strlen(argv[2])+1), чтобы передать также завершающий 0, который показывает окончание строки (string-terminating NULL character). На стороне устройства добавим новую переменную, чтобы запомнить, сколько байт нужно прочитать, и использовать специальное возвращаемое значение из usbFunctionSetup() (это хорошо документировано в файле usbdrv.h):

Теперь запрос будет типа control-out (USB_ENDPOINT_OUT в коде ПО хоста) и мы вернули USB_NO_MSG (со значением размера, ограниченным максимальным значением байта 255, это как раз та причина, по которой данных может быть максимум 254 байта), так что V-USB вызовет функцию usbFunctionWrite() для приема данных от хоста:

Последнее, что нужно сделать, это модифицировать usbconfig.h, чтобы указать V-USB, что бы предоставили функцию usbFunctionWrite():

Снова все перекомпилируйте, перешейте микроконтроллер. Попробуйте выполнить команду usbtest in abcdefgh, чтобы заменить значения в 16-байтном буфере устройства. Имейте в виду, что если Вы предоставите строку больше 15 символов, то завершающий символ NULL второго аргумента ПО хоста уже не поместится в буфер, и команда usbtest out может привести к печати мусора после 16 первых символов. Это просто демонстрационное приложение, в котором для упрощения не добавлены проверки на переполнение буфера.

[usbFunctionRead(): как передать из устройства USB больше 4 байт]

Вы создали свое собственное устройство на микроконтроллере AVR, и разобрались, как передавать ему команды от компьютера, и как обмениваться с устройством USB данными в обоих направлениях. Мы пока не разбирали, как работает функция usbFunctionRead(), но если Вы освоили разобранный здесь пример с usbFunctionWrite(), то легко разберетесь самостоятельно и с usbFunctionRead(). Примеры и документация в библиотеке V-USB есть. Это позволит проще по частям передавать достаточно большие массивы данных из устройства USB в компьютер.

Ниже приведен пример использования usbFunctionRead с микроконтроллером ATtiny85. В конфигурационном файле usbconfig.h сделайте настройку, которая говорит библиотеке V-USB, что должны быть реализованы передачи размером больше 254 байта, и что есть поддержка для функции usbFunctionRead():

Интересно, что если Вы определили использование длинных передач, библиотека V-USB все равно будет использовать переменную размером в байт для хранения длины передачи, так что передачи с использованием функции usbFunctionRead() будут работать неправильно с буферами на стороне ПО хоста длиной больше 254 байта. Так что задайте USB_CFG_LONG_TRANSFERS в 1, и используйте на стороне ПО хоста буфер размером 254 байта или меньше.

По какой-то странной причине стандартный метод V-USB с использованием usbMsgPtr работал нормально с буфером размером 256 байт. Так или иначе, после того, как мы сконфигурировали длинные передачи, возвращаемое значение usbFunctionSetup должно быть изменено. V-USB автоматически определяет usbMsgLen_t, чтобы был корректный тип данных, так что это мы будем использовать. Вот изменения в main.c на стороне микроконтроллера ATtiny85:

Здесь мы используем переменную dataSent, чтобы отследить, сколько байт было возвращено, и делаем выход, как только было отправлено 1024 байта. Как только usbFunctionRead вернет значение меньше, чем len, передача автоматически прерывается.

Изменения со стороны ПО хоста (usbtest.exe):

[Мышь USB HID]

Аббревиатура HID расшифровывается как Human Interface Device, т. е. интерфейс для взаимодействия с человеком. Это специальный класс устройств USB, который распознается операционной системой Windows как стандартный, и в операционной системе уже имеется драйвер для взаимодействия с устройством HID. На устройствах USB HID делаются клавиатуры, мыши и различные устройства ввода/вывода.

На сайте библиотеки V-USB [3] есть много готовых проектов, которые реализуют разнообразные устройства USB HID. Здесь будет рассмотрен пример реализации мыши USB HID, и показаны изменения, которые нужно сделать в шаблоне конфигурационного файла usbconfig.h библиотеки V-USB.

usbconfig.h. Вот что нужно изменить:

1. USB_CFG_HAVE_INTRIN_ENDPOINT следует установить так, чтобы была добавочная конечная точка.
2. USB_CFG_INTR_POLL_INTERVAL установить на 100 мс вместо 10, как было указано в шаблоне.
3. USB_CFG_IMPLEMENT_FN_WRITE это не нужно, так что задайте тут 0.
4. Нужно поменять идентификатор устройства (Device ID) и имя устройства.
5. USB_CFG_DEVICE_CLASS должен быть установлен как 0, а не 0xff.
6. USB_CFG_INTERFACE_CLASS должен быть 3 вместо 0.
7. USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH должен соответствовать длине структуры репорта.

Вот пример таких изменений:

main.c. Обзор изменений:

1. Дескриптор репорта должен предоставлять информацию о состоянии мыши, для чего реализован соответствующая структура.
2. Устройство мыши должно уметь обрабатывать несколько нужных запросов со стороны хоста USB.
3. В главном цикле функции main, когда разрешены прерывания от сигналов USB, нужно отправлять наш буфер репорта.

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

Все примеры исходного кода, рассмотренные в статье, и готовые двоичные файлы Вы можете скачать по ссылкам [10].

Источник

Поделиться с друзьями
Как подключить и установить...
Adblock
detector