Каталог статей

Главная » Статьи » Мои статьи

Практическое использование интерфейса USB в контроллерах PIC18Fa
C чего начинаем и что нужно.

Железо
1. Сам микроконтроллер
2.Кварцевый резонатор на 4, 8, 12, 16, 20 мегагерц –любой из них- на ножки OSC1 и OSC2.
3.Разъем usb b , чтобы использовать стандартный шнурок для usb. Землю – на землю, d- d+
на соответствующии ножки микроконтроллера (RC4/D- RC5/D+ ). Vusb пусть повисит пока в воздухе.
4.Источник питания на 5 вольт. +5 – на vdd, землю на vss.
5. 2 светодиода для индикации состояния контроллера и ограничивающие ток резисторы к ним – (я поставил по 300 Ом) к ножкам RD0 и RD1 и на землю.
6.Конденсатор 0,1 мкф на вывод vusb и на землю.
7.Резистор килоом 5 на MCLR и на vdd.
8.Конденсатор 0.33 мкф с MCLR на землю.
9.Конденсаторы – керамика на питание –много не бывает.

Этого – и плюс программатор, естественно, достаточно для запуска проекта.

Сразу оговорюсь об использовании столь любимого всеми программатора IC-PROG. Даже последняя версия на сайте 1.06 очень криво работает с 18 пиками. Впрочем, не буду обобщать о всех – но с этим точно.Используйте winpic800. Ссылку не даю, в инете полно – и он бесплатный.

Компилятор

1. Компилятор берем отсюда – « Ссылка » MPLAB C18 Student Edition – для получения ссылки на закачку нужно региться , а также попутно
2. « Ссылка »
Нормальную версию.
3. Делаем из студенческой версии нормальную. В принципе, можно оставаться и на студенческой, только раз в 2 месяца ее нужно сносить и ставить по новой. Вся операция проходит безболезненно. Но можно это обойти. Для этого :
Качаем отсюда « Ссылка »
Распаковщик
Сначала устанавливаем студенческую версию , затем распаковываем нормальную (инструкция внутри архива) и заменяем файлы из студенческой версии распакованными.
С компилятором все. Не забудьте в MPLAB установить язык.

Исходники
Все находится в одном файле
« Ссылка »
Запустив, мы получаем на диске С каталог с названием MCHPFSUSB. С ним и будем работать.

Теория
Итак, всего к компу может быть подключено 128 usb устройств.
Номер устройства назначается самой системой. Обмен происходит кадрами (фреймами). Инициатором обмена является только сама система, наше устройсво самостоятельно ничего не делает. Кадр состоит из посылок, посылки состоят из транзакций, транзакция состоит из пакетов. Пакеты начинаются с поля синхронизации, затем идет идентификатор пакета, затем инверсия поля идентификатора (check), потом, при необходимости – данные и затем – поле конца пакета. Пакеты бывают 4 типов –
Маркер – пакеты ( идентификаторы – setup, in, out ,sof ) пакеты данных (data0 data1 и пр.) пакеты подтверждения (ASK NAK STALL ) и специальные пакеты (ERR RING).
Уже из того, что каждый пакет имеет уникальный идентификатор, следует то, что тот самый идентификатор должна иметь точка, которые эти пакеты принимает (формирует).
Конечная точка (endpoint, EP – в проге на С) – это часть юсб устройства, имеющая уникальный идентификатор и является получателем или отправителем информации. Как минимум, в каждом устройстве их 3. Самая главная –это 0 точка. При включении (сбросе) она обязательно должна быть доступна системе.Собственно, это единственный случай, когда система напрямую читает инфу из устройства – из 0 точки, весь остальной обмен идет через драйвер.
Следующие конечные точки – ходят парами – in и out. При получении инфы из 0 точки (только через драйвер) ОС получает их дескрипторы.
Итак по тактам
1. Включение USB устройства – устройство переходит в состояние powered (кушать подано).
2. Хаб его замечает.
3. Хаб информирует ОС о новом устройстве и посылает на 0 точку запрос GET_STATUS
Устройство возвращает 16 – разрядное слово состояния, в котором разряды 15:2 зарезервированы и должны содержать 0
1 разряд – 0 – не реагируем на сигнал пробуждения
1 – откликаемся
0 разряд - 0 – получаем питание от шины
1- свое
4. Устройство, если оно хочет быть высокоскоростным, подтягивает ножку D+ к напряжению 5 вольт, а если низкоростным, то ножку D-. Хаб меряет разность потенциалов и посылает согласие /несогласие на устройство
Нас это не касается – наш микроконтроллер может быть или низкоскоростным (1,5 мегабита ) или полноскоростным (12 мегабит ). Высокоскоростным он быть не может.
5. Хаб сбрасывает устройство запросом SET_FEATURE
6. После сброса устройство находится в состоянии default state – основное состояние.
7. Хост посылает устройству запрос GET_DESCIPTOR
В ответ приходит 8 байт дескриптора
Ценного в этой информации есть только размер пакета для 0 точки, остальные данные пока не юзаются. Итак
0 байт – размер дескриптора в байтах (8)
1 байт – тип дескриптора (у нас дескриптор устройства, код будет 6)
2,3 байт – номер версии
4 байт – код класса
5 байт - код подкласса
6 код протокола
7 минимальный размер пакета для 0 точки.
8.Хост наконец назначает устройству его уникальный адрес (0 – 127, если помните)
Это происходит подачей запроса SET_ADRESS. С этого момента устройство переходит в состояние adressed.
9.Опять считываем кофигурацию (дескриптор устройства), но на этот раз уже по – взрослому. Запрос GET_DESCIPTOR уже идет по новому адресу устройства. Именно здесь уже считывается заявленный от устройства ток, число конфигураций, поля поля vendor, product id , необходимые системе для поиска драйвера и много, много всего…
10. Ищем драйвер, устанавливаем его и посылаем устройству SET_CONFIGURATION. Все, устройство переходит в состояние сконфигурировано (configured).

Практика.

1. Делаем заготовку (пустой проект с поддержкой usb).

. Заходим в MCHPFSUSB->fw ->CDC
и видим искомый проект. Обилие каталогов и файлов в котором сразу слегка расстраивает. Не все так страшно. Присмотримся внимательно к main.c


*****************************************************************************/

void main(void)

{

    InitializeSystem();

    while(1)

    {

        USBTasks();         // USB Tasks

        ProcessIO();        // See user\user.c & .h

    }//end while

}//end main



/*****************************************************************************

Наша задача - ProcessIO() находится cdc\user , что и будем менять, все остальное мы практически не трогаем.
Сразу предупреждаю, если откомпилить пример, прописать хекс и спаять соответственно схему – не полетит. В смысле, не заработает, потому что в проекте не установлена конфигурация. Видимо, рассчитано на то, что условия должны вибирать сами.
Итак, кварц. Он не должен быть с дробным значением и должен делиться на 4. Это может быть кварц на 4, 8, 12, 16, 20, 24, 40 и 48 мегагерц. Что есть, то и ставим, выбирая значения делителя в PLLDIV. Результат деления должен составлять 4 мегагерца.Если я поставил кварц на 20, то PLLDIV должен быть равен 5. Это значение частоты необходимо для синхронизации периферии USB. Вернее, это значение умножается и тогда уже идет на периферию USB . Значение частоты для синхронизации ядра и периферии ядра процессора мы можем тоже взять оттуда, установив FOSC = HSPLL_HS и CPUDIV = OSC1_PLL2 . В таком случае частота ядра у нас будет максимально возможная – 48 мегагерц. Чтобы не забыть, прописываем прямо в маin.c


/** I N C L U D E S **********************************************************/

#include <p18cxxx.h>

#include "system\typedefs.h"                        // Required

#include "system\usb\usb.h"                         // Required

#include "io_cfg.h"                                 // Required



#include "system\usb\usb_compile_time_validation.h" // Optional

#include "user\user.h"                              // Modifiable

//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

#pragma config FOSC = HSPLL_HS, USBDIV = 2 ,PWRT = OFF,BOR = OFF

#pragma config PLLDIV = 5, CPUDIV = OSC1_PLL2

#pragma config WDT = OFF, WDTPS = 128

#pragma config VREGEN = ON,MCLRE = ON,LVP = OFF,ICPRT = OFF

#pragma config XINST = OFF,DEBUG = OFF

//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Далее, идем в каталог user и уничтожаем там все, кроме файлов user.c и user.h.
Да и самы файлы не щадим, оставляя в них только индикацию состояния контроллера на 2 светодиодах.- BlinkUSBStatus. Вот как выглядит файл user.c после чистки


/*****************************************************************************

* CDC RS-232 Emulation Tutorial Instructions:

* /

/** I N C L U D E S **********************************************************/

#include <p18cxxx.h>

#include "system\typedefs.h"

#include "system\usb\usb.h"

#include "io_cfg.h"             // I/O pin mapping

#include "user\user.h"

/** V A R I A B L E S ********************************************************/

#pragma udata

/** P R I V A T E  P R O T O T Y P E S ***************************************/

void BlinkUSBStatus(void);

/** D E C L A R A T I O N S **************************************************/

#pragma code

void UserInit(void)

{

    mInitAllLEDs();

//  ----------------------------------------------------------------------------------------------------------------

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

//   здесь  мы инициализируем свои переменные

//  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

}//end UserInit

/******************************************************************************

* Function:        void ProcessIO(void)

*****************************************************************************/

void ProcessIO(void)

{  

    BlinkUSBStatus();

    // User Application USB tasks

    if((usb_device_state < CONFIGURED_STATE)||(UCONbits.SUSPND==1)) return;

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

//  начало главного цикла нашей     программы    

//        

//  окончание  главного цикла нашей программы

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!    

}//end ProcessIO

//-----------------------------------------

/******************************************************************************

* Function:        void BlinkUSBStatus(void)

*****************************************************************************/

void BlinkUSBStatus(void)

{

    static word led_count=0;

    if(led_count == 0)led_count = 500U;

    led_count--;

    #define mLED_Both_Off()         {mLED_1_Off();mLED_2_Off();}

    #define mLED_Both_On()          {mLED_1_On();mLED_2_On();}

    #define mLED_Only_1_On()        {mLED_1_On();mLED_2_Off();}

    #define mLED_Only_2_On()        {mLED_1_Off();mLED_2_On();}

    if(UCONbits.SUSPND == 1)

    {

        if(led_count==0)

        {

            mLED_1_Toggle();

            mLED_2 = mLED_1;        // Both blink at the same time

        }//end if

    }

    else

    {

        if(usb_device_state == DETACHED_STATE)

        {

            mLED_Both_Off();

        }

        else if(usb_device_state == ATTACHED_STATE)

        {

            mLED_Both_On();

        }

        else if(usb_device_state == POWERED_STATE)

        {

            mLED_Only_1_On();

        }

        else if(usb_device_state == DEFAULT_STATE)

        {

            mLED_Only_2_On();

        }

        else if(usb_device_state == ADDRESS_STATE)

        {

            if(led_count == 0)

            {

                mLED_1_Toggle();

                mLED_2_Off();

            }//end if

        }

        else if(usb_device_state == CONFIGURED_STATE)

        {

            if(led_count==0)

            {

                mLED_1_Toggle();

                mLED_2 = !mLED_1;       // Alternate blink                

            }//end if

        }//end if(...)

    }//end if(UCONbits.SUSPND...)



}//end BlinkUSBStatus

/** EOF user.c ***************************************************************/

Восклицательными знаками выделены мои комментарии.
И, наконец, последний шаг – комментируем в файле C:\MCHPFSUSB\fw\Cdc\autofiles\usbcfg.h строчки


#define MODE_PP                 _PPBM0

#define UCFG_VAL                _PUEN|_TRINT|_FS|MODE_PP



//#define USE_SELF_POWER_SENSE_IO здесь

//#define USE_USB_BUS_SENSE_IO здесь

Все, заготовка готова. Запустив компилятор, получаем код .Предупреждения могут быть, но не должно быть ошибок.
Загрузив hex в процессор, даем питание, подсоединяем к usb. Устройство должно опознаться системой и потребовать драйвер. Он находится здесь –
C:\MCHPFSUSB\fw\Cdc\inf\win2k_winxp\
Будет сообщение, что драйвер не является сертифицированным, все равно продолжить- и в конце установки обе лампочки должны замигать попеременно – устройство сконфигурировано.

2. Делаем что-нибудь полезное.
Подключим 2 далласовских термометра, например. Я подключил их к ножкам RB2 и RB3. Особенного мистического смысла в выборе именно этих ножек нет, они на разъеме у меня были следующими. На +5 от них резистор 4,7 кОм, землю датчиков – на общую землю, питание – на +5. Заходим в файл конфигурации io_cfg.h и добавляем туда следующее


//----------------------------------------------

#define gr0                 LATBbits.LATB2

#define gr1                 LATBbits.LATB3

#define gr0_set            TRISBbits.TRISB2  

#define gr1_set            TRISBbits.TRISB3

#define gr0_read            PORTBbits.RB2

#define gr1_read            PORTBbits.RB3

#define gr0_On()            gr0=1;

#define gr1_On()            gr1=1;

#define gr0_Off()            gr0=0;

#define gr1_Off()            gr1=0;

#define gr0_in()            gr0_set=1;

#define gr1_in()            gr1_set=1;

#define gr0_out()           gr0_set=0;

#define gr1_out()           gr1_set=0;

//----------------------------------------------


gr0_On() - мы выводим 1 в порт В2
gr0_Off() - мы выводим 0 в порт В2
gr0_in() - мы настраиваем ножку на ввод
gr0_out() - мы настраиваем ножку на вывод
gr0_read - мы читаем информацию из ножки В2
и соответственно по В3 – то же самое.

Далее – нам нужно выдавать временные интервалы. Учитывая, что тактовая Fosc – 48 мегагерц, пользуемся файлом delays.h - в нем функцией Delay10TCYx(Cycles), где
Cycles = (TimeDelay * Fosc) / 4 , а TimeDelay – нужная нам задержка в микросекундах, умноженная на 10. Для примера, если нам нужна задержка в 100 микросекунд, то Cycles получается (10 *48)/4 = 120
Чтобы не задумываться каждый раз, сколько микросекунд в циклах (или в попугайчиках), пишем :


#define del_mks(x)    Delay10TCYx(x *1.2)

Максимальное число, которое мы можем подставить в микросекундах – будет 255/1.2=212 микросекунд, потому что Cycles – 8-разрядное беззнаковое. Естественно, моя формула будет врать на временных интервалах, не кратных 5.Желающих получить более точные задержки отправляю в этот самый файл delays.h

Добавляем в каталог user еще 4 файла –grad.c grad.h crc.c crc.h
Первая пара – запись байта в градусник, чтение байта из градусника, сигнал сброса.
Вторая – проверка контрольной суммы принятой информации из градусника.
После копирования файлов – «добавить файлы в проект».Прописываем их в файле user.c


#include "user\grad.h"

#include "crc.h"


Вплотную приблизились к окончанию программы – осталось проинициализировать переменные и написать главный цикл. Поскольку хаб опрашивает устройство с цикличностью 1 милисекунда, то главный цикл должен быть меньше. Насколько меньше ? Хороший вопрос.
Решаем проблему «в лоб» - устанавливаем счетчик count и режем наш цикл на куски –


switch(count)

    {

        case 0:

задача1;

count++;

                break;

        case 1:

                                   задача2;

                            count++;

                break;

        case n:                

                задача n;

                count=0;

                break;

}


В заключение – прилагаю откомпилированные исходники - каталог cdc - hex в каталоге _output и исходники программы вывода результата на экран – экзешник в каталоге release. Прикрепленный файл  Cdc.rar ( 193.54 килобайт )исходники на вижуал
Прикрепленные файлы Прикрепленный файл  grad.rar ( 1.7 мегабайт )
скрин программы
« Ссылка »
вид снизу
« Ссылка »
вид сверху
« Ссылка »
Категория: Мои статьи | Добавил: MAS (26.11.2012)
Просмотров: 843 | Комментарии: 1 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Категории раздела
Мои статьи [51]
Справочные данные [165]
Справочные данные
Наш опрос
Оцените мой сайт
Всего ответов: 30
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Форма входа
Баннер
$$
Друзья сайта
  • Спортсменам
  • Огородникам СЮД(А
  • Строим вместе
  • Мир развлечений
  • Кто хочет похудеть
  • Здоровье у нас одно
  • Юмор
  • Кулинарные рецепты
  • Картинки_Заставки_Демотивоторы
  • Семья
  • Кто на мальчишник
  • Металлообработка
  • Кто на девишник
  • Блоки питания
  • Смерть соседям
  • Радиомедведь
  • Кибермедведь
  • Радиосайт
  • Деревообработка
  • Поиск