Minule jsme tu probrali jak napsat pro STM32F4 Discovery kit firmware, které z kitu vytvoří USB Custom HID Device. Na vyzkoušení funkčnosti jste mohli použít hotovou univerzální aplikaci od ST Microelectronic - USB HID Demonstratror. V tomto dílu si ukážeme jak napsat svojí vlastní aplikaci na PC, která s kitem bude komunikovat.



Úvod

Můžete na to jít jednoduše nebo složitě Já myslel že na to jdu jednoduše, ale nakonec se ukázalo že jsem si málem musel trhat vlasy. Pro vaše pobavení to popíšu. Nejjednodušší cesta je použít nějakou knihovnu a pak nacvakat GUI aplikaci a finito presto. Taková byla moje úvaha a proto jsem se vydal na internet najít nějakou slušnou knihovnu. Kromě několika komerčních variant za dost peněz jsem našel jen jednu použitelnou. Jde o dílo, které napsal Florian Leitner z Německa, ale v roce 2007, takže nejde o žádnou čerstvou věc. Jsem si říkal, že když to napsal před takovou dobou, tak jistě půjde o časem prověřený produkt. No to jsem se hodně sekl. Ono to funguje jen napůl. Knihovna data přijímá, ale nevysílá. Takže sice můžete číst například stavy tlačítek na kitu, které kit odesílá v reportech, ale nic na kitu nenastavíte. Přečetl jsem si diskuzi pod blogem Floriana a opravdu tam někteří nadávají že jim nejde odesílat data. ALE NIKDO TO NEODSTRANIL, boha jeho! Snad to nebude problém, pomyslel jsem si, ale byl. Ke všemu ještě nenávidím Windows API, je mi po něm špatně od žaludku. Jak vidím WM_CLOSED, tak myslím na closet
No abych to neprotahoval, tak jsem na tom strávil veselý víkend, než jsem našel špatnou definici funkce pro zápis. Na místo deklarace:
static public extern int WriteFile(int hFile, ref byte lpBuffer, int nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, int lpOverlapped);
má být deklarace
static public extern int WriteFile(int hFile, ref byte lpBuffer, int nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, ref OVERLAPPED lpOverlapped);

Tudíž to nikomu nemohlo chodit (přesněji možná to mohlo chodit někomu v dobách Windows 98) a ty hlasité pochvaly u článku s popisem knihovny mě tedy celkem překvapují. No nic, důležité je, že teď už knihovna chodí. A tedy existuje jednoduchá cesta, jak si napsat svou aplikaci, která bude komunikovat s USB HID zařízením.
Ještě bych nerad zapomněl na italského kolegu s nickem Neon, který také louskal tuto knihovnu a vzájemně jsme si sdělovali poznatky. Jeho nápad byl, že jsou potřeba dva handlery (HidHandler a WriteHandler), nichž první slouží pro čtení a druhý pro zápis (Také jsem to při úpravách aplikoval). Svůj postup popsal na serveru xene a naleznete jej zde. Neon se zajímá o konstrukce založené na mcu od Microchip, (18F..).


Popis

Pokud chcete jen vyzkoušet hotovou verzi, tak si stáhnete dle odkazů dole projekt pro tento díl seriálu a rozbalíte si ho do vašeho adresáře Dokumenty do složky "Dokumenty\Visual Studio 2010\Projects\MCU_HID_Demo" (složka dokumenty je tam jen jednou!). V adresáři "Visual Studio 2010\Projects\MCU_HID_Demo\MCU_HID_Demo\bin\Release" naleznete výsledný exe soubor MCU_HID_Demo.exe a knihovnu USBHIDDRIVER.dll, kterou program využívá. To je právě ta knihovna od Floriana, o které byla řeč výše.
Předpokládám že v kitu máte aplikaci z minulého dílu, tedy firmware pro USB Custom HID Device. Takže kit připojte dvěma kabely, jak už máte zažité a PAK můžete spustit demo exe aplikaci. Když jí spustíte před tím, než budete mít kit připojen, tak uvidíte následující stav.



Aplikace se zhruba navržena v optické podobě provedení kitu. A to že na aplikaci při spodním okraji nesvítí led, vlevo vedle USB konektoru, znamená že kit není správně připojen na USB. Pokud budete mít kit připojen správně, tak uvidíte následující podobu aplikace (na na kitu pochopitelně bude LED také svítit).



A v této chvíli už můžete propojení vyzkoušet. Když stisknete na kitu USER tlačítko, tak se Vám na aplikaci modré tlačítko změní na světle modré. A naopak, když kliknete na tmavě zakreslené LED na PC aplikaci, tak se vám rozsvítí jak na obrazovce, tak i na kitu. Pochopitelně, že jde jen o studijní demo aplikaci. Ve skutečnosti můžete přenášet zajímavější věci, než to, zda se má rozsvítit LED.

Pokud chcete program upravovat, tak začnete tím, že si od Microsoftu stáhnete a nainstalujete jeho prostředí VisualStudio 2010 C# ve verzi Express, která je zdarma. Dle mého soudu je to nejednoduší cesta, jak si pořídit svou aplikaci pro prostředí Microsoft Windows. Po spuštění si otevřete projekt a můžete vesele upravovat a překládat. Vaše vlastní aplikace s uděláte tak, že si otevřete nový projekt a pak si do References přidáte USBHIDLIBRARY.dll tak, že kliknete pravým tlačítkem myši na References vlevo nahoře na obrazovce a zvolíte Add references.



Pak si zvolíte záložku Browse a nacvakáte si knihovnu.


Program

Je jednoduchý, nechtěl jsem to komplikovat. Jako úkol si můžete zkusit, jak realizovat to, aby program po spuštění před tím, než se připojí USB zařízení, sice vypsal že zařízení není připojeno, ale aby čekal na připojení a po připojení aby umožnil další práci.

Na začátku programu si vedle globálních proměnných nadefinujte spojení na vaše zařízení (já to mám ve Form1.cs).
   public partial class Form1 : Form
    {   // budeme potrebovat jen 2 bajty
        Byte[] Buffer = new byte[2];
        // 4 LEDky
        Byte[] LED_ON = new byte[4];
        // flag na USB
        Byte[] USB_OK = new byte[1];
        Boolean Pom;
        USBInterface usbhid = new USBInterface("vid_0483", "pid_5710");
        /* poznamka - pouzivejte mala pismena, tj. misto 0E1A pouzijte 0e1a! */


V další části se pak na Usbhid budeme odkazovat. Například hned při inicializaci formuláře (komponety) si připojím USB a ověřím stav.
if (usbhid.Connect())
            {
                /* uspesne pripojeni */
                // nastavime myUsbCatcher fci jako vykonnou cast realizace USB komunikace
                usbhid.enableUsbBufferEvent(new System.EventHandler(this.myUsbCacher));
                usbhid.startRead();
                USB_OK[0] = 1;
                pb_USB.BackColor = Color.LawnGreen;
                lb_Discon.BackColor = Color.DarkGreen;
                lb_Discon.ForeColor = Color.DarkGreen;
            }


Tudíž, pokud se povede connect(), tak začnu sledovat Eventy z USB, zapnu čtení z USB a zneviditelním nápis na aplikaci, že kit je nepřipojen tím, že zvolím barvu písma stejnou jako podkladu.

Otázku kliknutí na obrázek LED řeším v následujícím kusu programu (pro jednoduchost má každá LED svůj kód, pochopitelně ale že to je možné parametrizovat).
       private void pb_LED3_Click(object sender, EventArgs e)
        {
            if (LED_ON[0] == 0 && USB_OK[0] == 1)
            {
                /* chceme rozsvitit */
                LED_ON[0] = 1;
                pb_LED3.BackColor = Color.Orange;
                Buffer[1] = 1;
                Buffer[0] = 1;
                Pom = usbhid.write(Buffer);
            }
            else
            {
                // chceme zhasnout
                LED_ON[0] = 0;
                pb_LED3.BackColor = Color.Black;
                Buffer[1] = 0;
                Buffer[0] = 1;
                Pom = usbhid.write(Buffer);
            }
        }


Tedy, zcela triviálně nastavím hodnoty v řetězci Buffer[] a zapíšu do USB pipe, což se postará o dopravu až do USB zařízení.

Nyní zbývá ještě otázka příjmu a zpracování dat, které k nám docestují přes USB pipe ze zařízení. O to se stará právě Cacher. Po příjmu dat se vyvolá myUsbCacher (který jsme si zprovoznili výše, při inicializaci)a tam také data zpracujeme.
private void myUsbCacher(object sender, EventArgs e)
        { /*  tady vyresime prenos dat z kitu pres USB do PC */
            if (USBHIDDRIVER.USBInterface.usbBuffer.Count > 0)
            {   /* neco je v bufferu, musime precist */
                byte[] currentRecord = null;
                int counter = 0;
                while ((byte[])USBHIDDRIVER.USBInterface.usbBuffer[counter] == null)
                {
                    lock (USBHIDDRIVER.USBInterface.usbBuffer.SyncRoot)
                    {
                        USBHIDDRIVER.USBInterface.usbBuffer.RemoveAt(0);
                    }
                }
                currentRecord = (byte[])USBHIDDRIVER.USBInterface.usbBuffer[0];
                lock (USBHIDDRIVER.USBInterface.usbBuffer.SyncRoot)
                {
                    USBHIDDRIVER.USBInterface.usbBuffer.RemoveAt(0);
                }

                /* tim to mame nacteno a ted to zpracujeme */
                /* stav USER BUTTONU se posila v Reportu c. 5 */
                Buffer[0] = 0x05; /* report cislo 5 */
                Buffer[1] = 0x01;
                if (currentRecord[0] == 0x05 && currentRecord[1] == 0x01)
                {  /* stisknuto */
                    pb_User.BackColor = Color.DodgerBlue;
                }
                else if (currentRecord[0] == 0x05 && currentRecord[1] == 0x00)
                {  /* uvolneno */
                    pb_User.BackColor = Color.Blue;
                }
            }
        }


No a tím je vše hotovo. Kromě pár dalších řádků, z nichž většinu za vás stejně vygeneruje VisualStudio, už nic více nepotřebujete. Výsledná aplikace také má jen cca 12 kB, což jak uznáte je na Windows HODNĚ MALÁ hodnota. Takže očekávám, že se brzy pochlubíte se svými aplikacemi na měření teploty či čehokoliv jiného a budeme moci publikovat další příklady, aby se začínající programátoři měli čím inspirovat. Doba pokročila, a od hnusných aplikací v C++, u kterých měly zdrojové kódy i triviální věci desítky kilobajtů jsme se dostali do situace, kdy napsat aplikaci pro PC v C# zvládne i mírně nadprůměrně duševně vybavená kočka domácí (felis catus).


Závěr

S ohledem na v současnosti probíranou otázku autorských práv a legislativu ACTA a PIPA, bych rád sdělil, že si doufám každý uvědomuje že zde publikovaný software je určen pouze ke studijním účelům. Jakékoliv využití ke komerčním účelům je zakázáno bez písemného svolení autora. Politikům, právníkům, poslancům a zejména europoslancům není tento software dovoleno ani studovat.

Pokud se domníváte, že si text a přiložený demoprogram zaslouží Vaše ocenění, tak můžete poslat svou dotaci. Předem děkuji všem! Podpoříte tím vznik dalších článků. Jako další naplánovaný díl na kterém pracuji je WEB server s STM32F VL Discovery kitem.





Odkazy

Materiál k HID naleznete zde.
USB HID Library, jejímž autorem je Florian Leitner naleznete zde.
Na webu Microsoft naleznete VisualStudio 2010 Express C# zde.
Zazipovaný projekt k tomuto dílu naleznete zde.

Začínáme s STM32F4 kitem 1. odkaz (vývojové prostředí, atd.)
Začínáme s STM32F4 kitem 2. odkaz (USB Úvod)
Začínáme s STM32F4 kitem 3. odkaz (USB Enumerace)
Začínáme s STM32F4 kitem 4. odkaz (USB Virtual COM port)
Modifikce USB HID pro STM32F103 odkaz
Začínáme s STM32F4 kitem 5. odkaz (označení portů, alternativní funkce)
Začínáme s STM32F4 kitem 6. odkaz (VGA monitor)
Začínáme s STM32F4 kitem 7. odkaz (USB Custom HID)