Портал для радиолюбителей
   Разработка микроконтроллерных USB-устройств в среде BASCOM
    Главная -> Статьи -> Устройства на микроконтроллерах -> Разработка микроконтроллерных USB-устройств в среде BASCOM

Надежная шумоизоляция зипс панели цена недорого.

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


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

Спецификацией USB (Universal Serial Bus — универсальная последовательная шина) определено, что среди одновременно подключённых к ней устройств только одно может быть ведущим, в роли которого чаще всего выступает компьютер, а все остальные — ведомые им периферийные устройства. Обмен информацией производится только по инициативе ведущего. Периферийные устройства не могут его начинать сами.

Электрические сигналы, несущие информацию, передаются по паре проводов D- и D+, образующим двунаправленную двухпроводную линию связи. Используется дифференциальный способ передачи — сигналы в проводах одинаковы по форме, но взаимно инверсны. Приёмник воспринимает их разность, а не уровень напряжения относительно общего провода. Логической единицей считается напряжение на входе D+, на 200 мВ большее, чем на входе D-. Логическому нулю соответствует обратная ситуация — напряжение на D+ на 200 мВ меньше, чем на D-.

Кроме информационных дифференциальных, по цепям D+ и D- передают и управляющие синфазные сигналы. Здесь логической единицей считается напряжение выше 2,8, но не более 3,6 В, а нулём — ниже 0,3 В относительно общего провода.

Информация кодируется по принципу NRZI (Non Return to Zero, Inverted — без возврата к нулю с инверсией). Чтобы предотвратить длительное отсутствие перепадов уровня в передаваемом сигнале, применяется "битстаф-финг" — в длинные последовательности разрядов одного логического значения с известным периодом вставляются разряды противоположного значения, автоматически исключаемые из потока на приёмной стороне.

Каждый сеанс связи (транзакция) состоит из пересылок между ведущим и ведомым устройствами нескольких пакетов данных. В них кроме полезной информации содержится и служебная: тип пакета, семиразрядный адрес устройства, номер конечной точки, контрольный код (CRC) и другие необходимые для правильного обмена информацией сведения.

Предусмотрено несколько типов транзакций. Управляющие используются ведущим для настройки ведомого

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

Передачи массивов байтов применяют, когда требуется гарантированная доставка информации адресату, но её время не оговаривается. Например, при работе с принтером или сканером. Обмен по прерываниям используют для пересылки единичных пакетов информации небольшого объёма за ограниченные промежутки времени. Так работают с компьютерной мышью или клавиатурой.

Изохронные передачи ведут, когда необходим обмен информацией в реальном времени, например, при пересылке аудио- или видеоинформации. Однако её доставка в этом случае не гарантирована!

Обработка информации в USB-устройствах (как ведущем, так и ведомых) ведётся на нескольких уровнях. Самый нижний — уровень шины USB. На нём происходит взаимодействие устройств по аппаратному интерфейсу USB, передача и приём пакетов информации.

Средним считается уровень логического USB-устройства. В каждом из них организованы конечные точки (endpoints) — логические источники и приёмники информации, циркулирующей между ведущим и ведомыми.

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

Конечная точка представляет собой выделенную в памяти устройства буферную область, имеющую свой уникальный номер. В каждом устройстве обязательно предусматривают управляющую двунаправленную конечную точку с нулевым номером. Её используют для настройки устройства и определения его текущего статуса. Число дополнительных конечных точек зависит от типа устройства и его конфигурации. Низкоскоростные USB-устройства могут иметь не более двух дополнительных конечных точек, а высокоскоростные — до 15 входных и столько же выходных.

Когда ведущий шины фиксирует подключение к ней нового устройства, он, обратившись к нему по адресу 0, назначает ему уникальный адрес в интервале 1—127. В дальнейшем (до отключения

от шины) устройство будет отзываться только на него. Затем ведущий посылает запрос GETDESCRIPTOR и определяет тип и конфигурацию нового устройства.

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

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

Но когда не требуется большая скорость обмена информацией, то организовать его по USB удаётся программным способом с помощью обычных широко распространённых микроконтроллеров достаточно большой производительности. Например, многие восьмиразрядные микроконтроллеры семейств ATtiny и ATmega, работая на пределе своих возможностей, позволяют реализовать предусмотренный спецификацией USB низкоскоростной обмен информацией (не более 1,5 Мбайт/с). К сожалению, эти микроконтроллеры не обладают достаточными ресурсами для программной реализации высоко- и полноскоростных устройств.

На страницах журнала уже публиковались описания приборов на таких микроконтроллерах, использующих программный USB-драйвер на языке С [1, 2]. Теперь речь пойдёт об аналогичном драйвере, предназначенном для среды BASCOM-AVR. Часть программы, отвечающая за работу с шиной USB и декодирование информации в режиме реального времени, написана на языке ассемблера и оформлена в виде библиотеки (файла Swusb.lbx). Этот файл следует скопировать в папку LIB установленной программы BASCOM. Остальные части драйвера написаны на языке BASIC и находятся в файлах USB_Config.bas, Const_swusb-includes. bas, USB_Descriptor.bas и USB Subroutines, bas. Их включают в разрабатываемую программу.

Файл USB_Config.bas отвечает за конфигурацию драйвера. В самом начале записанной в нём программы подключается библиотека Swusb.lbx и декларируются подпрограммы. Далее выбирается порт микроконтроллера, к

которому будут подключены информационные линии USB. В константах _usb_dplus и _usb_dmjnus должны быть указаны разряды порта, соединённые с контактами D+ и D- разъёма USB. Учтите, для сигнала D+ должен быть выбран вывод микроконтроллера, принимающий внешние запросы прерывания INTO.

Значение константы _usb_use_eeprom определяет, где будут храниться дескрипторы USB-устройства. Если оно равно 1, дескрипторы помещаются в EEPROM микроконтроллера. При любом другом значении они хранятся во FLASH-памяти вместе с программой. Использовать EEPROM имеет смысл только при недостаточности свободного места в программной памяти.

Константами _usb_pid и _usb_vid задают значения PID и VID, идентифицирующие устройство в системе. Одновременно подключать к компьютеру несколько устройств с одинаковыми PID и VID нельзя. Это вызовет конфликты между ними и приведёт к их неправильной работе.

Режим питания периферийного устройства задан константой _usb_powered. Если оно имеет собственный источник питания, эта константа должна иметь значение ОСОН. Если же устройство питается от шины USB, эта константа равна 80Н. В последнем случае константой _usb_maxpower можно указать ток, потребляемый устройством. Ей присваивают значение, вдвое меньшее максимального значения тока в миллиамперах. Например, при _usb_maxpower=100 (десятичное) устройство имеет право потреблять от линии Vbus разъёма USB не более 200 мА.

Если разрабатывается НЮ-устрой-ство, константа _usb_hids должна быть равна 1, в противном случае — 0.

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

Адреса дополнительных конечных


точек задают значениями констант _usb_endp2addr и _usb_endp3addr. Если какая-либо из них для разрабатываемой программы не требуется, соответствующую константу можно "закомментировать" — поставить в начале описывающей её строки символ ' (апостроф) Это освободит немного памяти микроконтроллера, поскольку для неиспользуемой конечной точки не будут выделяться буферы, а из программы будут исключены описывающие её дескрипторы.

Значения констант _usb_endp2direction и _usb_endp3direction определяют, будут ли точки использоваться для передачи информации в компьютер (1) или приёма из него (0). Режим работы точек задаётся константами _usb_endp2type и

_usb_endp3type. При обмене информацией по прерываниям их значения должны быть равны 3.

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

В конце текста программы в неё включают файл Const_swusb-includes.bas, который не следует модифицировать. Здесь вычисляются требуемые размеры массивов и дескрипторов, объявляются константы, переменные и массивы для драйвера. После этого вызывается подпрограмма Usb_reset, инициализирующая USB-драйвер. Обработчиком внешнего прерывания INTO назначается подпрограмма Usb_isr из библиотеки Swusb.lbx. Она будет вызываться при возникновении активности на шине USB и принимать пакеты информации.

В файле USB_Descriptor.bas находятся дескрипторы устройства, описывающие его характеристики и тип. Если создаётся HID-устройство (константа _usb_hids больше нуля), то в программу будет вставлен HID-дескриптор сообщения. По умолчанию он имеет вид, показанный в табл. 1.

Значение константы Size_hid_report-descriptor — длина дескриптора в байтах. Следующие две строки DATA означают, что создаётся нестандартное

USB НЮ устройство. Далее описываются дополнительные конечные точки типов Input и Output. Параметр Report_size определяет длину пакета в битах, а Report_count — число пакетов Указанные в таблице значения этих параметров таковы, что за одну посылку можно принять или передать только один байт Строковые дескрипторы, описывающие изготовителя, продукт и серийный номер устройства, имеют метки_изЬ_ mandescriptor, _usb_proddescriptor и _usb_numdescriptor соответственно. Первые два байта дескриптора — его длина в байтах. За ними следует константа _usb_desc_string, означающая, что это строковый дескриптор, а после неё — символы текста в кодировке Unicode.


Для создания строкового дескриптора можно использовать утилиту Bascom_USB_descriptor.exe, окно которой показано на рис. 1. В его поле "Текст" вводят с клавиатуры или вставляют из буфера обмена Windows текст дескриптора в обычной кодировке и нажимают на экранную кнопку "Преобразовать". В поле "Код Bascom" будет выведен созданный код дескриптора в формате, необходимом для вставки в BASIC-программу. Туда его переносят через буфер обмена.

В файле USB_Subroutines.bas собраны подпрограммы, обсуживающие USB-драйвер. Подпрограмма Usbjefresh повторно инициализирует драйвер при продолжительном отсутствии активности на шине. Её вызывают в главном цикле программы.

Подпрограмма Usb_processsetup обрабатывает системные запросы (так называемые пакеты SETUP) интерфейса USB. Она, например, передаёт дескрипторы по запросу ведущего, присваивает адреса устройствам и выполняет многие другие действия, необходимые для правильного функционирования USB-устройства.

Подпрограмма Usb_senddescriptor передаёт дескрипторы устройства ведущему. Подпрограмму Usb_send

используют для отправки ему информации. Подпрограмма Usb_reset необходима для инициализации USB-драйвера.

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

Для проведения экспериментов нужно собрать устройство по схеме, показанной на рис. 2. Она полностью совпадает с изображенной на рис. 2 в [3]. Напомним, что резистор R1 устанавливает на линии D-напряжение, служащее для ведущего признаком, что к нему подключено низкоскоростное устройство. Выбор выводов 4 и 5 (PD2 и PD3) микроконтроллера для подключения информационных линий шины USB отражён значениями констант _usb_dplus и _usb_dmlnus в файле USB_Config.bas. Он не случаен. В микроконтроллере ATmega8 изменение уровня на линии PD2 может генерировать запрос внешнего прерывания INTO, что используется для организации приёма информации, поступающей от компьютера.

В микроконтроллерах других типов этот запрос может генерироваться перепадом уровня на другом выводе. Это следует учитывать при разработке устройств на различных микроконтроллерах.

Исходный текст демонстрационной программы для микроконтроллера DD1 приведён в табл. 2. Его первая строка включает в программу файл с описанием использованного микроконтроллера. В следующей строке указана его тактовая частота в герцах. После этого задаются размеры аппаратного и программного стеков, необходимые для правильной работы программы.

Директива $include включает в программу ранее рассмотренный файл USB_Config.bas, выполняющий конфигурирование и инициализацию USB-драйвера. Далее линия порта РВО, к которой подключена кнопка, назначается входом, а управляющая светодиодом линия РСО — выходом.

Операторы Dim создают две переменные, предназначенные для хранения информации о текущем и прошлом состояниях кнопки SB1. Каждая из них занимает один байт памяти. Затем разрешается обработка прерываний, что необходимо для USB-драйвера, обра-


батывающего запросы прерывания INTO.

Следующий далее основной цикл программ выполняется всё время, пока работает микроконтроллер. В начале цикла вызывается подпрограмма Usb_refresh, следящая за активностью на шине USB и при необходимости повторно инициализирующая USB-драйвер. Затем с помощью условного оператора IF анализируется состояние разряда _usb_rxc переменной _usb_status, хранящей текущий статус драйвера. При поступлении по USB новой информации условие будет выполнено. В этом случае анализируется состояние разрядов _usb_setup и _usb_endp1 той же переменной.

Выполнение условия _usb.setup=1 означает приём системного сообщения (например, запроса текущей конфигурации устройства) от ведущего. В этом

случае вызывается подпрограмма Usb_ processsetup, в которой обрабатываются эти команды. А вот выполнение условия _usb_endp1=1 при текущей конфигурации драйвера показывает, что ведущий передал информацию в первую дополнительную конечную точку ведомого. Она находится в массиве _usb_rx_buffer.

В рассматриваемом примере младший разряд полученного байта заносится в разряд РС1 регистра порта С микроконтроллера. Это позволяет в зависимости от значения принятого байта включать и выключать светодиод HL1. После обработки полученной информации в разряды переменной _usb_status заносят следующие значения: _usb_rtr — 1, usbrxc — 0. Это сообщает драйверу, что полученная информация обработана и можно принимать следующий пакет.

Далее следует опрос состояния кнопки SB1, подключённой к линии РСО микроконтроллера. Если оно изменилось (кнопка была нажата либо отпущена), то сообщение об этом отправляется в компьютер. Но перед этим, чтобы убедиться в готовности драйвера к передаче, программа проверяет значение разряда _usb_txc переменной _usb_tx_status2. Для передачи содержимое переменной Button копируется в массив _usb_tx_buffer2, после чего следует вызов подпрограммы Usb_send. Её второй аргумент — число передаваемых байтов.

При первом подключении устройства к компьютеру операционная система определит его как USB НЮ совместимое устройство с именем "Демо-уст-ройство". Это имя хранится в строковом дескрипторе продукта, находящемся в файле USB_Descriptor.bas.

ЛИТЕРАТУРА

1. Рюмик С. Подключение джойстиков от игровых приставок к шине USB. — Радио, 2007, №1,с. 28—31.

2. Суров С. Обмен информацией с USB HID устройством. — Радио, 2010, № 3, с. 25—28.

3. Высочанский П. Работа с USB НЮ устройствами в Windows. — Радио, 2011, № 4, с. 27-30.

Скачать дополнительные файлы


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

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

  1. Сопряжение с компьютером цифрового мультиметра серии 830
  2. Устройство ДУ на 12 команд повышенной мощности
  3. "Что позволено Юпитеру", или Почему одни микроконтроллеры надежнее других
  4. Электронные аксессуары для игры S.T.A.L.K.E.R.
  5. USB термометр


Горюнов авто сколько стоит манипулятор эвакуатор качественно


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