Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
titulnik.docx
Скачиваний:
21
Добавлен:
16.03.2016
Размер:
246.21 Кб
Скачать

4 Разработка алгоритма работы управляющей программы для микроконтроллера

На рисунке 3 изображена блок-схема основной программы микроконтроллера.

Начало

Настройка портов вывода

Процедура подключения устройства к компьютеру

Ожидание входящих блоков данных

Рисунок 3 – Блок-схема основной программы

Основная программа начинается с настройки порта PB1 на вывод, остальные на ввод. Затем идет процедура подключения устройства к компьютеру которая состоит из функций usbDeviceDisconnect(), паузы и usbDeviceConnect(), которые служат для отключения и подключения микроконтроллера к компьютеру соответственно. Следом идет бесконечный вызов функции usbPoll(), которая служит для инициализации устройства на компьютере. Эта функция должна вызываться не менее чем через каждые 50 мс. Иначе устройство не будет распознано. Так же в последний блок включаются прерывания, а именно функции usbFunctionWrite() и usbFunctionRead(), которые служат для приема и отправки микроконтроллером блока данных соответственно.

5 Функции и переменные основной программы для микроконтроллера

Прототипы функций и их описание:

– usbFunctionRead() вызывается когда хост запрашивает порцию данных от устройства

– usbFunctionWrite() вызывается когда хост отправляет порцию данных к устройству

– usbFunctionSetup(uchar data[8]) – инициализация класса устройства HID

– usbInit() – Эта функция должна быть вызвана перед разрешением прерываний и заходом в основной цикл main.

– usbDeviceDisconnect() – Эта функция не соединяет устройство с шиной USB хоста.

– usbDeviceConnect() – Эта функция соединяет устройство с шиной USB хоста.

– usbPoll() – Эта функция должна быть вызвана через регулярные интервалы внутри главного цикла main. Максимальная задержка между вызовами должна быть несколько меньше 50 мс (таймаут USB для принятия сообщения Setup). Иначе устройство не будет распознано.

Основные переменные:

– uchar b1 - без знаковый символьный тип, в нем хранится блок данных.

– static uchar currentAddress - без знаковый символьный тип. Эта переменная отвечает за адрес чтения и записи данных.

– static uchar bytesRemaining - без знаковый символьный тип. Эта переменная отвечает за количество оставшихся байт данных.

– uchar len - без знаковый символьный тип. Эта переменная отвечает за длину текущего сообщения.

– uchar *buffer – указатель на без знаковый символьный тип. Указывает на начала области буфера.

– uchar *data - указатель на без знаковый символьный тип. Указывает на начала области данных.

6 Листинг основной программы для микроконтроллера

#include <avr/io.h>

#include <avr/interrupt.h>

#include <util/delay.h>

#include <avr/pgmspace.h> /* нужно для usbdrv.h */

#include "usbdrv.h"

uchar b1 = 0;

PROGMEM char usbHidReportDescriptor[22] = { // USB report descriptor

// Дескриптор описывает структуру пакета данных для обмена

0x06, 0x00, 0xff, // USAGE_PAGE (Generic Desktop)

0x09, 0x01, // USAGE (Vendor Usage 1)

0xa1, 0x01, // COLLECTION (Application)

0x15, 0x00, //LOGICAL_MINIMUM(0)// min. значение для данных

0x26, 0xff, 0x00, //LOGICAL_MAXIMUM (255)// max. значение для данных, 255 тут не случайно, а чтобы уложиться в 1 байт

0x75, 0x08, //REPORT_SIZE (8)

// информация передается порциями, это размер одного "репорта" 8 бит

0x95, sizeof(uchar), //REPORT_COUNT

// количество порций (у нашем примере = 1, описанная выше переменная передастся за один репорт)

0x09, 0x00, //USAGE (Undefined)

0xb2, 0x02, 0x01, //FEATURE (Data,Var,Abs,Buf)

0xc0 // END_COLLECTION

};

/* Здесь мы описали только один report, из-за чего не нужно использовать report-ID (он должен быть первым байтом). С его помощью передадим 1 байт данных (размер одного REPORT_SIZE = 8 бит = 1 байт, количество REPORT_COUNT = 1).

*/

/* Эти переменные хранят статус текущей передачи */

static uchar currentAddress;

static uchar bytesRemaining;

/* usbFunctionRead() вызывается когда хост запрашивает порцию данных от устройства*/

uchar usbFunctionRead(uchar *data, uchar len)

{

if(len > bytesRemaining)

len = bytesRemaining;

uchar *buffer = &b1;

if(!currentAddress) // Ни один кусок данных еще не прочитан.

{ // Заполним структуру для передачи

if ( PINB & _BV(1) )

b1 = 1;

else

b1 = 0;

}

uchar j;

for(j=0; j<len; j++)

data[j] = buffer[j+currentAddress];

currentAddress += len;

bytesRemaining -= len;

return len;

}

/* usbFunctionWrite() вызывается когда хост отправляет порцию данных к устройству */

uchar usbFunctionWrite(uchar *data, uchar len)

{

if(bytesRemaining == 0)

return 1; /* конец передачи */

if(len > bytesRemaining)

len = bytesRemaining;

uchar *buffer = &b1;

uchar j;

for(j=0; j<len; j++)

buffer[j+currentAddress] = data[j];

currentAddress += len;

bytesRemaining -= len;

if(bytesRemaining == 0) // Все данные получены

{ // Выставим значения на PORTB

if ( b1 )

PORTB |= _BV(1);

else

PORTB &= ~_BV(1);

}

return bytesRemaining == 0; /* 0 означает, что есть еще данные */

}

/* ------------------------------------------------------------------------- */

usbMsgLen_t usbFunctionSetup(uchar data[8])

{

usbRequest_t *rq = (void *)data;

if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) /* HID устройство */

{

if(rq->bRequest == USBRQ_HID_GET_REPORT)

{ // у нас только одна разновидность репорта, можем игнорировать report-ID

bytesRemaining = sizeof(uchar);

currentAddress = 0;

return USB_NO_MSG; // используем usbFunctionRead() для отправки данных хосту

}else if(rq->bRequest == USBRQ_HID_SET_REPORT)

{ // у нас только одна разновидность репорта, можем игнорировать report-ID

bytesRemaining = sizeof(uchar);

currentAddress = 0;

return USB_NO_MSG; // используем usbFunctionWrite() для получения данных от хоста

}

}else

{/* остальные запросы мы просто игнорируем */

}

return 0;

}

/* ------------------------------------------------------------------------- */

int main(void)

{

DDRB = 0b0000010; // PB1 - выход

usbInit();

usbDeviceDisconnect(); // принудительно отключаемся от хоста, так делать можно только при выключенных прерываниях!

uchar i = 0;

while(--i){ // пауза > 250 ms

_delay_ms(1);

}

usbDeviceConnect(); // подключаемся

sei(); // разрешаем прерывания

for(;;){ // главный цикл программы

usbPoll(); // эту функцию надо регулярно вызывать с главного цикла, максимальная задержка между вызовами - 50 ms

}

return 0;

}

/* ------------------------------------------------------------------------- */

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]