Скачал последню версию v-usb, почитал как развести МК, соответственно здесь: http://www.obdev.at/products/vusb/index.html и http://easyelectronics.ru/podklyuchenie-mikrokontrollera-likbez.html.
Долго выбирал чем буду пограммировать. Тратить большие деньги на программатор нет смыла, когда есть в наличии arduino, которая легко превращается в программатор http://arduino.cc/en/Tutorial/ArduinoISP. Для этого просто надо посмотреть на последнюю схему подключения, главное свериться с даташитом программируемого МК, т.к. ножки могут отличаться. У меня, например МК ATmega32A у которого ноги для ISP программирования находятся совсем в другом месте. Также не надо забыть записать прошивку программатора avrisp на arduino. В данной мной ссылке документация как прошить МК бутлоадер от arduino с помощью ПО arduino, т.е. само ПО arduino заливает только бутлоадер, а далее контроллер превращается в arduino и программируется через булоадер. Мне это было не интересно. Однако программа для заливки прошивок avrdude успешно работает с нашим новоиспеченным программатором (собственно и софт arduino использует avrdude).
Теперь как же все-таки заливать прошивки? Разобраться с командной строкой легко, но нужно еще рассчитать фьюзы (зто читайте отдельно, документации полно), где можно легко ошибиться, поэтому нужна удобная gui программа для нашей avrdude. Единственная, которая заработала сразу и в которой было все что мне надо без излишеств это sinaprog 2.0 скачанная у производителя. Сборка от DIHALT тут не подошла, она видимо хорошо при использовании bit-bang программатора или программатора от DIHALT. Я для v-usb настроил фьюзы на использование внешнего кварца 12MHz.
Чем будем программировать? Разумеется интереснее всего брать софт от производителя и последней версии, а именно Atmel studio 6 (он же AVR studio 6). Там и патч для него уже какой-то выпустили. Про данную версию на форумах народ жалуется, что у нее эмулятор работает с ошибками, но я не представляю как можно эмулировать подключение МК к USB реального компьютера, а потому мне главное чтобы была качественная среда для программирования и все. Она вроде умеет и сама программировать МК, но в описании нету поддерживаемого программатора avrisp, который был получен из arduino.
Итак, софт есть, апаратура есть - можно приступать!
Можно взять в помощь статью http://we.easyelectronics.ru/electro-and-pc/usb-dlya-avr-chast-2-hid-class-na-v-usb.html как начало для первой настройки, но там все расписано для avr studio 4, а 4-я версия студии от 6-й отличается очень сильно. Не буду писать как, у меня ничего долго не получалось, напишу сразу что надо сделать чтобы получилось:
0. ВНИМАНИЕ!!! Перед установкой студии необходимо сперва установить WinAVR иначе Студия будет работать только на ASM (так написано во всех рекомендациях, я делал также).
1. При создании нового проекта необходимо выбрать компилятор asm, gcc или g++. Не экспериментируйте, сразу надо использовать gcc т.к. именно под него писалась v-usb. У g++ лезут совершенно неадекватные ошибки при компиляции, а с gcc хоть понятно как их необходимо исправлять (думаю разный синтаксис описания типов имеет место быть).
2. Как описано в статье на easyelectronics, необходимо сбросить в наш проект все файлы из папки usbdrv пакета v-usb. Но!!! Там все рассчитано на более старую версию gcc, а новая более придирчива к синтаксису (не знаю как лучше это назвать), поэтому в файле usbdrv.c необходимо поменять все определения переменных вроде "PROGMEM char usbDescriptorString0" на "PROGMEM const char usbDescriptorString0", иначе компилятор ругается, что переменная объявленная с директивой PROGMEM должна быть const.
3. В созданный главный модуль main.c нашей программы необходимо скопировать, например текст примера из папки /examples/hid-mouse/. Если компилировать сразу, то получим ошибки, что определение переменной usbHidReportDescriptor не соответсвует другому определению. Вобщем тут тоже должно быть определение переменной usbHidReportDescriptor с директивой const, а именно "PROGMEM const char usbHidReportDescriptor[52]".
4. Не забудем скопировать и файл usbconfig.h или переименовать в него файл "usbconfig-prototype.h", но в последнем случае надо четко выставить все настройки из примера hid-mouse, т.к. малейшее отклонение в параметрах и может даже не компилироваться, не то что не работать. Проще все-таки скопировать из примера файл конфигурации. Если после всех настроек ниже что-то не пашет, смотрите тут.
5. Необходимо в проект добавить файлы usbdrv.c, usbdrvasm.S и oddebug.c (последний необязательно, я из примера убрал отладку, т.к. все-равно у меня нет отладчика или его надо собирать - неохото). В отличии от предыдущих студий, добавить эти файлы необходимо несколько по другому. В "solution explorer" (окошко справа, а если не открыто, то в меню "view -> solution explorer") кликаем правой кнопкой мыши по нашему проекту и в открывшемся меню выбираем "Add" и так для каждого файла.
6. Необходимо настроить сам компилятор, иначе ничего не получиться.
6.1. Необходимо задать частоту МК. В старой версии было специальное поле, а тут нету. Что делать? Для простых проектов достаточно в главном модуле просто прописать перед всеми "#include" константу с частотой "#define F_CPU 12000000UL" (я использовал кварц 12MHz как основной для v-usb, а при б`ольших частотах, все-равно используется искусственное затормаживание). В нашем проекте такая директива не прокатит, т.к. usbdrvasm.S не сможет ее использовать при компиляции, поэтому заставим компилятор всем раздать эту директиву. Убираем, если уже поставили, из главного модуля "main.c" директиву "#define F_CPU 12000000UL". Идем в меню "Project -> Имя_проекта Properties", где откроются свойства проекта. В разделе "Toolchain" находятся все настройки для компиляции проекта. В "AVR/GNU C Compiler -> Symbols" добавляем в раздел "-D" строчку "F_CPU=12000000UL". А в разделе "AVR/GNU Assemler -> General" в поле "Assembler flag" надо добавить "-DF_CPU=12000000UL".
6.2. Еще не ушли из настроек компилятора? Надо еще выставить несколько настроек. В "AVR/GNU C Compiler -> General" необходимо снять галку "Default char type is unsigned (-funsigned-char)" - говорят работает и с ней, но не так как надо, догадайтесь почему.
6.3. в разделе В "AVR/GNU C Compiler -> Optimization" в поле "Optimization Level" должно стоять "Optimize for size (-Os)". Не знаю влияет ли именно это на работоспособность затем v-usb, но прежде чем наконец все заработало я изменил данную настройку.
6.4. Об этом лучше было сказать в самом начале, но это последнее что я сделал. Все настройки 6.1.-6.3. необходимо делать в разделе при выбранном вверху окна "Имя_проекта Properties" в поле "Configuration:" -> "Active (Release)", а при компиляции на тулбаре студии (сразу под верхнем меню) в выпадающем списке необходимо вместо "Debug" (установлено по умолчанию) переключить на "Release". Это всего лишь вариант конфигурации, но там в конфигурации уже где-то стоят настройки компилятора с включением кода отладки. Как можно отлаживать работу USB отладчиком, при том что USB не терпит остановок, в реальном времени я не представляю, поэтому надо сразу делать в режиме "Release".
Только после всех этих чудесных настроек все заработало.
Могу добавить еще одну замеченную странность. Из функции main() я убрал все вызовы watchdog и odDebug, я же не знал почему не работает и пользуясь опытом работы с PS/2 убрал все лишнее что может вызывать задержки алгоритма. Получилось так:
Код: Выделить всё
int __attribute__((noreturn)) main(void)
{
uchar i;
usbInit();
usbDeviceDisconnect(); /* enforce re-enumeration, do this while interrupts are disabled! */
i = 0;
while(--i){ /* fake USB disconnect for > 250 ms */
_delay_ms(1);
}
usbDeviceConnect();
DDRC=0b00000011;
sei();
for(;;){ /* main event loop */
usbPoll();
if(usbInterruptIsReady()){
PORTC=0b00000011;
/* called after every poll of the interrupt endpoint */
advanceCircleByFixedAngle();
usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
}
PORTC=0b00000000;
}
}
Но почему-то такой вариант работал нестабильно, т.е. устройство определилось, мышка начала двигаться, но какими-то редкими рывками, неравномерно. Как видно из кода я активировал на вывод 2 порта для подключения светодиода(ов) (можно и один - это исторически сложилось, что для экспериментов я включил сразу 2). Светодиод точно также изредка и тихо подмигивал, но редко, как и двигался курсор мыши.
Я вспомнил, что usbPoll() должна вызываться не реже чем 50 миллисекунд, но любая передача данных провоцирует задержку в передаче полезной информации. Насколько я понимаю usbPoll() отправляет хосту usbHidReportDescriptor и в таком цикле он это делает без остановок. А когда передавать наши данные? Вот наши данные и передаются урывками, когда найдется свободное время между отправками usbHidReportDescriptor. Проблему решил просто, вставив задержку в конце цикла _delay_ms(10). Поскольку v-usb работает на прерываниях, то нет смысла беспокоится, что во время _delay_ms(10) МК все-равно не делает ничего полезного и не отдает никому другому процессорное время. Прерывание отберет у основного цикла процессорное время и выполнит отправку данных, что нам и надо. Заодно этой задержкой можно регулировать скорость движения мышки, правда не сильно, поскольку нам нельзя делать задержку более 50мксек (устройство может начать теряться/дисконектиться).
Вот вроде и все основное, а далее можно развлекаться в меру своей испорченности...