ЖЕЛЕЗО. Я использовал контроллер ATXMega256A3BU. Это та же самая ATXMega256A3, но с аппаратно реализованным USB модулем. К слову, я думал, что они pin-to-pin совместимы, но это не полностью так, будьте внимательны! Выводы контроллера D+ и D- я подключил напрямую к соответствующим пинам на разъеме компьютера без всяких резисторов. В моем случае, правда, был не компьютер, а микросхема USB хаба, а потом уже компьютер, но я не думаю, что это существенно меняет дело.
СОФТ МИКРОКОНТРОЛЛЕРА. Для создания костяка прошивки, с уже реализованным программистами Atmel USB стеком, мы воспользуемся мастером ASF Wizard, который встроен в Atmel Studio 6 версии. Дня начала необходимо создать новый проект (File->New Project). Далее в открывшемся окне необходимо выбрать пункты, показанные на картинке.
После создания нового проекта нужно запустить ASF Wizard (меню ASF->ASF Wizard). Во вкладке Availble modules нужно найти USB Device (service), и нажать Add. После этого во вкладке Selected Modules появится USB Device (service), а напротив него выпадающий список. В нем выбираем hid_generic. После чего нажимаем на кнопку Summary, и на этом создание проекта закончено. Теперь он готов к тому, чтобы наполнить его смыслом. В основном файле проекта main.c мы увидим следующее содержание:
#include <asf.h> int main (void) { board_init(); // Insert application code here, after the board has been initialized. }
Функция board_init() инициализирует отладочную плату, XMEGA-A3BU Xplained. Так как у меня была не эта плата, а своя, я эту функцию выкинул. Далее нам понадобится функция для инициализации USB. Это udc_start(). Она объявлена где-то в недрах asf.h, так что спокойненько ее прописываем. Она инициализирует USB в соответствии с настройками, описанными в файле conf_usb.h.Этот файл находится в папке с проектом. Приведу те строки этого файла которые особо важны для настройки USB HID:
#define USB_DEVICE_VENDOR_ID 0x03EB #define USB_DEVICE_PRODUCT_ID 0x2013 #define USB_DEVICE_POWER 500 // Consumption on Vbus line (mA) #define USB_DEVICE_ATTR USB_CONFIG_ATTR_SELF_POWERED #define USB_DEVICE_MANUFACTURE_NAME "Company Name" #define USB_DEVICE_PRODUCT_NAME "Varior Lens" #define USB_DEVICE_SERIAL_NAME "00001" #define UDI_HID_GENERIC_REPORT_OUT(ptr) my_callback_generic_report_out(ptr) extern void my_callback_generic_report_out(uint8_t *report); #define UDI_HID_REPORT_IN_SIZE 64 #define UDI_HID_REPORT_OUT_SIZE 64 #define UDI_HID_REPORT_FEATURE_SIZE 4
Имена дефайнов говорят сами за себя. Информации о том, что такое vendor id и product id в сети достаточно. UDI_HID_REPORT_IN_SIZE и UDI_HID_REPORT_OUT_SIZE — это размеры входного и выходного буферов соответственно. Функция my_callback_generic_report_out() вызывается в тот момент, когда получен пакет данных с компьютера. В ней можно обрабатывать полученные данные.
После того, как USB инициализирован, его можно использовать. Код программы в общем случае выглядит вот так:
#define F_CPU 32000000UL #include <asf.h> int8_t ui_hid_report [64]; uint8_t report [64]; void my_callback_generic_report_out(uint8_t *data){ for (uint8_t i = 0; i < 64 i++){ report [i] = data[i]; } // теперь в массиве report находятся данные полученные в сообщении } void main(){ irq_initialize_vectors(); cpu_irq_enable(); sysclk_init(); udc_start(); sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_TC0); // включение тактирования таймера ТС0 while(1){ // отправка данных находящихся в массиве ui_hid_report на компьютер udi_hid_generic_send_report_in(ui_hid_report); } }
Скажу несколько слов о строчке sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_TC0). Дело в том, что функция sysclk_init() по умолчанию выключает тактирование большей части периферии. Я так и не смог разобраться, по какому принципу она это делает, но разобрался, как включить периферию обратно:) Можно использовать sysclk_enable_module(), и дописывать в нее в качестве аргументов то что надо включить. Что именно дописывать можно понять, если использовать поиск по всему проекту и в качестве параметра поиска указать sysclk_disable_module.
Если залить этот код в контроллер, и подключить его к компьютеру, то в диспетчере устройств появится HID-совместимое устройство. А в устройствах и принтерах устройство с тем названием которое было указано в строке #define USB_DEVICE_PRODUCT_NAME. В моем случае все выглядит вот так:
СОФТ ДЛЯ КОМПЬЮТЕРА.
Все тот же Atmel любезно предоставляет нам примеры как это сделать на стороне компа. Они выполнены в Visual Studio, в которой я не силен, так что мне пришлось переписать под C++ Builder. По этому поводу коллеги говорили мне: «изыди». Но чем богаты тем и рады. В общем привожу пример на билдере.
Первым делом надо подключить библиотеку AtUsbHid.dll. Ее нужно взять в папке с атмеловским примером и скинуть в папку своего проекта. Для начала в .h файле проекта в соответсвующие места прописываем следующие строчки:
typedef ULONG HIDStatus; typedef HIDStatus WINAPI __import tcloseDevice(void); typedef HIDStatus WINAPI __import tfindHidDevice(const UINT VendorID, const UINT ProductID); typedef HIDStatus WINAPI __import twriteData(UCHAR* buf); protected: tcloseDevice *closeDevice; tfindHidDevice *findHidDevice; twriteData *writeData;
Далее в теле программы, например, при создании формы нужно написать следующее.
HINSTANCE AtUsbHidhandle; AtUsbHidhandle = LoadLibrary("AtUsbHid.dll"); if (AtUsbHidhandle == 0) ShowMessage("Не найдена AtUsbHid.dll"); else{ closeDevice = (tcloseDevice*)GetProcAddress(AtUsbHidhandle,"closeDevice"); findHidDevice = (tfindHidDevice*)GetProcAddress(AtUsbHidhandle,"findHidDevice"); writeData = (twriteData*)GetProcAddress(AtUsbHidhandle,"writeData"); }
Теперь мы имеем функции для работы с HID устройсnвом. findHidDevice(VID, PID) ищет в системе устройство с соответствующими VID и PID. После этого с ними можно работать. writeData() отправляет массив на устройство. Использовать это все можно например так:
#define VID 0x03EB #define PID 0x2013 char a = 0; a = findHidDevice(VID, PID_1); if (a != 0){ Label1->Caption = "Подключено"; } UCHAR leds[64]; leds[0] = 255; leds[1] = 10; leds[2] = 20; leds[3] = 30; writeData(leds); closeDevice();
Вот так я реализовал HID девайс на ATXMega. Конечно, в статье не раскрыты тонкости и нюансы настрОйки USB. Однако теперь, у тех, кто только начинает свое знакомство с этой темой, есть инструкция к действию, а уж дальше, ковыряйтесь, разбирайтесь, вам и карты в руки!
Ну и конечно в конце обязательно видео, как это работает у меня. Видеокамера с регулируемым зумом, фокусом и диафрагмой.
ссылка на оригинал статьи http://habrahabr.ru/post/221839/
Добавить комментарий