<<<   На главную   <<<
<<<  К списку статей <<<


USB CDC на ассемблере для PIC18F4550


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

Скачать обновлённый ассемблерный код можно здесь:
USB_VSTAVKA1.rar

Хочу поделиться своими наработками в области передачи данных от самодельного устройства на микроконтроллере к компьютеру и обратно по шине USB. До этого я мог писать только простенькие программы для обмена данными через COM-порт, но так как сейчас пришла эпоха заката для COM, пришлось переходить на USB. Сразу оговорюсь, что в этой статье я не смогу освещать эту тему на профессиональном уровне,
если вы хотите получить конкурентно способные знания, то идите путем настоящего джедая на сайт www.usb.org.

А теперь по существу. Написал я тут как-то небольшую программку для компьютера, которая обменивается данными с устройством на
микроконтроллере PIC16F876A через COM-порт, но из-за того что на новых компьютерах перестали устанавливать COM-порты появилась
необходимость переделать этот проект на USB. Я узнал, что есть несколько способов это сделать:

Варианты перевода своих разработок на USB

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

- Более простой вариант это взять микроконтроллер с поддержкой USB и готовый драйвер, который входит в состав большинства популярных операционных систем. Вот здесь уже чувствую, что что-то могу сделать, но и здесь есть из чего выбирать, а именно классы USB это HID или CDC. Класс HID мне сразу не понравился, потому что скорость слишком маленькая, а вот CDC это явно то, что нужно. Во-первых, скорость передачи данных не уступает интерфейсу RS232, который используется в COM-портах, а во вторых CDC это и есть COM порт! Да, если вы подключите к компьютеру CDC-устройство, то в вашем компьютере появится виртуальный COM-порт, а это значит, что вносить изменения
в компьютерную программу вашего проекта, работающего с COM-портами, не потребуется, чего правда не скажешь про устройство, подключаемое к компьютеру;

- Самый простой способ перехода на USB это купить переходник COM-USB. Но мне этот способ показался не интересным, потому что хочется чего-то своего родного, что дает моральное удовлетворение от проделанной работы. Но с другой стороны если в вашем проекте по какой-то причине нет возможности использовать специализированный микроконтроллер, то этот вариант вполне оправдан;

Что касается меня, то я остановился на втором варианте.

У фирмы Microchip есть подходящие для этого дела микроконтроллеры  PIC18F2455/2550/4455/4550. Они имеют в своем составе модуль USB.
Я в этой статье буду ориентироваться на микроконтроллер PIC18F4550.

Подключаем своё устройство на PIC18F4550 к USB порту


Итак, нам нужно написать программу для микроконтроллера PIC18F4550. Такую программу чтобы при подключении этого микроконтроллера к компьютеру происходило создание виртуального COM-порта, через который можно передавать и принимать данные. Задачка не из легких ведь, несмотря на то, что в этой микросхеме есть модуль USB общее представление о том, что происходит на шине нужно знать. Модуль USB занимается очень глубокими вещами на очень низком уровне, такими как канальное кодирование, декодирование событий и ошибок, а что касается протоколов транзакций, структуры дескрипторов,  обработки запросов и прочих непонятных словосочетаний должна заниматься управляющая программа микроконтроллера. Значит, чтобы написать эту программу придется все-таки ознакомиться со спецификацией USB и со спецификацией CDC класса? А вот и не обязательно! Хотя конечно желательно. Дело в том, что фабрика Microchip подсуетилась и написала такую программу. Но вот беда написала она ее на языке Си, а кому-то нужно на ассемблере. Здесь пришлось подсуетиться мне и парировать этот проект на ассемблер. Но я не просто переписал этот проект, а взял на себя смелость внести в него существенные изменения. Собственно о том, что у меня получилось я и хочу рассказать в этой статье.

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

Проверочная схема для тестирования связи по USB
Проверочная схема для тестирования связи по USB

и зашить в микроконтроллер эту программу.

После первого подключения появится мастер установки нового оборудования. Для установки укажите путь, в котором предварительно должен находиться вот этот файл. После того как установка драйвера закончится компьютер сообщит что новое оборудование установлено и готово к использованию, при этом в системе должен появиться новый COM-порт с которым можно работать. Теперь давайте проверим наше устройство в работе.

Для экспериментов нам потребуется компьютерная программа, которая принимает и отправляет данные через COM-порт. Эту тестовую программу можно скачать здесь. Ее написал Петр Высочанский за что выражаю ему большую благодарность.

В этой программе выберите новый COM-порт, который появился после подключения нашего устройства к компьютеру. В поле снизу введите число, которое хотите передать в USB устройство и нажмите кнопку отправить. Это число должно отобразиться в двоичном виде на светодиодах. Теперь нажмите кнопку на устройстве, которая подключена к выводу RB4 для отправки этого же числа обратно в компьютер, а программа Петра Высочанского покажет это число в десятичном виде. Вы только что произвели однобайтный обмен в обе стороны по шине USB, поздравляю. Но вы не знаете, как это работает, сочувствую. А нужно ли вам это знать? Давайте продолжим практические эксперименты, после которых я надеюсь, что вы сможете ответить себе на этот вопрос.

Ассемблерная вставка в программу, реализующая USB протокол связи

Здесь скачайте USB-вставку на ассемблере для микроконтроллера и создайте для нее новый проект в MPLAB. Эта USB-вставка не отправляет и не принимает данные, но она может это делать. Для начала прокрутите текст вниз до конца. Вот здесь под меткой USER и находится место, куда вы можете вписывать все, что душе угодно.

Но возникает вопрос, как все-таки отправлять и принимать данные?

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

Но тогда возникает еще вопрос: где-то должна быть область в памяти, которая служит для хранения принятых и отправляемых данных?

Всего таких областей две, одна область отдельно для приема, а другая для передачи. Эти области находятся в третьем банке оперативной памяти, и каждая область занимает по 64 байта. Как вы уже, наверное, догадались область для приема INPUT_BUFFER1-INPUT_BUFFER64, а для передачи OUTPUT_BUFFER1- OUTPUT_BUFFER64.

Использование ассемблерной вставки для работы через USB

Передача данных по USB

Для того чтобы передать данные в компьютер нужно проделать следующее:

1. Выбрать банк памяти 3
2. Установить размер буфера передатчика
3. Записать в буфер передатчика нужные данные
4. Вызвать подпрограмму TX_DATA для передачи данных

Поясняю картину. Для передачи, например числа 12 нужно проделать следующее:

 
            MOVLB           .3  ; Установить банк 3
            MOVLW          .1  ; Размер буфера для передачи 1 байт
            MOVWF          RAZMER_BUFFER , BANKED
           
            MOVLW         .12 ; Число для передачи
            MOVWF          OUTPUT_BUFFER1 , BANKED
            CALL               TX_DATA

Размер буфера можно указать любой от 1 до 64 байта. Например, если нам
нужно передать два байта за 1 раз, то получим такой код:

 
            MOVLB          .3  ; Установить банк 3
            MOVLW        .2  ; Размер буфера для передачи 2 байт
            MOVWF        RAZMER_BUFFER , BANKED
           
            MOVLW        .12 ; Число для передачи
            MOVWF        OUTPUT_BUFFER1 , BANKED
            MOVLW        .12 ; Число для передачи
            MOVWF        OUTPUT_BUFFER2 , BANKED
            CALL             TX_DATA

Вот так просто и понятно можно передать через USB данные в компьютер. А компьютерная программа способная работать только с COM-портом примет их даже не подозревая, что данные пришли от USB. Попробуйте сами сделать
так, чтобы байты отправлялись от нажатия кнопки. Для этого под меткой USER впишите следующее:

            MOVLB          .3  ; Установить банк 3
            MOVLW        .1  ; Размер буфера для передачи 1 байт
            MOVWF         RAZMER_BUFFER , BANKED
            MOVLW        .12
            MOVWF        OUTPUT_BUFFER1 , BANKED
            BTFSS            PORTB , 4 , ACCESS 
            CALL             TX_DATA
            GOTO            USER

Теперь убедитесь, что это действительно работает с помощью компьютерной тестовой программы Петра Высочанского, которая у вас осталась от предыдущего эксперимента. Ну что работает? Конечно, работает!

Приём данных по USB

Теперь давайте также поэкспериментируем с приемом данных.

Для приема данных также как и при передаче нужно установить размер буфера. Если мы установим размер буфера, например 4 байта, а придет 8 то последние 4 байта будут игнорированы. Мало того при приеме данных существует дополнительный индикатор, по которому можно узнать пришли новые данные или нет. Это можно определить по биту №1 регистра FLAG.

А вот как это выглядит на практике:

                    MOVLB          .3  ; Установить банк 3
                    MOVLW        .1  ; Размер буфера для приема 1 байт
                    MOVWF        RAZMER_BUFFER , BANKED

LOOP         CALL             RX_DATA 
                    BTFSS           FLAG , 1 , BANKED
                    BRA               LOOP ; Новых данных нет
 
                    MOVF           INPUT_BUFFER1 , W , BANKED
                    MOVWF       PORTD , ACCESS 
                    GOTO           USER

Установка FLAG , 1 говорит о том, что в буфер приемника (регистры INPUT_BUFFER1-
INPUT_BUFFER64) поступили новые данные от компьютера.
Передать байт устройству можно все той же тестовой программой Петра Высочанского,
которая у вас есть.

В этой USB-вставке можно даже принимать сигналы квитирования линий RTS и DTR их состояние отображается в регистре CONTROL_LINE_STATE, а если точнее то нулевой бит этого регистра отображает состояние DTR, а первый бит состояние RTS.
Но я думаю при USB передачах аппаратную синхронизацию делать необязательно, ведь в данном случае спецификация USB гарантирует безошибочную передачу данных, но иногда хочется подстраховаться, это уж на ваше усмотрение какой протокол хотите делать такой и делайте.

Еще немаловажная деталь. От вызова подпрограмм TX_DATA и RX_DATA, а также от прерываний модуля USB регистры W, STATUS, BSR и все регистры косвенной адресации, а также табличного чтения и аппаратного умножения не изменяются!!! Их сохранением и восстановлением занимаются специальные подпрограммы. Так что за содержимое этих регистров можете, не беспокоится. Все остальные регистры специального назначения, которые изменяются это регистры модуля USB. К тому же перед отработкой USB-вставки регистр FSR2 обнуляется для поддержки
индексного адресного смещения, но потом он как я уже говорил, восстанавливается.

Ну а теперь на всякий случай о том, что вы и сами прекрасно понимаете. Я имею в виду, что ваша программа естественно не должна использовать те регистры, которые использует эта USB-вставка, иначе возникнет конфликтная ситуация и все пойдет под откос. Исключением может быть регистры буферной зоны для приема или передачи данных. Ваша программа не должна влиять на работу USB модуля, в том числе запрещать прерывания кроме тех случаев, когда нужно запретить прерывания ненадолго, например, при записи данных в EEPROM.
Не используйте команду SLEEP для перехода в режим sleep или idle. В режиме sleep вы перекроете кислород модулю USB, так как отключите его тактирование, а в idle долго не задержитесь, так как прерывание USB переключит экономичный  режим PRI_IDLE в неэкономичный режим PRI_RUN.

Эта USB-вставка не использует EEPROM память данных, поэтому она полностью в вашем распоряжении. Несмотря на то, что в этом примере применяется кварц на 20МГц тактирование ядра микроконтроллера и периферии происходит на частоте 48МГц. Эта частота получается путем деления выходной частоты ФАПЧ на 2. И вообще если захотите изменять тип тактового генератора и экономичного режима не забывайте про
модуль USB. Следите за тем, чтобы на его входе было 48МГц.

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

Ну, вот вроде бы и все. Таким образом, не зная даже поверхностного описания премудростей, которые творятся на шине USB можно принимать и отправлять данные.







Батов Игорь Александрович
Сайт автора :    http://startusb.narod.ru








7 сентября 2009 года

<<<  К списку статей <<<
<<<   На главную   <<<






Rambler's Top100


Hosted by uCoz