Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 23 lis 2024, o 23:05


Strefa czasowa: UTC + 1





Utwórz nowy wątek Ten wątek jest zablokowany. Nie możesz w nim pisać ani edytować postów.  [ Posty: 3 ] 
Autor Wiadomość
 Tytuł: V-USB na Atmega
PostNapisane: 25 lut 2014, o 01:11 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 22 cze 2013
Posty: 988
Lokalizacja: Byram, MS 39272
Pomógł: 55

Czym jest V-USB?

V-USB jest to biblioteka napisana z myślą o procesorach ATMEL umożliwiająca oprogramowanie komunikacji poprzez interfejs USB. Wprawny programista może spróbować przerobić bibliotekę pod inne procesory. Bibliotekę można ściągnąć ze strony projektu http://www.obdev.at/products/vusb/index.html. W tym miejscu dowiesz się jak obsługiwać USB od strony projektu opartego na procesorze ATMEL oraz od strony środowiska systemu operacyjnego Twojego PC.
Schematy podłączeń

Zgodnie z zaleceniami końcówki D+ i D- powinny być podłączone do nóżek odpowiedzialnych za przerwania procesora (INT0, INT1) aczkolwiek łącze D+ interfejsu podłączone być powinno zawsze do nóżki INT0 natomiast D- może być podłączone gdzie chcemy. Dodatkowo ważnym jest aby napięcie wychodzące z łączy D+ i D- było na poziomie 3.6V co można uzyskać na kilka sposobów (patrz schematy poniżej). Zaleca się też podłączenie rezystora pull-up 1.5k do D- oraz pull-up lub pull-down 1M do D+ żeby uniknąć interferencji kiedy USB nie jest podłączone.
Jako, że USB zasilane jest napięciem 5V do jego obniżenia można użyć diody Zenera

Obrazek
Podłączenie 1

Obrazek
Podłączenie 2

Obrazek
Podłączenie 3

Rys 1. Sposoby obniżenia napięcia na wyjściu USB


Obrazek
Rys 2. Schemat wtyczki


Przygotowanie do pracy

Zanim zaczniemy należy przygotować stanowisko pracy. Nie piszę już o samym układzie ale bardziej mam na myśli przygotowanie środowiska programistycznego tj. ściągnięcie biblioteki i przygotowanie jej do pracy z naszym programem.

Po ściągnięciu biblioteki rozpakowujemy ją do wybranego katalogu. Należy też ściągnąć sterowniki USB dla ©MS WINDOWS, dzięki którym będziemy mogli "rozmawiać" z naszym układem. Można to zrobić ze strony projektu libusb-win32. Moduł ten umożliwi nam skompilowanie sterowników dedykowanych dla naszego układu. Ale o tym później.

Kopiujemy folder usbdrv do naszego katalogu projektu. Wchodzimy do katalogu i tworzymy kopię pliku usbconfig_prototype.h jako usbconfig.h. Lokalizujemy linie definiującą porty IO oraz taktowanie zegara i jeśli to potrzebne uaktualniamy je do odpowiednich danych. W tym miejscu chciałbym zaznaczyć, że nasz procesor MUSI byś taktowany jedną z wartości: 12 MHz, 15 MHz, 16 MHz oraz 20 MHz lub 12.8 MHz w ostateczności 16.5 MHz +/- 1%. Inne wartości taktowania spowodują, że nie będzie możliwości używania naszego urządzenia.
Dlatego należy używać zewnętrznych kwarców i oczywiście odpowiednio obliczyć i ustawić FUSE BITy. (ja ustawiam low = AF high = DF ext. = 01)


Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Wstawiamy:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Powinniśmy też skonfigurować nazwę naszego urządzenia oraz numer, przez który będzie nas rozpoznawać nasz sterownik WINDOWS.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Przydaje się także informacja o tym czy nasze urządzenie korzysta z zasilania USB czy nie

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Tak naprawdę plik usbconfig.h jest na tyle dobrze opisany, że można samemu zaglądnąć do środka i zorientować się co jeszcze można ustawić. Zapraszam do lektury.

Czas na main.c


Poniżej mamy podstawowy szkielet programu dla μprocesora obsługującego protokół i łącze USB

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Co tu mamy? Jak to działa? Małe wytłumaczenie

Zaimplementujmy funkcję usbFunctionSetup() obsługującą wywołania USB (co i jak opiszę później)
W częsci głównej programu ustawiamy watchdog na 1 s, która zresetuje procesor jeśli coś pójdzie nie tak i nie zostanie wywołana funkcja wdt_reset() w czasie 1000 ms. To zabezpiecza program przed jakimiś nietypowymi zachowaniami i pozwala uniknąć użytkownikowi odłączania i ponownego przyłączania urządzenia jeśli stanie się coś dziwnego.
Wywołajmy usbInit() - funkcję inicjującą działąnie biblioteki V-USB.
Wymuśmy przenumerowanie USB poprzez użycie usbDeviceDisconnect(), a następnie po 500ms usbDeviceConnect(). Na wypadek resetu Watchdog.
Włączamy przerwania
Na sam koniec nieskończona pętla resetująca watchdog i wywołująca funkcję obsługi USB usbPool().

Jak dotąd wszystko wygląda chyba prosto. Zatem wypadałoby napisać jak urządzenie ma odpowiadać na zewnętrzne wywołanie.
Aby lepiej zrozumieć w jaki sposób procesor odpowiada na zewnętrzne wywołania USB należy przybliżyć działanie trzech podstawowych funkcji. Ale to w następnej części

------------------------ [ Dodano po: 16 minutach ]

Dwie funkcje

Jak wspominałem w części poprzedniej aby zacząć pisanie programów do komunikacji USB należy poznać dwie, no może trzy podstawowe funkcje służące do komunikacji URZĄDZENIE-KOMPUTER.

Pierwszą funkcją, która musi być zawsze zdefiniowana jest usbFunctionSetup(uchar dane[8]). Wywołując wezwanie USB z poziomu komputera uruchamiana jest zawsze ta funkcja. Jej wywołanie z poziomu procesora jest następujące:



Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


usbRequest jest zdefiniowany następująco

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.




Wszystkie dane są przekazywane od strony komputera poprzez funkcje wywołującą działanie programu poprzez USB ale co i jak napiszę w kolejnej części. W tej chwili zajmiemy się tylko funkcjami usbFunctionSetup, usbFunctionRead oraz usbFunctionWrite.

bmRequestType - informuje sterownik o tym czy chcemy dane przesyłać z czy do urządzenia

bRequest - rodzaj wywołania (zazwyczaj ustalane przez programiste)

twValue - wartość przesyłana do urządzenia

twIndex - index (w rzeczywistości kolejna wartość wysyłana przez programistę)

twLength - ilość danych


Funckie usbFunctionSetup możemy wykorzystać do wysyłania danych statycznych. Jeśli chcemy przesyłać dane odczytywane "w locie" winnismy użyć funkcji usbFunctionRead.

Przyszedł zatem czas na napisanie przykładowego programu służącego do zapalenia i gaszenia diody i przy okazji przesłania jakiegoś krótkiego tekstu np nazwy urządzenia. Ponieważ już wiadomo jak skonfigurować sterownik (patrz USB - AVR - biblioteka VUSB - część I) więc ten etap pominę.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Mam nadzieję, że choć trochę rozjaśniłem sposoby komunikacji URZĄDZENIE<-->KOMPUTER poprzez USB. W następnej części wytłumaczę jak można przekazywać większą ilość danych niż 8 znaków (w dwie strony) oraz jak porozumiewać się z naszym procesorem z poziomu komputera (WIN/LINUX). Napiszę też trochę informacji na temat numerowania VENDOR/DEVICE aby pozostać legalnym.

_________________
Pomysły na podpis - wyślij SMSa +1 769 243 0011



Góra
 Zobacz profil  
 
PostNapisane: 27 lut 2014, o 20:31 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 22 cze 2013
Posty: 988
Lokalizacja: Byram, MS 39272
Pomógł: 55

usbFunctionRead();

Przyszedł czas na wytłumaczenie w jaki sposób przesyłać większe ilości danych odczytywanych w locie. Do tego celu służy procedura usbFunctionRead(). Jednakże żeby jej użyć należy najpierw w pliku usbconfig.h zmienić

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.




na
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


To umożliwi wykorzystanie tej funkcji w naszym programie. Dobrze, zatem czas napisać do czego właściwie służy ta funkcja. Otóż jest ona wywoływana w chwili gdy sterownik żąda wysłania jakichś danych z naszego urządzenia. Na początku wywoływana jest zawsze funkcja usbFunctionConfig(), a następnie wywoływana jest jedna z funkcji usbFunctionRead() lub usbFunctionWrite(). W rzeczywistości jest tak, że funkcja Read służy do wysyłania danych z urządzenia, a funkcja Write do odczytywania danych przychodzących. Żeby jednak nastąpiło wywołanie jednej z tych funkcji to funkcja Setup musi zwrócić wartość USB_NO_MSG tak jak w przykładzie poniżej.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Funkcję usbFunctionRead() można wykorzystać np do odczytu większej ilości danych z pamięci EEPROM. Mozliwości jest wiele to tylko jeden z przykładów ale warto pamiętać jedną aczkolwiek bardzo ważną rzecz. Mianowicie to, że funkcja ta zwraca max 254 bajtów. Jakby jednak ktoś chciał to da się zwiększyć ilość danych przesyłanych przez nasz program do komputera. Aby to zrobić należy:

ustawić zmienną USB_CFG_LONG_TRANSFERS na 1 w pliku usbconfig.h.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


to pozwoli nam na przesyłanie danych powyżej 254 bajtów. Oczywiście powoduje to także zwiększenie ilości zajętej pamięci naszego procesora przez sterownik.

Teraz możemy wysyłać do hosta więcej niż 254 bajty.

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Jak widać w powyższym przykładzie funkcja usbFunctionRead() wysyła dane poprzez wskaźnik uchar *data. Dane trafiaja wprost do naszego hosta. Pamiętać należy, że funkcja MUSI zwrócić dokładną liczbę wysłanych danych. Jeżeli funkcja zwróci mniejszą liczbę program na komputerze nie będzie w stanie odczytać wszystkich bajtów wysłanych przez urządzenie, jeżeli zwróci większą liczbę niż liczba wysłanych danych to program się wysypie próbując odczytać nieistniejące dane.

Jeśli z jakichś powodów wewnątrz funkcji wystąpi błąd (np odczytując dane z EEPROM okaże się, że jest błąd odczytu) można poinformować sterownik o błędzie wysyłając jako wynik działania funkcji wartość (-1) 0xff.

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


To poinformuje sterownik i nasz program o tym, że wystąpił błąd.

Bardziej wnikliwi użytkownicy mogą spróbować przeanalizować działanie funkcji usbReadWrite() czytając źródła USBasp dostępne pod adresem https://github.com/whitequark/usbasp/blob/master/main.c

Dyskusja na temat http://forum.atnel.pl/post71949.html#p71949
Różowo-zielony (czyli s...[śliczny] - cenzura mirekk36 ;) ) J.

_________________
Pomysły na podpis - wyślij SMSa +1 769 243 0011



Góra
 Zobacz profil  
 
PostNapisane: 20 sie 2014, o 09:17 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 22 cze 2013
Posty: 988
Lokalizacja: Byram, MS 39272
Pomógł: 55

usbFunctionWrite()

Tak jak pisałem wyżej funkcja ta służy do odbierania danych wysyłanych do urządzenia. Np. w programatorze USBasp wysyłamy ciąg danych z PC do programatora, które mają zostać zapisane w programowanym procesorze. Odbiór danych z PC odbywa się właśnie poprzez funkcję usbFunctionWrite()
Składnia funkcji jest następująca (odrazu z małym przykładem wykorzystania)
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Jak widać składnia i działanie jest bardzo podobne do usbFunctionRead(). Powyższy przykład pokazuje jak zapisać dane do bufora w pamięci RAM.

To przyszedł czas na

USB <--> PC

W tej części kursu postaram się pokazać na prostym przykładzie jak przy pomocy programu napisanego w C (np. VISUAL C++) pod Windows porozumiewać się z naszym urządzeniem. Takie hello world przy pomocy V-USB. Na początek program zapalający i gaszący diodę po naciśnięciu przycisku zapal/zgaś na ekranie naszego komputera. Ale zanim to nastąpi omówię w jaki sposób podłączać i wyszukiwać nasze urządzenie z poziomu programu PC.



Po pierwsze trzeba dołączyć plik nagłówkowy pozwalający na komunikacje z USB. Plik ten uzyskamy zmieniając nazwę lusb0_usb.h na usb.h z katalogu sterowników libusb, które musimy zainstaloać (te same, które instaluje się żeby móc korzystać z USBasp)

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Od tej chwili możemy korzystać z połączenia AVR<->PC poprzez USB. Oczywiście wcześniej należy użyć odpowiednich funkcji.

Na początek stwórzmy przycisk, którym będziemy sprawdzać czy nasze urządzenie jest włożone do gniazda i jeśli jest to połączymy je z programem.

Do tego celu służą instrukcje

usb_find_busses(); //************************** szukamy portów USB
usb_find_devices(); //************************** szukamy urządzeń

Nastepnie musimy przeszukać uzyskaną w ten sposób bazę podłączonych rządzeń w celu znalezienia naszego. Nasze urządzenie rozpoznajemy poprzez VendorID oraz ProductID, które ustaliliśmy wcześniej w naszym programie


Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

W ten sposób podłączamy nasze urządzenie pod nasz program. Flaga is_connected jest ustawiana w chwili gdy w zmiennej usb_handle znajdzie się hak do naszego urządzenia.

OK, mamy podłączone urządzenie do programu. Można wysłać pierwszą wiadomość. Informacje wysyła się przy użyciu funkcji usb_control_msg(), która ma następującą składnie

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


A w wyniku zwraca liczbę otrzymanych bajtów lub (-1) w przypadku błędu. (http://libusb.sourceforge.net/doc/function.usbcontrolmsg.html)



Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Zapewne wielu z was zastanawia się czym jest ten zestaw komend/poleceń USB_TYPE_VENDOR | USB_RECIP_DEVICE |USB_ENDPOINT_IN

Otóż jeżeli wykorzystujemy metodę usbFunctionWrite(), która służy do odczytywania danych wysyłanych z PC (lub innego urządzenia) powinniśmy użyć tej składni

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Jeżeli natomiast dane odczytujemy z naszego urządzenia to korzystamy z takiego zestawu

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Więcej informacji na http://vusb.wikidot.com/host-software, a ja za chwilę wytłumaczę znaczenie poszczególnych poleceń

_________________
Pomysły na podpis - wyślij SMSa +1 769 243 0011



Góra
 Zobacz profil  
 
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Ten wątek jest zablokowany. Nie możesz w nim pisać ani edytować postów.  [ Posty: 3 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 0 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO