реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Помогите с at90usb162.
arbuz
сообщение Aug 1 2013, 06:22
Сообщение #1





Группа: Участник
Сообщений: 12
Регистрация: 9-04-11
Пользователь №: 64 241



День добрый. Обращаюсь за помощью-подсказкой. Начал изучение интерфейса USB, для этого приобрёл контроллер at90usb162. Решил познать всё с нуля. Проштудировав datasheet, и прочую литературу занялся написание прошивки на языке С в AVR Studio 4. Написав пару программа моргания диодом и ответом на нажатие кнопочки, решил приступить к написанию программы для USB. Сейчас затык на этапе получения пакета SETUP от хоста т.е. ПК. Подскажите, пожалуйста, где ошибка. Код прошивки прилагается.
CODE
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/power.h>


#define F_CPU 16000000UL


#include <util/delay.h>



int main()
{
DDRC |= 1 << DDC6; // Порт С - как выход

MCUSR &= ~(1 << WDRF);
wdt_disable();

clock_prescale_set(clock_div_1);

//CLKPR = 0x80; // Бит разрешение изменения делителя
//CLKPR = 0x00; // Установка делителя на 1 F = 16 MHz

PORTC |= (1 << PC6); // РС6 - зажечь диод

//REGCR = (1 << REGDIS);

UDIEN = 0x00; //
UDINT = 0x00; //

USBCON |= (1 << USBE);

USBCON &= ~(1 << FRZCLK);

PLLCSR |= (1 << PLLP0); // Установить делитель PLL
if ((PLLCSR & 0x1C) == 0x04)
PORTC = 0x00; // Потушить диод
PLLCSR |= (1 << PLLE); // Enable PLL
while((PLLCSR & 0x01) != 0x01) // Захват в петле PLL
PORTC = 0x00; // Потушить диод
PORTC |= (1<<PC6); // РС6 - зажечь диод

/*------Начало настройки нулевой КТ------*/
UENUM = 0x00; // Нулевая конечая точка
//UECONX |= 0x29; // Бит разрешения работы КТ + бит сброса переключения данных
UECONX |= (1 << STALLRQ);
UECONX |= (1 << EPEN); // Бит разрешения работы КТ + бит сброса переключения данных
//UECFG0X = 0x81; // Bulk, in
//UECFG0X = 0x00; // Control, out
//UECFG0X = 0x01; // Control, in
//UECFG1X = 0x36; // 64 байта, 2-ой банк, выделение буфера
UECFG1X = 0x32; // 64 байта, 1 банк, выделение буфера
//UECFG1X = 0x10; // 16 байт, 1 банк, очистка буфера
while ((UESTA0X & 0x80) != 0x80) // Проверка корректности настройки КТ
PORTC = 0x00; // Потушить диод, диод горит - КТ сформировалась корректно*/
/*------Конец настройки КТ------*/
PORTC |= (1<<PC6); // РС6 - зажечь диод
//UERST |= 0x01; // Сброс нулевой конечной точки
//UERST = 0x00; // Очистка, для завершения броса и начала использования FIFO.
UENUM = 0x00; // Выбор нулевой КТ

UDCON &= ~(1 << DETACH);

while((UDINT & 0x04) != 0x04)
PORTC = 0x00; // Потушить диод, ожидание флага Start of Frame
PORTC |= (1<<PC6); // РС6 - зажечь диод
UDINT &= ~(1 << SOFI);
while((UEINTX & 0x08) != 0x08)
PORTC = 0x00; // Потушить диод, ожидание пакета SETUP, бит RXSTPI
PORTC |= (1<<PC6); // РС6 - зажечь диод

while(1);
return 0;
}


Сообщение отредактировал IgorKossak - Aug 1 2013, 06:31
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
kovigor
сообщение Aug 1 2013, 08:27
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(arbuz @ Aug 1 2013, 09:22) *
решил приступить к написанию программы для USB

Начинать надо не с прошивки, а со спецификации USB. Очень желательно также соотв. книжку Гука глянуть ("Шины PCI, USB и FireWire"). Без этого, наверное, ничего не выйдет. Ну и примеры готовые разберите, предлагаемые Атмелом для вашего МК. Писать все это самому - жизни не хватит ...
Go to the top of the page
 
+Quote Post
arbuz
сообщение Aug 1 2013, 08:50
Сообщение #3





Группа: Участник
Сообщений: 12
Регистрация: 9-04-11
Пользователь №: 64 241



Спасибо за совет. Читал и Гука, и Агурова, и перевод спецификации USB 1.1. Если не сложно можно дать прямую ссылку на пример Атмела.
Go to the top of the page
 
+Quote Post
kovigor
сообщение Aug 1 2013, 08:59
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295



Цитата(arbuz @ Aug 1 2013, 11:50) *
Спасибо за совет. Читал и Гука, и Агурова, и перевод спецификации USB 1.1. Если не сложно можно дать прямую ссылку на пример Атмела.

Любой соотв. апп. ноут для вашего МК у него на сайте берете и изучаете. Найти легко, например, AVR272:

http://www.atmel.com/products/microcontrol...x?tab=documents
Go to the top of the page
 
+Quote Post
arbuz
сообщение Aug 1 2013, 11:15
Сообщение #5





Группа: Участник
Сообщений: 12
Регистрация: 9-04-11
Пользователь №: 64 241



Остаётся вопрос, почему после того как ловится бит прихода SOF, бит прихода маркера SETUP не устанавливается?
Go to the top of the page
 
+Quote Post
fractcon
сообщение Aug 1 2013, 11:40
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 157
Регистрация: 10-05-13
Пользователь №: 76 788



Цитата(arbuz @ Aug 1 2013, 15:15) *
Остаётся вопрос, почему после того как ловится бит прихода SOF, бит прихода маркера SETUP не устанавливается?

Вот честно, если Вы будете упираться в аппаратный уровень потратите напрасно много времени. С USB все всегда неоднозначно. И много зависит от железа.
Вам правильно подсказали. Возьмите ГОТОВЫЙ пример HID устройства на USB для AT90USB162 и перелопатьте код под свои нужды.
В свое время быстро и незатейливо удалось реализовать CDC+HID на данной меге. И HID там простой и очень дружелюбный.
А если хотите все таки USB узнать "от сохи", тогда начинать надо с CY7C68013 и FX2 Development Guide. Вот там да, все очень корректно. Можно лазить с осциллографом по шине, ловить биты и узнать много, очень много абсолютно бесполезной информации. Если только Вы не собираетесь корку на USB писать руками sm.gif

Сообщение отредактировал fractcon - Aug 1 2013, 11:42


--------------------
Скажи нет международному терроризму... не покупай Pepsi Cola.
Go to the top of the page
 
+Quote Post
arbuz
сообщение Aug 8 2013, 19:15
Сообщение #7





Группа: Участник
Сообщений: 12
Регистрация: 9-04-11
Пользователь №: 64 241



Цитата(fractcon @ Aug 1 2013, 15:40) *
Вот честно, если Вы будете упираться в аппаратный уровень потратите напрасно много времени. С USB все всегда неоднозначно. И много зависит от железа.
Вам правильно подсказали. Возьмите ГОТОВЫЙ пример HID устройства на USB для AT90USB162 и перелопатьте код под свои нужды.
В свое время быстро и незатейливо удалось реализовать CDC+HID на данной меге. И HID там простой и очень дружелюбный.
А если хотите все таки USB узнать "от сохи", тогда начинать надо с CY7C68013 и FX2 Development Guide. Вот там да, все очень корректно. Можно лазить с осциллографом по шине, ловить биты и узнать много, очень много абсолютно бесполезной информации. Если только Вы не собираетесь корку на USB писать руками sm.gif

Если не заруднит, не могли бы выложить программу созданного вами HID устройства на at90usb162. Заранее спасибо.

Сообщение отредактировал arbuz - Aug 8 2013, 19:15
Go to the top of the page
 
+Quote Post
vgo1
сообщение Aug 11 2013, 12:31
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 28-05-12
Пользователь №: 72 050



Цитата(arbuz @ Aug 1 2013, 10:22) *
День добрый. ...

После того как вы сделали atach, шина должна сбросить ваше устройство. Дождитесь EORSTI а не SOFI (while((UDINT & 0x08) != 0x08)), потом сконфигурируйте endpoint0 ещё раз. Шина может сбросить устройство ещё раз. Опять дождитесь EORSTI и снова конфигурируйте endpoint0. После этого уже можете дожидатся RXSTPI. Дальше согласно спецификации шины. Не забудте сразу после получения флага EORSTI его сбросить.
Еще прислушайтесь к советам kovigora, он мне здорово помог с USB.

Сообщение отредактировал IgorKossak - Aug 11 2013, 13:48
Причина редактирования: избыточное цитирование
Go to the top of the page
 
+Quote Post
Alex11
сообщение Aug 11 2013, 22:16
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 106
Регистрация: 23-10-04
Из: С-Петербург
Пользователь №: 965



Я тут давным-давно выкладывал проект под 162 мегу: http://electronix.ru/forum/index.php?act=a...st&id=32315
Посмотрите, там все обрезано лишнее, остается минимум, требуемый для понимания работы.
Go to the top of the page
 
+Quote Post
Rimsky
сообщение Aug 13 2013, 11:12
Сообщение #10





Группа: Участник
Сообщений: 14
Регистрация: 10-06-12
Пользователь №: 72 261



Цитата(arbuz @ Aug 1 2013, 17:50) *
Спасибо за совет. Читал и Гука, и Агурова, и перевод спецификации USB 1.1. Если не сложно можно дать прямую ссылку на пример Атмела.

Вот тут http://www.fourwalledcubicle.com/index.php проект LUFA есть хорошие примеры реализации USB на AVR
Go to the top of the page
 
+Quote Post
controller_m30
сообщение Aug 13 2013, 17:15
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 356
Регистрация: 24-02-09
Пользователь №: 45 309



Моё предложение такое, что надо сначала проверить железо - всё ли в нём настраивается для работы с USB? Загрузить в контроллер стандартный пример USB-девайса - пусть комп хотя бы обнаружит, что "найдено новое устройство, USB-AVR клавиатура... или мышь... или флешка" или какие там примеры ATMEL выкладывает.
Если компьютер обнаружил некое устройство, и его видно в диспетчере устройств, с названием, с всякими VID/PID - тогда уже можно начинать писать программу самому. А то, если что-то не так с железом (ножка не пропаяна, кварц не той частоты и т.п.) - можно долго ждать SETUP-пакетов.

Если с железом всё в порядке, и настройки железа в норме, то вот последовательность энумерации:
1. Подключаем Pull_Up резистор к D+ (для FullSpeed, и к D- для LowSpeed).
2. Обнаружив Pull_Up резистор - Хост выставляет на шине состояние RESET (1й раз).
3. Хост выставляет состояние SUSPEND.
4. Хост снова выставляет RESET (2й раз).
5. И только после этого - приходит первый SETUP-пакет. В буфер придёт последовательность из 8 байт: 0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00 - отправляем ACK.
6. Отправляем Хосту 8 байт ответа: 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08
7. Хост присылает пакет данных нулевой-длины (длина 0 !) - отправляем ACK.
8. Хост снова выставляет RESET на шину (3й раз)
9. Хост присылает SETUP-пакет присвоения адреса: 0x00, 0x05, 0xNN, 0x00, 0x00, 0x00, 0x00, 0x00 где NN присвоенный устройству адрес (1-127). Прописываем присвоенный адрес в соответствующий регистр контроллера, и отправляем ACK.
10. Отправляем Хосту пакет нулевой длины.
11.... дальше больше, но это потом, если хотя бы эти шаги работают wink.gif

Если всё в порядке, больше состояние RESET на шине появляться не будет. А если с обменом будут ошибки - то Хост ещё два раза повторит с пункта [4], после этого выставит команду SUSPEND, и затихнет до переподключения USB-устройства.

Сообщение отредактировал controller_m30 - Aug 14 2013, 05:51
Go to the top of the page
 
+Quote Post
arbuz
сообщение Aug 15 2013, 07:05
Сообщение #12





Группа: Участник
Сообщений: 12
Регистрация: 9-04-11
Пользователь №: 64 241



Спасибо всем за подсказки, результат - положительный, пакет SETUP приходит и об этом свидельствует установка бита RXSTPI. Далее действия:
Код
#define Usb_read_byte() (UEDATX)

  while((UEINTX & 0x08) != 0x08)
    PORTC = 0x00;  // Потушить диод, ожидание пакета SETUP, бит RXSTPI
  UEINTX &= ~(1 << RXSTPI); // Очистка RXSTPI, для подтверждения пакета setup
  PORTC |= (1<<PC6);  // РС6 - зажечь диод

  UEINTX &= ~(1 << RXOUTI); // Очистка бита RXOUTI

  bmRequestType = Usb_read_byte();  // тип запроса; bmRequestType - переменная типа unsigned char
  bmRequest      = Usb_read_byte();  // код запроса; bmRequest - переменная типа unsigned char

  if (bmRequestType == 0x80)
    PORTC |= (1<<PC6);  // РС6 - зажечь диод
  else PORTC = 0x00;     // Потушить диод

  if (bmRequest == 0x06)
    PORTC |= (1<<PC6);  // РС6 - зажечь диод
  else PORTC = 0x00;  // Потушить диод

Результат оказывается следующим, переменные bmRequestType и bmRequest содержат одно и тоже число 0х80. Вопрос, как необходимо считывать данные из UEDATX? ACK отправляется самостоятельно контроллером или необходимо это сделать программно? И правильный ли вобщем алгоритм действий?

Сообщение отредактировал arbuz - Aug 15 2013, 07:10
Go to the top of the page
 
+Quote Post
vgo1
сообщение Aug 15 2013, 10:21
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 28-05-12
Пользователь №: 72 050



После того как поймали RXSTPI. сделайте 8 последовательных считываний из UEDATX и сохраните эти данные чтобы потом анализировать. Только после того как прочли 8 байт, сбросте RXSTPI. Это аппаратно иницирует ACK, программно ничего делать не нужно. Внимательнее прочтите даташит, вся информация оттуда.
Забыл спросить зачем вовремя SETUP-а устанавливаете бит STALLRQ ? Если не ошибаюсь, это делается когда вы от хоста получаете не поддерживаемую вашим устройством команду.
Аппаратура у вас вроде в порядке, так что изучайте даташит и 9-ый раздел спецификации.

Сообщение отредактировал vgo1 - Aug 15 2013, 12:46
Go to the top of the page
 
+Quote Post
arbuz
сообщение Aug 16 2013, 12:18
Сообщение #14





Группа: Участник
Сообщений: 12
Регистрация: 9-04-11
Пользователь №: 64 241



Цитата(vgo1 @ Aug 15 2013, 14:21) *
После того как поймали RXSTPI. сделайте 8 последовательных считываний из UEDATX и сохраните эти данные чтобы потом анализировать. Только после того как прочли 8 байт, сбросте RXSTPI. Это аппаратно иницирует ACK, программно ничего делать не нужно. Внимательнее прочтите даташит, вся информация оттуда.
Забыл спросить зачем вовремя SETUP-а устанавливаете бит STALLRQ ? Если не ошибаюсь, это делается когда вы от хоста получаете не поддерживаемую вашим устройством команду.
Аппаратура у вас вроде в порядке, так что изучайте даташит и 9-ый раздел спецификации.

Спасибо за подробное разъяснение, бит STALLRQ устанавливался в первоначальной версии прошивки, на данном этапе установка бита отсутствует.
Go to the top of the page
 
+Quote Post
arbuz
сообщение Sep 2 2013, 06:43
Сообщение #15





Группа: Участник
Сообщений: 12
Регистрация: 9-04-11
Пользователь №: 64 241



Процесс пошёл, пришёл пакет SETUP, флаг RXSTPI установился, далее считываю данные из UEDATX, и далее флаг RXSTPI сбрасываю.
Код
  while((UEINTX & 0x08) != 0x08)
    PORTC = 0x00;  // Потушить диод, ожидание пакета SETUP, бит RXSTPI
  PORTC |= (1<<PC6);  // РС6 - зажечь диод

  bmRequestType = Usb_read_byte();  // тип запроса
  bmRequest     = Usb_read_byte();    // код запроса

  if (bmRequestType == 0x80)
    PORTC |= (1<<PC6);  // РС6 - зажечь диод
  else PORTC = 0x00;  // Потушить диод

  if (bmRequest == 0x06)
    PORTC |= (1<<PC6);  // РС6 - зажечь диод
  else PORTC = 0x00;  // Потушить диод*/


  UEINTX &= ~(1 << RXSTPI); // Очистка RXSTPI, для отправки ACK


Далее, должен прийти пакет IN, в ответ на который контроллер обязан выслать 8 байт дескриптора, и получить от хоста ACK.
CODE

#define Usb_write_byte(byte) (UEDATX = (unsigned char)byte)

while((UEINTX & 0x01) != 0x01) //(ВЕРНО?)
PORTC = 0x00; // Потушить диод, ожидание пакета IN, бит TXINI
PORTC |= (1<<PC6); // РС6 - зажечь диод
Usb_write_byte(0x12);
Usb_write_byte(0x01);
Usb_write_byte(0x00);
Usb_write_byte(0x02);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x08); // Запись данных в UEDATX

UEINTX &= ~(1 << TXINI); // Сброс TXINI для отправки данных хосту



Вопрос: правильно ли, то что установка бита TXINI считается приходом пакета IN? Каким образом узнать что хост прислал ACK?

Далее, хост присылает пакет OUT нулевой длинны, задача контроллера отправить пакет ACK.
Код
  while((UEINTX & 0x04) != 0x04)
    PORTC = 0x00;  // Потушить диод, ожидание пакета OUT, бит RXOUTI
  PORTC |= (1<<PC6);  // РС6 - зажечь диод
  
  UEINTX = 0x00; // Сброс регистра, для отправки ACK


Вопрос: для отправки ACK на пакет OUT достаточно очистки бита RXOUTI?

Сообщение отредактировал IgorKossak - Sep 23 2013, 11:27
Причина редактирования: Поднятие темы запрещено правилами форума!!!
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 8th July 2025 - 11:16
Рейтинг@Mail.ru


Страница сгенерированна за 0.01517 секунд с 7
ELECTRONIX ©2004-2016