Наш магазин на eBay Наш магазин на AliExpress Наш канал в telegram

Интерфейс USB. Часть 5. Программная реализация LS устройства USB. Схема

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

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

Итак, что нам понадобится и что нужно учесть?

Во-первых, понадобятся два пина микроконтроллера для подключения информационных линий интерфейса USB (D+/D-) и ещё три пина для светодиодов.

Во-вторых, на линиях D+/D- используются уровни 0/3,3 В, соответственно, если питание микроконтроллера отличается от напряжения 3,3 В, то нужно будет как-то согласовывать уровни на этих линиях с уровнями на ногах контроллера. Мы будем питать контроллер прямо от разъёма USB (Vcc=+5В), так что для нас вопрос согласования уровней будет актуальным. Здесь нужно учесть, что по даташиту, при питании +5В, минимальное напряжение, воспринимаемое контроллером как сигнал высокого уровня, равно 0.6*VCC, то есть +3В, что позволяет не делать двунаправленный преобразователь уровней.

В-третьих, как вы, наверное, помните, хаб определяет тип подключенного USB устройства (Low Speed или Full/High Speed) по наличию подтягивающего резистора 1,5 кОм на одной из информационных линий. В нашем случае нужно будет подтянуть к питанию линию D-.

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

Скорость передачи на Low Speed равна 1,5 Мбит/с, причём мегабиты и килобиты здесь не настоящие (по 1024 килобайта и 1024 бита), а десятичные (по 1000 килобит и 1000 бит). Так что нам понадобится кварц, частота которого без остатка делится на 1,5. Например, если взять кварцы на 12 МГц (12/1,5=8) или на 18 МГц (18/1,5=12), то передача одного бита данных у нас будет занимать, соответственно, 8 или 12 тактов контроллера. Мы для экспериментов возьмём кварц на 12 МГц.

Теперь давайте подумаем вот о чём. Ресурсы у нас ограничены, поэтому желательно уметь максимально быстро определять начало активности на шине. Тут нам придётся вспомнить, какие у шины бывают состояния и как определяется активность (об этом мы говорили в предыдущих частях этой статьи).

Состояние покоя для LS устройств соответствует длительному состоянию J, которое для LS устройств соответствует сигналу Diff0 (на D- высокий уровень сигнала, на D+ — низкий). Значит начало активности можно определить либо по переходу линии D- к низкому уровню (задний фронт на D-), либо по переходу линии D+ к высокому уровню (передний фронт на D+). Однако, если учесть, что задний фронт на D- может говорить также и о переходе шины в состояние SE0 (для LS-устройств пребывание шины в этом состоянии в течении 2 битовых интервалов обозначает конец пакета, а длительное — disconnect), то наиболее предпочтительным оказывается вариант определения начала активности по переднему фронту на D+. А определить эту активность максимально быстро нам поможет внешнее прерывание INT0. Оно также, как и прерывание Pin Change происходит при изменении уровня на одном из пинов, однако, во-первых, INT0 привязано только к одному, строго определённому пину контроллера (и нам не нужно тратить время, выясняя, по какому именно пину оно сгенерилось), а, во-вторых, мы можем выбрать, по какому фронту (переднему или заднему это преывание генерить). То есть, для максимально быстрой реакции на начало активности, — нужно завести линию D+ на ногу INT0.

Ну вот, теперь, с учётом описанных выше «техусловий», можно ваять схему. Более того, давайте наваяем сразу парочку различных вариантов схем.

Вариант 1 (самый правильный).

схема устройства USB Low Speed на ATtiny2313

Вариант 2 (рискованный, но возможный).

схема устройства USB Low Speed на ATtiny2313

Как видите, во втором варианте мы просто понизили напряжение питания всего нашего устройства, вместо того чтобы заниматься уровнями напряжения на отдельных линиях. Сделать это можно как при помощи интегрального стабилизатора, типа LM1117-3.3, так и просто впаяв в цепь питания последовательно пару-тройку обычных диодов (не Шоттки), поскольку ток в этой схеме совсем небольшой.

Почему второй вариант подписан как «рискованный»? Тут всё просто, — дело в том, что по даташиту, для некоторых модификаций ATtiny2313, частота 12 MHz превышает максимально допустимую при питании 3,3В частоту. При этом эксперименты показывают, что контроллеру на это пофиг, он всё равно нормально работает, но тем не менее факт нарушения заявленных характеристик в этом случае имеет место быть.

Со схемой на этом всё, а в следующей части начнём писать саму программу для контроллера.

  1. Часть 1. Основы.
  2. Часть 2. Как происходит передача данных по шине.
  3. Часть 3. Что должно уметь любое USB-устройство.
  4. Часть 4. Дескрипторы и классы.
  5. Часть 5. Программная реализация low speed устройства USB. Схема.
  6. Часть 6. Программная реализация LS устройства USB. Физика и приём пакетов.
  7. Часть 7. Программная реализация LS устройства USB. Разбираем пакеты по типам.
  8. Часть 8. Программная реализация LS устройства USB. Передача по USB произвольного буфера и пакетов подтверждения.
  9. Часть 9. Программная реализация LS устройства USB. Продолжаем разбираться с принятыми пакетами.

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