Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

C# USB HID Device Interface Komunikacja

sajmosia 03 May 2013 23:57 14577 10
  • Witam Wszystkich.

    Ten artykul jest poswiecony komunikacji pomiedzy urzadzeniami peryferyjnymi typu HID a komputerem przez C# i .net.

    Intro:


    Zaczelo sie od tego, ze poprzez hobby wpadly mi w rece uklady scalone PIC firmy Microchip, z ktorych wiele ostatnich mozna zaprogramowac jako urzadzenie, ktore mozna podpiac do komputera przez usb. Fakt, ze bawilem sie scalakami firmy microchip zamiast np atmel czy nxp jest czystym przypadkiem i ten artykul nie jest w zaden sposob zwiazany z wyborem zadnej z tych firm, bo chodzi tu o rozwiazanie problemu komunikacji a nie z czym sie komunikujemy, gdyz dzieki klasie, ktora tu opisze mozna "rozmawiac" z praktynie kazdym tego typu urzadzeniem tak dlugo, jak potrafi sie przedstawic jako "HID Device". http://pl.wikipedia.org/wiki/Human_Interface_Device.

    Postaram sie tu troche ulawtwic zycie tym, ktorzy tez zaczynaja sie bawic tego typu elektronika.

    Historia.

    Kiedy zaczalem sie bardziej interesowac ukaladami scalonymi, ktore mozna programowac, duzo podrozowalem po roznego rodzaju forach, blogach i innych tego rodzaju
    wirtualnych miejscach w poszukiwaniu jednej odpowiedzi na wszechczesne pytanie: o co w tym wszystkim chodzi?
    Przejzalem wiele dyskusji, troche ciekawych, innych mniej, jeszcze innych, ktore zaczynaly sie ciekawie,
    lecz po krotce szybko odbiegaly od tematu czesto przeradzajac sie w swieta wojne pt:
    Moj atmel jest lepszy niz twoj Microchip itd itp. Troche to przypomnialo mi wojne z mojego dziecinstwa miedzy Sinclair, Commodore i Atari :)
    , co w gruncie rzeczy w ogole nie ma sensu, ale czasem milo bylo poczytac.
    Wracajac do tematu, dowiedzialem sie jednego: nie ma jescze na ta chwile miejsca, gdzie mozna sie dowiedziec wszystkiego na jeden temat i czasem
    rozwiazanie nawet w miare prostego problemu okazalo sie na tyle skomplikowane, ze na koniec wszystkiego, kiedy problem byl rozwiazany,
    sposobem byla skladanka z rozwiazan znalezionych tu i owdzie dlatego, ze np wersja kompilera nie dziala z jednym rozwiazaniem a system operacyjny x64
    nie dziala z innym, ale jak sie pozbiera najlepsze czesci z kazdego to nawet cos tam dziala ... mniej wiecej, co potem mozna jeszcze pryszlifowac i "bedzie pan zadowolony".

    Tak wlasnie bylo z klasa ktora tu zamieszczam: Problem komunikacji przez USB. Nigdy specjalnie nie mialem ochoty studiowac tajnikow protokolu
    ani uczyc sie na pamiec 9-go rozdzialu z deskrypcji tylko poto zeby zaswiecic diode na plytce prototypowej. Potrzebowalem wiec rozwiazania ktore bedzie na tyle
    rozwiniete, zebym mial pelna kontrole nad moim urzadzeniem, ale na tyle proste zebym rozumial co sie dzieje, bez koniecznosci robienia fakultetu.

    Kontekst:

    Znalazlem kilka "Gotowych" klas w obiegu po internecie ale zadna nie odpowiadala moim potrzebom i jak jedna miala cos to druga tego nie miala ale miala cos innego itd.
    To co bylo mi potrzebne w mojej klasie wyglada tak:

    1. Modulowosc - o ile takie cos istnieje. Chcialem, zeby moja klase mozna bylo przypiac do jakiejkolwiek aplikacji czy innego w tym stylu ustrojstwa (Framework) i zeby kazda z funkcji byla kontrolowana niezaleznie, jak na przyklad notyfikacja o tym ze urzadzenie zostalo odpiete od komputera moze byc wylaczone lub po prostu zignorowane.
    2. Czytelnosc - Kod musi byc na tyle czytelny, zebym nie musial sie zastanawiac "co ta linia tutaj robi i po co w ogole tu jest".
    3. Prostota - Tak na prawde to nie chcialbym traktowac tej klasy jako gotowy produkt. Zaznacze ze mozna podpiac tak jak jest i bedzie dzialac,
    ale wolalbym to ujac jako dobry punkt startowy do czegokolwiek budowanego na bazie tej klasy. Wiekszosc innych przykladow, ktore znalazlem na necie
    byla zasmiecona kodem specyficznym dla danej aplikacji przy okazji tak wplecionym, ze czasem ciezko bylo wyrzucic niepotrzebny kod nie lamiac przy okazji
    wszystkiego innego. Zazwyczaj ten dodatkowy kod byl nie tylko zbedny ale czasem interferowal z tym, do czego dana klasa mnie byla potrzebna, automatycznie renderujac calosc bezuzytecznym.
    Zawsze twierdzilem, ze jak mozna cos zamknac w paru slowach to po co pisac eseje :).
    4. Prawdziwa komunikacja w obie strony w czasie rzeczywistym - czy tam na tyle rzeczywistym na ile to jest mozliwe. Wiekszosc przykladow, ktore znalazlem dzialaly na bazie tego,
    ze zeby uskac stan, czy zmiany w urzadzeniu (np: nacisniety guzik) trzeba bylo nacisnac przycisk na formie, albo zaaplikowac Timer() ktory zrobi to dla ciebie raz na jakis czas.
    To bylo dla mnie cos, czego zupelnie i absolutnie nie bylem w stanie zaakceptowac jako rozwiazanie i dlatego moja klasa kreuje osobny Watek (Thread) ktory sobie siedzi cichutko w tle i czeka az urzadzenie bedzie mialo cos do powiedzenia.
    a kiedy urzadzenie cos mowi, to tem watek podnosi reke i krzyczy (tak troche asynchronicznie) ze cos tam ma, w miedzyczasie cekajac na wiecej.
    5. Stabilnosc - Wekszosc rozwiazan, ktore znalazlem do tej pory, po wielu trudach jak juz zaczely dzialac, to dzialaly ale tylko do momentu, kiedy stalo sie cos nieoczekiwanego jak np:
    urzadzenie zostalo wyjete z gniazda USB. Czasem tylko byl komunikat, czasem nie, czasem sie po prostu wieszal, a w jeszcze innych przypadkach "wygladal jakby mial wybuchnac" zupelnie nie ogarniajac tego co sie stalo mimo ze stalo sie cos zupelnie trywialnego.
    To jest kolejna rzecz, ktorej nie bylem w stanie zaakceptowac, takze zbudowalem ta klase tak, zeby jak najczysciej rozprawiala sie z anomaliami i szybko dawala znac, ze cos sie dzieje.
    6. Kilka innych spraw, ktore szybko wyjda przy czytaniu kodu.

    Opis Klasy:

    Mysle i mam nadzieje, ze napisalem ta klase w najbardziej czytelny sposob jak tylko moglem z mysla, ze jesli ktos startuje w tej dziedzinie lecz ma juz troche doswiadczenia i w miare swobodnie porusza sie w C# to bedzie mogl bez wiekszych klopotow zrozumiec kod i szybko dotrze do sedna sprawy.
    Calosc kodu podzielilem na nastepujace grupy:

    1. UsbHidDevice - To jest podstawa klasa i punkt wejsciowy.
    2. USB - Katalog z podzespolami dzielacu sie na:
    a) Structures - budowa struktur potrzebnych do komunikacji z kernelem itd.
    b) Classes - zestaw podzespolow, ktore maja nastepujace zadania:
    Constants - Zestaw stalych wartosci (czesto zebranych z roznych opisow i dokumentacji), ktore ulatwiaja czytanie kodu.
    Device Discovery - Trzy funkcje potrzebne do tego, zeby znalezc urzadzenie w systemie.
    Device Communication - Trzy funkcje potrzebne do komunikacji z urzadzeniem
    DeviceChangeNotifier - Klasa, ktora jest niczym innym jak schowana forma, do tego zeby zbierac notifikacje od systemu, takie jak "urzadzenie Usb zostalo odpiete", bo wlasnie do tego jest.
    Dll Wrappers - 4 Statyczne klasy uzyte jako bufor z bibliotekami systemowymi: Hid, Kernel, SetuApi i User32
    Messaging - Prototyp pojedynczego pakietu bajtow jaki jest wysylany miedzu urzadzeniem a klasa. Jak zaznaczylem wczesniej to jest tylko prototyp i bazuje na tym ze jedna wiadomosc ma 64 bajty.

    I to Tyle. To jest dokladnie wszystko co jest potrzebne, zeby sobie pogadac z urzadzeniem typu HID.

    Jak Tego Uzyc:

    Code: csharp
    Log in, to see the code


    C# USB HID Device Interface Komunikacja

    Podsumowanie:

    Mam nadzieje, ze ktos znajdzie ta klase w miare uzyteczna, a jesli nie to moze czegos sie z niej nauczy.
    Co Do legalnosci i praw autorkich to powiem tak: Ten kod jest poskladany z wielu zrodel, kilku gotowcow napisanych przez inne osoby i w wiekszosci, zwlascza strukturalnie przeze mnie.
    Co do przykladow z netu, to bylo tego zbyt duzo, zeby wypisac wszystkich, ale najwieksza czesc pochodzi z artykulu napisanego przez Simona Innsa z http://www.waitingforfriday.com.
    Co do mnie to uwazam, ze od momentu, kiedy opublikuje ten artykul prosze rob z tym kodem co chcesz, wez sobie calosc, czesc, albo tylko poczytaj, bo w sumie jesli nauczysz sie z tego czegokolwiek to bedzie dla mnie najwieksza satysfakcja.

    Pozdrawiam.

    SR.

    Cool? Ranking DIY
    Can you write similar article? Send message to me and you will get SD card 64GB.
    About Author
    sajmosia
    Level 16  
    Offline 
    Has specialization in: zagorzaly piwosz
    sajmosia wrote 146 posts with rating 21, helped 15 times. Live in city Londyn. Been with us since 2011 year.
  • #2
    lukash90
    Level 16  
    a można by prosić pełny przykład kompletnej aplikacji? Do projektu z paczki dodałem Windows.Form i skopiowany wyżej i już się sypie
    Code: csharp
    Log in, to see the code

    Kompiluje się ale wyskakuje okno z błędem
    Quote:

    A project with an Output Type Class Libary cannot be started Directly
  • #4
    lukash90
    Level 16  
    Ok udało się uruchomić. Jednak nic się nie dzieje. Ustawiłem moje Vendor ID oraz Product ID i się nie łączy. Dałem break pointy przy funkcjach Device_OnConnected oraz Device_DataReceived i program ani razu do żadnej nie wszedł nie ważne czy najpierw uruchamiałem program a potem podłączałem urządzenie czy odwrotnie. Moje urządzenie jest na pewno sprawne i wysyła poprawnie dane, podglądam je w programie Device Monitor Studio. Jakieś rady dla amatora? Będę bardzo wdzięczny za pomoc, ponieważ akurat na gwałt potrzebuję uruchomić komunikację z USB i ten artykuł spadł mi z nieba (byle by to działało tylko)
  • #5
    mrh
    Level 18  
    Ja mogę komuś przesłać obsługę klasy HID, ale w języku C++ napisaną w Visual C++ 2008.
    Program działa wyśmienicie z płytką STM32F4-Discovery... odczytuje temperaturę z termometru i wyświetla. Program jest napisany na podstawie książki Pana Andrzeja Daniluka, na pewno mój kod nie jest doskonały, ale działa.
  • #6
    sas49
    Level 12  
    do kolegi mrh

    Mnie zainteresowało to co zaproponowałes w C++.
    Chetenie się zapoznam z Twoim kodem
  • #7
    Martin_250
    Level 12  
    Również jestem zainteresowany wersją w C++ w szczególności, że też dostałem właśnie tę płytkę stm32f4 discovery i próbuję odebrać jakieś dane.
    Z C# niestety nie miałem nigdy styczności i przy próbie wykorzystania dllki do testowej aplikacji ze screenshota dostaję błąd od buttona po naciśnięciu.
    Code:
    System.NullReferenceException: Odwołanie do obiektu nie zostało ustawione na wystąpienie obiektu.
  • #8
    sajmosia
    Level 16  
    Witam ponownie.

    Ze wzgledu na ilosc prozb postanowilem zbudowac w calosci dzialajace rozwiazanie.

    Zaczne od schematu minimallnego ukladu do komunikacji przez usb za pomoca PIC 18F2550

    C# USB HID Device Interface Komunikacja

    A Tak Wyglada Zbudowany Prototyp:

    C# USB HID Device Interface Komunikacja

    Do tego dorzuce kod zrodlowy, napisany pod MPLAB 8.90 dla kompilera C18 v3.45 w plikach nizej, I skompiloany HEX.

    Po zaprogramowaniu kostki I podpieciu do komputera taki mialem efekt:

    C# USB HID Device Interface Komunikacja

    C# USB HID Device Interface Komunikacja

    Po czym uruchomilem Programik w Visual studio (tez w plikach ponizej) I za kazdym kliknieciem guzika, uklad odpowiadal wymieniajac pierwsze 4 bajty wyslanej informacji.

    Mam nadzieje, ze to pomoze.

    Pozdro.
  • #9
    sajmosia
    Level 16  
    Tak na marginesie, jezeli komus pomoglo to rozwiazanie, lub natknal sie na jakies problemy, lecz je rozwiazal, to poprosilbym o notki.

    Pozdro.
  • #10
    sajmosia
    Level 16  
    Hejka.

    Na innym Forum dowiedzialem sie, ze jest jeden maly blad w strukturach. Wlasciwie to nie jest blad tylko problem wynika z tego, ze w windows x86 int I intPtr to jest to samo a w x64 nie, w zwiazku z czym nie musza ale moga wystapic problemy z komunikacja.

    Zeby poprawic ten blad wystarczy wymienic public int Reserved; na public IntPtr Reserved; w strukturze SpDeviceInterfaceData.

    Mam nadzieje, ze to pomoze.

    Pozdro.
  • #11
    polczyk
    Level 9  
    Witam,

    Jestem zainteresowany Twoją biblioteką. Gdzie można przeczytać bardziej szczegółowo o niej. Czy można z niej korzystać implementując komunikację z dowolnymi mikrokontrolerami np. z rodziną mikrokontrolerów LPC? Czy projekt biblioteki jest rozwijany?