Vývoj USB ovládača – 5. časť
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama

Vývoj USB ovládača – 5. časťVývoj USB ovládača – 5. časť

 
Hledat
Moderní platforma pro vytvoření vašeho nového webu – Wix.com.
Nyní už můžete mít web zdarma.
Vybavení pro Laser Game
Spuštěn Filmový magazín
Laser Game Brno

Vývoj USB ovládača – 5. časť

Google       Google       18. 11. 2013       17 278×

V tejto časti si vytvoríme GUI klientsku aplikáciu v jazyku C#, ktorej základom bude rozhranie na komunikáciu medzi ovládačom zariadenia a .Net aplikáciou vytvorené s pomocou PInvoke (Platform Invoke).

Reklama
Reklama

Úvod

V tomto kroku máme funkčné USB zariadenie a ovládač s ním komunikujúci pomocou libusb. Ďalším krokom je vytvorenie koncovej aplikácie, pomocou ktorej môže používateľ hardvér ovládať. Pre zmenu som si vybral platformu .NET a jazyk C#, vďaka ktorým bude jednoduchšie demonštrovať princípy.

Aplikácia bude tvorená jedným oknom, v ktorom sa bude zobrazovať stav tlačidiel na zariadení, teplota procesora a napätie na potenciometri. Taktiež bude obsahovať prvky na ovládanie LED diód, na vypísanie textu a odoslanie bitmapy na LCD. Pri vytvorení okna sa aplikácia pokúsi otvoriť spojenie s USB zariadením; pokiaľ zariadenie nebude pripojené, skončí s chybovým hlásením.

Celú komunikáciu so zariadením vložíme do jedného objektu, ktorý bude pomocou P/Invoke (Platform Invoke) komunikovať s natívnou knižnicou ovládača vytvorenou v minulom dieli tohto seriálu. Tento objekt alebo wrapper sa bude taktiež starať o spracovanie vzniknutých chýb a namiesto číselných hodnôt vrátených ovládačom vyhodí príslušnú výnimku.

P/Invoke – Platform Invoke

Pokiaľ v .NET programujete už nejaký ten čas, je dosť možné, že ste sa stretli s potrebou importovať funkcie natívnych knižníc. V C/C++ by ste toho dosiahli jednoducho prilinkovaním knižnice k vášmu programu alebo by ste knižnicu načítali pomocou funkcie LoadLibrary, získali adresu funkcie volaním GetProcAddress a pretypovaním by vám vznikol odkaz na funkciu, ktorú by ste zavolali ako každú inú. V .Net to ale funguje trochu inak, na volanie funkcií v natívnych knižniciach musíme využiť DllImport (System.Runtime.InteropServices v knižnici System.Core).

V prvom kroku si v zdrojovom súbore zadeklarujeme použitie názvoslovia:

using System.Runtime.InteropServices;

Potom nám stačí v triede deklarovať statickú metódu nasledovným spôsobom:

/// <summary>
/// Vyčistí obrazovku jednou farbou
/// </summary>
/// <param name="color">Farba</param>
/// <returns></returns>
[DllImport("DeviceWrapper.dll",
 CallingConvention = CallingConvention.Cdecl)]
private static extern uint ClearScreen(uint color);

Čím prekladač vie, že metóda ClearScreen je externá a nachádza sa v knižnici DeviceWrapper.dll (to je náš ovládač). Každá takto vložená funkcia musí byť označená ako static extern s atribútom DllImport.

Naša klientska aplikácia bude importovať všetky funkcie exportované v ovládači DeviceWrapper, nebudú sa ale používať priamo. Napr. funkcia ClearScreen preberá jeden argument, ktorým je 24bitové číslo reprezentujúce farbu. Návratová hodnota je taktiež číslo (0 v prípade, že funkcia uspeje alebo iná hodnota popisujúca chybu). My ale túto metódu zabalíme v objekte (wrapper) tak, aby parameter farby nebol číslo, ale typ System.Color, a odstránime návratový typ, zmeníme ju na void. V prípade, že volanie funkcie ClearScreen z knižnice DeviceWrapper.dll zlyhá, nevrátime volajúcemu kód chyby, ale vyhodíme výnimku. Je to omnoho prijateľnejší spôsob. Týmto spôsobom dosiahneme to, aby bola metóda ClearScreen volaná vždy v správnom kontexte.

/// <summary>
/// Vyčistí obrazovku
/// </summary>
/// <param name="color">Farba</param>
public void ClearScreen(Color color)
{
    // Spojenie so zariadením musí byť otvorené
    if (!isOpen)
        throw new DeviceFailException(
            DeviceFailException.DeviceError.NotOpen);

    // Zavolať funkciu ClearScreen z DeviceWrapper.dll
    uint result = ClearScreen((uint)color.ToArgb());

    // Pokiaľ volanie zlyhalo, vyhodíme výnimku s kódom chyby
    if (result != 0)
        throw new DeviceFailException(
            (DeviceFailException.DeviceError)result);
}

Rozhranie na komunikáciu s ovládačom

Základ aplikácie bude tvorený jedným objektom – rozhraním na komunikáciu s ovládačom. Pri štarte aplikácie sa vytvorí inštancia tohto objektu, otvorí sa spojenie s USB zariadením a ďalšia komunikácia s ním už bude prebiehať iba pomocou tohto objektu. Pri ukončení aplikácie sa objekt odstráni, tým sa zatvorí spojenie s ovládačom a zariadením. Na obrázku je znázornené, aké metódy bude objekt obsahovať a ďalšie pomocné štruktúry, triedy a dátové typy.

Je dôležité uvedomiť si, že dátové štruktúry (pakety) sú rovnaké pre zariadenie, ovládač aj koncovú aplikáciu. Preto pri vývoji ovládača pracujeme s rovnakými dátovými typmi v zariadení aj na strane hosta. Táto klientska aplikácia definuje štyri takéto štruktúry, a to usbapp_bulk_out_t, usbapp_control_in_t, usbapp_control_out_t a usbapp_interrupt_in_t.

Ďalej potrebujeme definovať výnimky, ktoré objekt vyhodí pri chybnej komunikácii alebo pri nesprávnom použití rozhrania. Na to nám budú slúžiť dve triedy, DeviceFailException, ktorá bude vyhodená, ak dôjde k chybe v ovládači alebo zariadení, a DeviceNotOpenException, ktorú rozhranie vyhodí, ak sa programu nepodarí nadviazať spojenie so zariadením.

Nakoniec zadefinujeme štruktúry a enumy, ktoré poskytnú informácie z paketov cieľovému používateľovi rozhrania. Ako príklad uvediem nastavenie LED a LCD.

Aplikácia potrebuje odoslať zariadeniu príkaz, aby rozsvietilo modrú a zelenú LED diódu, zaplo LCD displej a taktiež aby posunulo obsah LCD displeja o 50 px. Keďže každé nastavenie v pakete je číselné, užívateľ nášho rozhrania by musel poznať, aké čísla pripadajú na modrú a zelenú LED. Taktiež by musel vedieť, akým príznakom zapne LCD displej. Preto je dôležité, aby naše rozhranie tieto čísla skrylo za enum dátové typy ako napr. zoznam LED diód a ich číselné hodnoty:

/// <summary>
/// Nastavenia LED diód
/// </summary>
public enum Led
{
    None = 0,
    Blue = 0x1,
    Green = 0x2,
    Amber = 0x4
};

Potom môže užívateľ jednoduchým spôsobom zostaviť nastavenia a odoslať ich zariadeniu:

// Vytvoriť nastavenie LED a LCD
Device.LedLcdOptions ledLcd = new Device.LedLcdOptions(
    Device.Led.Blue | Device.Led.Green, // Modrá a zelená LED
    0, // Oranžová nebude svietiť
    Device.DisplayOption.DisplayOn, // Zapnúť LCD displej
    0, // Displej nebude podsvietený
    50); // Obsah displeja bude posunutý o 50 px
 
// Odoslať nastavenie zariadeniu
device.SetupLedLcd(ledLcd);

Metóda Device.SetupLedLcd(LedLcdOptions options) skontroluje, či je spojenie na zariadenie otvorené a ak áno, zostaví paket usbapp_control_out_t z nastavení, ktoré užívateľ predal ako argument options. Zároveň skontroluje platnosť nastavení a to, či hodnota PWM a hodnota podsvietenia LCD displeja neprekročia max. hodnoty stanovené USB zariadením. Následne paket posunie ovládaču volaním funkcie SetupDevice z knižnice ovládača DeviceWrapper.dll.
Tá vytvorí USB paket, jeho dáta naplní obsahom štruktúry usbapp_control_out_t a odošle ho zariadeniu, ktoré paket prijme a spracuje. Akonáhle host potvrdí príjem paketu zariadením, funkcia SetupDevice vráti hodnotu určujúcu, či prenos prebehol v poriadku alebo sa vyskytla chyba.

Naše rozhranie túto vrátenú hodnotu porovná a pokiaľ zistí, že počas prenosu nastala chyba, vyhodí výnimku.

/// <summary>
/// Nastavi LED a LCD
/// </summary>
/// <param name="options">LED a LCD nastavenia</param>
public void SetupLedLcd(LedLcdOptions options)
{
    if (!isOpen)
        throw new DeviceFailException(
            DeviceFailException.DeviceError.NotOpen);
 
    // Vytvoriť paket obsahujúci nastavenia LED a LCD
    usbapp_control_out_t data = new usbapp_control_out_t();
    data.leds = options.Leds;
    data.pwmLedDuty = options.PwmLedDuty > MaxPwm ?
        MaxPwm : options.PwmLedDuty;
    data.display = options.LcdOptions;
    data.backlight = options.Backlight > MaxBacklight ?
        MaxBacklight : options.Backlight;
    data.displayScroll = options.LcdScroll;

    // Posunúť paket ovládaču, ktorý ho odošle
    uint result = SetupDevice(ref data);

    // Vyhodiť výnimku ak počas prenosu vznikla chyba
    if (result != 0)
        throw new DeviceFailException(
            (DeviceFailException.DeviceError)result);
}

Obdobným spôsobom trieda Device poskytuje prístup k ostatným funkciám ovládača. V princípe je potrebné iba „zabaliť“ volania ovládača takým spôsobom, aby klientska aplikácia na platforme .NET mohla využívať tieto metódy v súlade s konvenciami .NET a taktiež aby bolo možné spracúvať výnimky namiesto chybových kódov.

Front end – používateľské rozhranie

Na otestovanie funkčnosti poslúži jednoduchá GUI aplikácia, ktorá pri svojom štarte skontroluje, či je k počítaču pripojené naše zariadenia a ak áno, vytvorí klientske rozhranie pre komunikáciu s týmto zariadením. Používateľ tak bude mať možnosť jednoducho odosielať príkazy zariadeniu pomocou nami vytvoreného rozhrania.

Komunikácia bude pozostávať z troch častí:

  1. Príkazy odosielané klientom do zariadenia – nastavenie LED a vykresľovanie na LCD
  2. Pravidelná aktualizácia hodnôt z ADC prevodníka
  3. Vlákno bežiace na pozadí aplikácie čakajúce na prerušenia zo strany zariadenia

Keďže väčšinu práce bude mať na starosti rozhranie v triede Device, GUI aplikácii zostáva konvertovať vstupné hodnoty od používateľa a zobrazovať výstup zo zariadenia a čo je podstatnejšie, spracovanie chýb. V našom prípade pri vzniku chyby program zobrazí bližšie informácie o príčine vzniku chyby a následne sa ukončí.

Záver

A na záver si môžete stiahnuť zdrojový kód aplikácie a pozrieť ukážku toho, ako zariadenie a klientska aplikácia fungujú v praxi:

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

2 názory  —  2 nové  
Hlasování bylo ukončeno    
3 hlasy
Google
Autor sa venuje programovaniu v jazykoch C#, C/C++, Delphi a v poslednej dobe sa taktiež zaujíma o vývoj hardvéru.
Web    

Nové články

Obrázek ke článku NVIDIA shrnuje přehled novinek na E3 2018

NVIDIA shrnuje přehled novinek na E3 2018

Společnost NVIDIA si u příležitosti E3 2018 připravila řadu novinek, které uvádí v kompletním přehledu, Například nové hry s podporou NVIDIA Highlights, která je součástí aplikace GeForce Experience, i nadále nabírá na obrátkách. Kromě výše zmíněné Shadow of the Tomb Raider získaly podporu také hry Dirty Bomb a Switchblade.

Reklama
Reklama
Obrázek ke článku SODAT vidí budoucnost datové bezpečnosti ve strojovém učení

SODAT vidí budoucnost datové bezpečnosti ve strojovém učení

Firmy chrání svá citlivá data často nedostatečně. Podle průzkumu společnosti SODAT se v minulém roce setkalo až 80 % z nich s bezpečnostním incidentem ztráty nebo úniku dat. Jedna z pilotních firem, která testovala novou verzi řešení SODAT Protection & Analytics 2.0pro bezpečností analýzu a monitoring dat díky novince zjistila, kdo z disku smazal důležité výkresy a mohla na incident včas reagovat.

Obrázek ke článku Kontrolujete pracovní emaily i na dovolené? 7 tipů odborníka, jak nepřijít o data

Kontrolujete pracovní emaily i na dovolené? 7 tipů odborníka, jak nepřijít o data

Letní měsíce jsou pro většinu zaměstnanců spojené s každoroční dovolenou. Z údajů Českého statistického úřadu vyplývá, že v roce 2017 podnikli Češi přes 13 milionů delších cest (tzn. s více než čtyřmi noclehy). Přitom právě na období července, srpna a září připadá více než 7,5 milionů z nich. Nicméně tradiční představu o dovolené jako o čase, kdy má práci na starost někdo jiný, Češi boří. 

Obrázek ke článku 10 SEO mýtů, které už nemusíte v roce 2018 řešit

10 SEO mýtů, které už nemusíte v roce 2018 řešit

„Kolik má být na stránce klíčových slov?“, „Nemáš vyplněný meta tag keywords, to nebude fungovat.“, „Katalogy jsou mrtvý“. Také jste už slyšeli některé z těchto otázek? Pojďme si na ně konečně jednou provždy odpovědět.

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032018 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý