USB-programmering i Android. Vi använder USB-gränssnittet för kommunikation. Bok: USB-gränssnitt (övning av användning och programmering) Programmering för att fungera med usb

USB-bussen (Universal Serial Bus) dök upp den 15 januari 1996, med godkännandet av den första versionen av standarden av Intel, DEC, IBM, NEC, Northen Telecom och Compaq.

Huvudmålet med standarden som satts upp för dess utvecklare är att skapa möjligheten för användare att arbeta i Plug&Play-läge med kringutrustning. Det betyder att det måste vara möjligt att ansluta enheten till en kördator, automatiskt känna igen den direkt efter anslutning och sedan installera lämpliga drivrutiner. Dessutom är det lämpligt att förse lågeffektsenheter med ström från själva bussen. Busshastigheten bör vara tillräcklig för de allra flesta kringutrustning. USB-styrenheten bör endast uppta ett avbrott, oavsett antalet enheter som är anslutna till bussen, det vill säga lösa problemet med brist på resurser på de interna bussarna på en IBM PC-kompatibel dator.

Nästan alla uppgifter löstes i USB-standarden och våren 1997 datorer utrustade med kontakter för USB-anslutningar enheter. Nu har USB blivit så aktivt implementerat av tillverkare av kringutrustning till datorer att till exempel iMAC-datorn från Apple Computers endast har USB som extern buss.

USB 1.0-funktioner är följande:

1. hög dataöverföringshastighet (full hastighet) – 12 MB Det/Med;

2. maximal kabellängd för höghastighetsutbyte – 5 meter;

3. låg datautbyteshastighet (låghastighet) – 1,5 MB Det/Med;

4. maximal kabellängd för låg dataöverföringshastighet är 3 meter;

5. maximalt antal anslutna enheter – 127;

6. möjlig samtidig anslutning av enheter med olika växelkurser;

8. Den maximala strömförbrukningen per enhet är 500 mA.

Därför är det lämpligt att ansluta nästan alla kringutrustningar till USB 1.0, förutom digitala videokameror och höghastighets hårddiskar. Detta gränssnitt är särskilt praktiskt för att ansluta ofta anslutna/bortkopplade enheter, såsom digitalkameror.
Möjligheten att använda endast två datahastigheter begränsar bussens användbarhet, men minskar avsevärt antalet gränssnittslinjer och förenklar hårdvaruimplementeringen.
Strömförsörjning direkt från USB är endast möjlig för enheter med låg effekt som tangentbord, möss, joysticks etc.

USB-signaler överförs via en 4-trådskabel, som visas schematiskt i bilden nedan:

Figur 2.6.1 – USB-signalkablar

Här är GND den gemensamma trådkretsen för att driva kringutrustning, Vbus är +5 V även för kraftkretsar. D+-bussen är för att överföra data på bussen, och D-bussen är för att ta emot data.
Fullhastighetsbusskabeln är en partvinnad kabel, skyddad av en skärm, och kan även användas för låghastighetsdrift. En kabel för drift endast vid lägsta hastighet (till exempel för att ansluta en mus) kan vara vilken som helst och oskärmad.
Kontakterna som används för att ansluta kringutrustning är indelade i serier: "A"-seriens kontakter (kontakt och uttag) är endast avsedda för anslutning till en källa, såsom en dator, "B"-seriens kontakter (kontakt och uttag) är endast avsedda för anslutning till en kringutrustning.

USB-kontakter har följande stiftnummer, som visas i Tabell 2.6.1.

Tabell 2.6.1 – Syfte och märkning av USB-kontakter

1999, samma konsortium datorföretag, som initierade utvecklingen av den första versionen av USB-bussstandarden, började aktivt utveckla version 2.0 av USB, som kännetecknas av införandet av ett extra höghastighetsläge (Hi-speed). Bussbandbredden har utökats 40 gånger, upp till 480 Mbit/s, vilket gjorde det möjligt att överföra videodata via USB.
Kompatibiliteten för all tidigare utgiven kringutrustning och höghastighetskablar är helt bevarad. Standardstyrenheten 2.0 är redan integrerad i systemlogikuppsättningen av programmerbara enheter (t.ex. moderkort personlig dator).

2008 skapade Intel, Microsoft, Hewlett-Packard, Texas Instruments, NEC och NXP Semiconductors standardspecifikationen USB 3.0. I USB 3.0-specifikationen är den uppdaterade standardens kontakter och kablar fysiskt och funktionellt kompatibla med USB 2.0, men utöver de fyra kommunikationslinjerna har ytterligare fyra tillkommit. De nya stiften i USB 3.0-kontakter är dock placerade separat från de gamla på en annan stiftrad. USB 3.0-specifikationen ökar den maximala informationsöverföringshastigheten till 5 Gbps – vilket är en storleksordning högre än de 480 Mbps som USB 2.0 kan ge. Dessutom har den maximala strömmen höjts från 500 mA till 900 mA per enhet, vilket gör att du kan driva vissa enheter som tidigare krävde en separat strömförsörjning.

Anta att du har utvecklat en USB-enhet som du behöver arbeta med med en dator. Detta kan uppnås på minst två sätt:

1. utveckling av en fullfjädrad drivrutin för operativsystemet;

2. användning av ett USB-gränssnitt av särskild klass - enheter som kallas HID-enheter (Human Interface Device).

Den första metoden är universell: med tillräcklig kunskap inom området för att skriva drivrutiner kan du programmera den för att fungera med vilken enhet som helst med vilken hastighet som helst som stöds av USB. Men det här är en ganska svår uppgift.

Det andra sättet är som följer. Det finns ett gränssnitt som stöds av moderna operativsystem för dator-mänskliga gränssnittsenheter eller HID-enheter, som:

1. tangentbord, möss, joysticks;

2. olika sensorer och läsare;

3. Spelstyrning och pedaler;

4. knappar, strömbrytare, regulatorer.

En sådan enhet, om den uppfyller kraven för HID-enheter, kommer att kännas igen automatiskt av systemet och kommer inte att kräva att skriva speciella drivrutiner. Dessutom är programmering av dem vanligtvis mycket enklare än att skriva en anpassad enhetsdrivrutin. Tyvärr har denna metod en betydande nackdel: hastigheten för informationsutbytet med HID-enheten är mycket begränsad och uppgår till maximalt 64 kB/s.

I princip, baserat på HID-teknik, är det möjligt att organisera interaktion med vilken enhet som helst, även om den inte i strikt mening är en gränssnittsenhet mellan en person och en dator. Detta eliminerar den tidskrävande utvecklingen av en unik enhetsdrivrutin och sparar tid på att utveckla en ny USB-enhet. På värdsidan kommer kommunikationen med enheten att styras av den vanliga HID-drivrutinen som ingår i operativsystemet. Du behöver bara göra det från enhetens sida minimikrav USB-HID-protokoll.

Det är värt att notera att många USB-enheter, som vid första anblicken inte faller under definitionen av mänskliga interaktionsenheter, fortfarande är mer logiska att implementeras som HID-enheter. Detta fenomen är vanligt inom tillverkningsutrustningsområdet, som nyligen har upplevt en massiv användning av USB-teknik. Tänk till exempel på en laboratorieströmförsörjning med möjlighet att ställa in parametrarna för dess utsignaler från en dator med hjälp av ett USB-gränssnitt. Strömkällan i sig är utan tvekan inte ett sätt att interagera med en person. Men i det här fallet duplicerar funktionerna som implementeras via en USB-anslutning tangentbordet, kontrollerna och indikatorerna installerade på själva enheten. Och dessa kontroller faller inom definitionen av HID. Följaktligen är det mest logiskt att organisera en strömförsörjning med dessa USB-funktioner som en HID-enhet.

I det aktuella exemplet kommer en låg dataöverföringshastighet att vara tillräcklig för normal drift, i andra fall kan enheter kräva mycket växelkurs. Låg överföringshastighet är den huvudsakliga begränsningen för HID-enhetsdesignalternativet, som, i jämförelse med 12 Mbit/s fullhastigheten för USB 1.0-bussen, ser ut som en stor nackdel med HID-teknik när det gäller att välja en specifik USB-implementering. Men för många kommunikationsuppgifter är den angivna hastigheten tillräckligt och HID-arkitekturen som ett specialiserat verktyg tar sin rättmätiga plats bland metoderna för att organisera datautbyte.

Det finns två typer av HID-enheter: de som deltar (boot) och de som inte deltar i den initiala uppstarten av datorn. Det mest slående exemplet på en startbar USB-HID-enhet är ett tangentbord som börjar fungera när datorn startar.

När du designar en HID-enhet måste följande specifikationskrav uppfyllas:

1. Fullhastighets HID-enhet kan överföra 64000 byte varje sekund eller 64 byte var 1ms; En låghastighets HID-enhet kan överföra upp till 800 byte per sekund, eller 8 byte var 10:e ms.

2. HID-enheten kan schemalägga sin avfrågningsfrekvens för att avgöra om den har färska data att överföra.

3. Datautbyte med HID-enheten utförs genom en speciell struktur som kallas en rapport. Varje definierad rapport kan innehålla upp till 65535 byte med data. Rapportstrukturen har en mycket flexibel organisation som låter dig beskriva vilket dataöverföringsformat som helst. För att ett specifikt rapportformat ska bli känt för värden måste mikrokontrollern innehålla en speciell beskrivning - en rapportdeskriptor.

USB-interaktion implementeras direkt på mikrokontrollern på flera sätt:

1. använda en styrenhet med hårdvarustöd, till exempel AT90USB*, från atmega;

2. använda mjukvaruemulering av USB-gränssnittet på valfri mikrokontroller.

För mjukvaruimplementering finns det idag ett antal färdiga lösningar för olika familjer av mikrokontroller. För AVR mikrokontroller, till exempel Atmega8 är det möjligt att använda följande gratisbibliotek på C-språket:

Båda är ganska lätta att använda, ger full emulering av USB 1.1-låghastighetsenheter, med undantag för hantering av kommunikationsfel och elektriska egenskaper, och körs på nästan alla AVR-kontroller med minst 2 kilobyte flashminne, 128 byte RAM och en frekvens på 12 till 20 MHz.

För att skriva applikationer som stöder Windows USB HID-enheter behöver du hid* header-filerna som ingår i WDK (Windows Driver Kit), eller så kan du använda det fritt tillgängliga hidlibrary-biblioteket eller ett annat liknande.

Således är USB-programmering i allmänhet en ganska komplex uppgift, som kräver en speciell mikrokontroller med hårdvarustöd och skrivning av en drivrutin för operativsystemet. Men i praktiken, när du utvecklar enheter, kan du använda ett mycket enklare HID-enhetsgränssnitt, vilket stöd implementeras på nivån av en standardsystemdrivrutin, och programmering förenklas genom att använda befintliga funktionsbibliotek.

Kontrollfrågor

  1. Vad är skillnaden mellan D- och GND-kablarna i USB? Varför kan du inte använda en gemensam tråd för ström och signal?
  2. Hur många USB-hastighetslägen finns det idag (inklusive version 3.0)?
  3. Vad är en HID-enhet? Varför kräver de inte att skriva drivrutiner för att fungera i moderna operativsystem?
  4. Är det möjligt att implementera USB-enheter med en mikroprocessor som inte har inbyggt gränssnittsstöd?
  5. Vilka är de största skillnaderna mellan USB 3.0 och tidigare versioner?

Som redan nämnts tillhandahåller Windows-operativsystem mjukvarustöd för funktionen av enheter anslutna till USB-bussen. Bearbetning av USB-enhetsdataströmmar på operativsystemnivå utförs av en stapel standarddrivrutiner som utför de grundläggande funktionerna för att hantera alla USB-enheter och utbyta data mellan dem och systemet.

Om du behöver skriva programvara För alla USB-enheter som skulle utöka sina databehandlingsmöjligheter kan du välja en av tre möjliga vägar:

skriv din egen enhetsdrivrutin som skulle tillhandahålla alla nödvändiga kontroll- och datautbytesfunktioner, och ett program som skulle interagera med denna drivrutin i användarläge. I det här fallet kan du helt avstå från standardsystemdrivrutiner;

skriv en filterdrivrutin som skulle tillhandahålla den nödvändiga funktionaliteten, men som skulle finnas i drivrutinstacken ovanför systemdrivrutinerna. Således skulle alla standardbehandlingsfunktioner utföras USB-drivrutiner, installerat av systemet, och ytterligare funktioner skulle tillhandahållas av din filterdrivrutin, som användarprogrammet skulle interagera med;

dra nytta av fritt distribuerade funktions- och drivrutinsbibliotek

mi för att komma åt USB-enheten.

I de flesta fallen programmatisk åtkomst till en USB-enhet kan krävas om enheten utför någon mycket specifik funktion. Till exempel har USB-baserade "elektroniska oscilloskop" eller datainsamlingssystem utvecklats, som kräver åtkomst till själva enheten för att fungera. I de flesta av dessa fall kan du använda fritt distribuerade bibliotek med funktioner som fungerar i nästan alla populära programmeringsmiljöer. Till exempel, under GNU:s överinseende, har programvara känd som LibUsb utvecklats, som inkluderar nödvändiga drivrutiner och funktionsbibliotek för att köras på Windows och Linux operativsystem. Dessa funktionsbibliotek är mycket populära och låter dig snabbt utveckla program som interagerar med din enhet med hjälp av en uppsättning standardfunktioner. Detta eliminerar behovet av att skriva din egen enhetsdrivrutin, vilket sparar mycket tid.

Dessutom är de flesta användare inte bekanta med tekniker för drivrutinsutveckling,

Detta är ett mycket komplext område av programmering, så tillgången till sådan fritt distribuerad programvara kommer att ge ovärderlig hjälp till ett brett spektrum av användare. Baserat på LibUsb-projektet har wrappers utvecklats för att arbeta med Visual Basic .NET och C# .NET, varav den mest populära är LibUsbDotNet, även utvecklad under fri programvara. Trots den uppenbara komplexiteten i att programmera USB-enheter, förenklar den listade programvaran denna uppgift så mycket att även nybörjare kan göra det. Låt oss titta på praktiska exempel på hur du arbetar med dina USB-enheter, och börja med LibUsb-programpaketet. Förresten, ovanstående programvara kan laddas ner gratis från www.sourceforge.net eller från många dubbletter av webbplatser.

Hur arbetar man med LibUsb USB-funktionsbibliotek? Biblioteket byggdes på ett sådant sätt

så att du kan utföra grundläggande funktioner relaterade till USB-enheten:

identifiering eller, med andra ord, uppräkning. När du utför denna operation upptäcks enheter som är anslutna till USB-bussen, vilket utförs med motsvarande funktioner i libusb-biblioteket;

erhålla enhetsparametrar (enhetsidentifierare, data om tillverkaren och enhetsegenskaper), för vilka biblioteket har ett antal funktioner;

öppna, stänga, läsa och skriva data, skicka kommandon. Till en USB-enhet, precis som andra objekt filsystem, kan du komma åt den genom att skriva eller läsa, vilket görs med hjälp av motsvarande biblioteksfunktioner.

Alla ovanstående funktioner kan implementeras genom att anropa lämpliga libusb-biblioteksfunktioner, men de kommer inte att listas här eftersom det skulle ta för mycket utrymme; vi ska titta på hur du använder några av dessa funktioner

Ris. 6.10

Placering av drivrutinen libusb0.sys i enhetsdrivrutinstacken

med praktiska exempel. Läsare kan hitta en beskrivning av alla funktioner i motsvarande dokumentation. Låt mig påminna dig om att vi överväger att använda libusb-biblioteksfunktioner i Windows-operativsystem.

När du installerar en distribution med libusb i operativsystemet Windows-system Filterdrivrutinen libusb0.sys är installerad på systemet. Denna drivrutin kommer att finnas överst i systemdrivrutinstacken, vilket är lätt att se, till exempel genom att titta på drivrutinsinformationen för valfri USB-enhet (Fig. 6.10).

Dessutom, för att komma åt drivrutinen från användarprogram, är libusb0.dll-biblioteket installerat i systemet, med hjälp av vilket du kan utveckla användarprogram.

Ris. 6.17

Visa programfönstret vid avinstallation

USB-enheter från systemet

Men det räcker inte bara att fysiskt ansluta enheten till datorn, du måste också etablera datautbyte mellan dem. Hur väljer man en port och organiserar en anslutning? För några år sedan var standardlösningen att använda en COM-port. Förresten, olika specialister installerar fortfarande 8, 16 eller till och med 32 COM-portar på industridatorer (det finns en hel kategori av olika PCI-expansionskort för serieportar, kontroller, etc.). Om du behöver ansluta flera externa enheter med ett RS-232-gränssnitt kan du alltså behöva dyra adaptrar och exotiska expansionskort, som enligt den gamla traditionen reser till Ryssland med fartyg i veckor. Förresten, namnet på en vanlig adapter "DB9m/DB25f adapter" kan bara orsaka irritation för en datorbutikschef.

Vad är en HID-enhet

Numera är nästan alla enheter anslutna till en dator via ett USB-gränssnitt. Därför har många nya datorer ingen COM-port alls.

USB-gränssnitt - standard lösning för att para ihop en ny extern enhet med en dator, mer exakt, det är ett HID-gränssnitt baserat på USB 1.1-protokollet.

Även om många tror att HID-gränssnittet (Human Interface Device) enbart är avsett för tangentbordet, musen och joysticken, är det lämpligt för många lösningar relaterade till att para ihop externa enheter med en dator.

Om användaren behöver utföra låghastighetsdatautbyte (upp till 64 kbit/s) och samtidigt vill minska tiden på tråkig utveckling av sina egna drivrutiner, är HID ganska lämpligt för honom. Slutresultatet blir en enkel och helt modern lösning baserad på ett standard USB-mjukvarugränssnitt med garanterat stöd på alla vanliga mjukvaruplattformar.

HID-enhetsegenskaper

Ur synvinkel att organisera mjukvarustöd för en HID-enhet ser allt ganska attraktivt ut: att arbeta under Windows kontroll du kan snabbt skapa begriplig, kompakt kod baserad på färdiga, beprövade algoritmer. Samtidigt kommer utvecklaren att ha mycket tid att implementera sitt eget datautbytesprotokoll på toppnivå, eftersom den nödvändiga abstraktionsnivån redan är organiserad genom HID-protokollet (se tabell). Dessutom är det lätt för en programmerare att felsöka ett skriftligt utbytesprotokoll (naturligtvis om det finns en fungerande HID-enhet) - på grund av den relativa stelheten hos själva protokollet räcker det att helt enkelt utveckla ett datorstödsprogram för enhet. Skulle fortfarande! Skaparen av HID-enheten har redan tagit på sig mycket arbete.

Organisering av datautbyte mellan HID-enheten och datorn

För att beskriva interaktionen mellan en HID-enhet och en dator kommer vi att använda termen "värd". I detta fall förstås det som en kontrollenhet i den allmänna fysiska arkitekturen för interaktion via USB-protokollet. Så alla portar på en dator är värdar. Du kan ansluta olika USB-enheter (flash-enheter, möss, webbkameror, kameror etc.) som inte har en värd. Värden tillhandahåller enhetsupptäckt, anslutning, frånkoppling, konfiguration samt statistikinsamling och energihantering.

HID-enheten kan ställa in sin egen avfrågningsfrekvens för att avgöra om den innehåller några nya data. Detta innebär att även på en så låg nivå kan programmeraren lita på systemet, eftersom pollingfrekvensen och andra kommunikationsparametrar måste förinställas i HID-enhetskontrollprogrammet. Detta skiljer HID-protokollet från den allmänna beskrivningen av USB 1.1 eller USB 2.0, som inte har några strikta krav på organisationen av protokollet. Men för specifika uppgifter som kräver en ökad säkerhetsnivå kan det vara ganska svårt att bli av med cyklisk polling, när nästan samma datablock ständigt överförs.

HID-enhetsprogrammeringsfunktioner

HID-enheter har speciella beskrivningar. När värden bestämmer att enheten tillhör HID-klassen, skickar den kontrollen över den till lämplig drivrutin. Det antas att ytterligare datautbyte sker under hans ledning.

I Windows är HidServ-systemtjänsten ansvarig för åtkomst till HID-enheter. Mer information om funktionerna för förfrågningar till HID-enheter och andra funktioner för att arbeta med HID-drivrutinen beskrivs i arbetet med P. V. Agurov “USB Interface. Praxis för användning och programmering" (S:t Petersburg: BHV-Petersburg, 2005).

Programmera HID-enheter på "toppnivå"

Det hårda livet för "applikations"-programmerare som arbetar i Pascal underlättas av den beprövade HID-modulen. PAS, skalmjukvara för hid. dll (Hid User Library - som anges i filegenskaperna). Kommentarerna till filen visar att den är baserad på modulerna hidsdi.h och hidpi.h från Microsoft. Och själva HID-filen. PAS är en del av JEDI()-paketet.

För att arbeta med en HID-enhet i Delphi for win32-miljön används TJvHidDeviceController-komponenten, som är en bekväm global hanterare för åtkomst till HID-enheter. Och redan på grundval av det kan du få en objektinstans för att arbeta med en specifik enhet.

Grundläggande egenskaper och händelser för TJvHidDeviceController-komponenten

Låt oss titta på TJvHidDeviceController-komponenten mer i detalj. OnArrival-händelsen utlöses när en HID-enhet kommer in (ansluter) till systemet; åtkomst till enheten ges i hanteraren för denna händelse genom en instans av klassen TJvHidDevice. Den enkla OnDeviceChange-händelsen reagerar på förändringar i enhetens tillstånd, den signalerar bara förändringar i systemet. OnDeviceData-händelsen utlöses när data kommer från en av HID-enheterna och skickar följande till hanteraren: HidDev: TJvHidDevice; - enheten från vilken data togs emot;

Händelsen OnDeviceDataError meddelar om ett dataöverföringsfel genom att skicka HidDev-parametrarna till bearbetningsproceduren: TJvHidDevice; - HID-enhet och fel: DWORD; - felkod. OnDeviceUnplug-händelsen meddelar att en enhet tas bort från listan över installerade på systemet. Typerna av händelsehanterare på Plug och Unplug är desamma (i källtexten: TJvHidUnplugEvent = TJvHidPlugEvent). Ett objekt av klassen TJvHidDevice som motsvarar HID-enheten skickas till hanteraren.

För att sekventiellt räkna upp de HID-enheter som är tillgängliga i systemet genom att anropa Enumerate-metoden, är OnEnumerate-händelsen avsedd, dvs. i händelsehanteraren överförs de hittade enheterna sekventiellt som objekt. Denna händelse framtvingas av Enumerate-metoden, som används för att "passera" befintliga HID-enheter genom en hanterare, till exempel när tillståndet för HID-enheter revideras på initiativ av värden (datorn).

OnRemoval-händelsen utlöses när en enhet fysiskt tas bort från systemet och har samma hanterartyp TJvHidUnplugEvent som för OnDeviceUnplug. Funktionen CountByProductName returnerar antalet enheter som matchar produktnamnet som anges i argumentet, och CountByVendorName returnerar tillverkarens namn som anges i argumentet.

Huvudegenskaper och händelser i klassen TJvHidDevice

Klassen TJvHidDevice är en virtuell representation av en enda HID-enhet. Ett nytt objekt av denna klass kan erhållas, som redan nämnts, från OnArrival- eller OnEnumerate-händelsen. Funktionaliteten hos klasserna TJvHidDeviceController och TJvHidDevice är delvis duplicerad, eftersom den första av dem integrerar vanliga verktyg för att arbeta med en uppsättning HID-enheter som finns tillgängliga i systemet och en mekanism för att komma åt en av dem. En enhet kan identifieras unikt med egenskaperna SerialNumber, ProductName och VendorName. För att få information om ankomsten av data med hjälp av ett sådant objekt kan du använda OnData-händelsen. Data skickas genom metoden WriteFile (i strikt mening - genom en funktion). WriteFile är ett omslag runt WriteFile (kernel32) systemfunktionen.

För att kontrollera om enheten har tagits bort bör du tilldela din egen hanterare till OnUnplug-händelsen. Innan du börjar utbyta data med en HID-enhet måste du se till att ett sådant utbyte är möjligt med HasReadWriteAccess. Den här klassen har till och med en separat OnDataError-händelse när ett datautbytesfel inträffar.

Låt oss nu titta på kodfragment från ett "live"-projekt som implementerar en testklientapplikation för att organisera datautbyte med en icke-standardiserad enhet - HID-baserade plastchipkort. I kampen för realism tog författaren på sig att inte kasta ut "extra" tekniska kodkopplingar från listorna.

ScanDevices-metoden (lista 1) är avsedd att initiera processen att söka i systemet efter den nödvändiga HID-enheten. Det mesta av koden, med undantag för anropet till Enumerate-metoden, är valfritt och ger flexibilitet till applikationen, till exempel så att möjligheten att arbeta på ett icke-HID-gränssnitt skulle kunna läggas till i samma testprogram. AddError-metoden visar felsökningsinformation i fönstret medan programmet körs.

Lista 2 visar en OnEnumerate-händelsehanterare för att hitta den externa enheten som krävs. För enkelhetens skull kommer vi att anta att programmet bara kan fungera med en enhet av den typ det behöver.

Innan vi överväger det fortsatta genomförandet av projektet bör vi prata lite om det antagna datautbytesformatet på toppnivå, det vill säga om strukturen utformad för att vara en mellanhand mellan metoderna för att ta emot och överföra data och det specifika applikationsproblemet som ska lösas. Faktum är att här ges utvecklaren möjligheten att förverkliga sina kreativa förmågor. Eller snarare, utvecklare, eftersom processen att skapa ett nytt protokoll ofta är tvåvägs, och den första fiolen spelas av den som har svårare att implementera utbytesalgoritmen. I allmänhet, oavsett vad utbytesprotokollet är, är det alltid trevligt att göra varje mjukvaruenhet så visuell och självförsörjande som möjligt, även på bekostnad av några allmänt accepterade traditioner. För den bästa lösningen är den som kommer att implementeras på kort tid med minimal koppling till mjukvarumiljön och med stora möjligheter till vidareutveckling. Baserat på dessa principer skapades ett utbytesprotokoll på toppnivå, där huvudkonceptet är "kommando". Lista 3 visar hur mycket författaren älskar strängdata, vilket har sparat honom mer än en gång vid felsökning av programmoduler. Vad underbart det är att vi ens har en String-typ! Alla protokollkommandon är indelade i kategorier (klasser), inom vilka det finns en kommandokod som unikt karakteriserar dess syfte. Parametern edParam används för att skicka data till enheten, och parametern edAnswerData innehåller data som tas emot från enheten. Strängtypen för de beskrivna postmedlemmarna låter dig fritt och tydligt manipulera data i HEX-strängformat. Och det bästa är att formatet för den beskrivna posten ideologiskt sett står någonstans i mitten mellan dess direkta syfte och de olika formerna av dess presentation (INI, HEX, XML, etc.)

Utförande av kommandot, d.v.s. sändning av data till enheten, implementeras genom att skicka datapaket 8 byte långa (lista 4). Denna längd är inte den enda lösningen, detta val dikteras av kraven i protokollet på den övre nivån och kan vara olika i varje specifikt fall. Detta är, som man säger, en smaksak. Den märkliga IsUSBMode-flaggan i ExecuteCommand-metoden (listning 5 i PC World) är kvar som en påminnelse om att vi kan behöva använda en COM-port eller något annat gränssnitt istället för att arbeta med USB. I början av den skickade datagruppen sänds en synkroniseringsserie av ett slumpmässigt valt format (till exempel 3E3E3E2B) till enheten, vilket informerar enheten om att den har helt laglig data vid ingången. Låt mig påminna dig om att i det här fallet pratar vi inte så mycket om HID, utan om ett specifikt toppnivåprotokoll, ideologiskt separerat från hårdvaran och avsett att lösa speciella applikationsproblem.

GetDataExecutor-hanteraren för data som tas emot från enheten (ett paket på 8 byte) använder en speciellt skapad OnNewInputData-händelse för att överföra de initialt bearbetade data för vidare bearbetning, vilket indikerar deras gamla och nya värden (lista 6 på "World of PC Disk" ”). På detta sätt frikopplas rådataankomsthändelser och indikationer för vidare bearbetning, vilket gör att någon specifik algoritm kan läggas till tidigt för att varna för felaktig, dubblerad eller onödig inmatningsinformation.

Exemplen på att arbeta med en HID-enhet som presenteras här illustrerar den allmänna idén med artikeln - den relativa lättheten att programmera icke-standardiserade HID-enheter med Delphi.

Bild 1

USB-gränssnittet blir allt mer populärt som gränssnitt för att ansluta kringutrustning till en PC, och moderna datorer har ofta inte det vanliga RS-232-gränssnittet. Populariteten för USB beror på många skäl, här är de viktigaste:

  • hög växlingshastighet, hög brusimmunitet
  • dataflödeskontroll, integritetsövervakning och felkorrigering
  • möjlighet att förgrena sig genom nav och ansluta ett stort antal enheter.
  • Möjlighet att ta emot ström från bussen
  • buss mångsidighet - möjlighet att ansluta olika enheter (tangentbord, skrivare, modem)
  • automatisk systemidentifiering och konfiguration, Plug and Play

Det finns dock (ofta ogrundade) faktorer som hindrar den utbredda användningen av USB av utvecklare av mikrokontrollerenheter:

  • behovet av att programmera drivrutiner för Windows
  • relativt låg förekomst av mikrokontroller med inbyggt USB-gränssnitt
  • Lektion 2: Skapa en USB 2.0-kompatibel HID-joystick-enhet.

Den här artikelserien är avsedd att visa att det är ganska lätt att övervinna dessa svårigheter och vem som helst kan "uppgradera" sin enhet från den vanliga RS-232 till USB eller skapa en ny enhet med ett USB-gränssnitt.

I exemplen kommer en mikrokontroller tillverkad av Microchip att betraktas som en mikrokontroller PIC18F4550 med USB 2.0-gränssnitt (stöder låg hastighet och full hastighet).

Lektion 1. USB utan Windows-programmering, virtuell COM-port

En av uppgifterna som uppstår vid utveckling av USB-enheter är övergången från RS-232-gränssnittet till USB, och om en "gammal" enhet modifieras eller enheten måste vara kompatibel med befintliga protokoll och PC-mjukvara, är det önskvärt att bli av med programvara för modifiering av programvara på datorn. En lösning på detta problem är att använda USB-gränssnittet som en virtuell COM-port. Användningen av denna metod eliminerar behovet av att modifiera datorprogram, eftersom USB-anslutningen ses av persondatorn som en extra COM-port. En annan viktig fördel är att vanliga Windows-drivrutiner används och det finns inget behov av att skapa någon anpassad drivrutin.

USB-specifikationen beskriver Communication Device Class (CDC), som definierar en mängd olika anslutningslägen för telekommunikation (modem, terminaler, telefoner) och nätverksenheter (Ethernet-adaptrar och -hubbar, ADSL-modem), inklusive serieportsemulering.

Låt oss som exempel ta en enhet som överför spänningsdata från en potentiometer och temperatur från en TC77 digital sensor via RS-232, och som även tar emot kommandon för att slå på/stänga av två lysdioder (för enkelhets skull implementerar vi detta exempel på PICDEM™ FS USB DEMONSTRATIONSKORT, men du kan montera en enklare krets - se nedan).

PICDEM FS-USB-utvecklingskortet är avsett för utveckling och demonstration av enheter på PIC18F4550 mikrokontroller med en USB2.0-buss. Kortet innehåller en PIC18F4550-kontroller i ett TQFP44-paket, som har följande funktioner:

  • Maximal driftfrekvens - 48 MHz (12 MIPS);
  • 32 KB Flash-programminne (Enhanced Flash-teknik);
  • 2 KB dataminne (varav 1 KB dual-port RAM);
  • 256 byte EEPROM-dataminne;
  • FS USB2.0-gränssnitt som stöder 12 Mbit/s hastighet, med inbyggd transceiver och spänningsregulator.

Följande är installerade på tavlan:

  • Kvarts 20 MHz;
  • RS-232-gränssnitt för att demonstrera möjligheten att byta från USART till USB;
  • Kontakt för in-circuit programmering och felsökning
  • Matningsspänningsstabilisator med möjlighet att växla till ström från USB-bussen;
  • PICtail™ expansionskontakt;
  • Temperaturgivare TC77, ansluten via I2C;
  • Variabelt motstånd anslutet till ADC-ingången;
  • Lysdioder, knappar.

Den här enheten har ett PC-program för att styra enheten och visa spännings- och temperaturvärden. Så vi kan ansluta enheten till RS-232, välja COM-porten som är tillgänglig i systemet och ställa in växelkursen med vår enhet, antalet databitar, antalet stoppbitar, såväl som parametrarna för paritetsbitarna och flödeskontroll i enlighet med mikrokontrollerprogrammet (för Detta betyder att vi behöver känna till initialiseringsparametrarna för vår kontroller)


Ris. 2

Låt oss börja ansluta vår enhet till USB.

Microchip Technology Inc. Erbjuder ett färdigt applikationsexempel AN956, som implementerar USB CDC-stöd för mikrokontroller PIC18F2550, PIC18F2455, PIC18F4455, PIC18F4550. Programmet bygger på en modulär princip, vilket möjliggör enkel modernisering och integration i färdiga projekt.

Efter initial initiering av styrenheten kan programmet kommunicera med PC:n via USB-gränssnittet med hjälp av flera färdiga funktioner:

Vi modifierar vårt program för att överföra och ta emot data via USB.

Fragment av databerednings- och överföringsprogrammet:

Datamottagning:

if(getsUSBUSART(input_buffer,1)) ( switch (input_buffer) ( case "1" : mLED_3_On(); break; case "2" : mLED_3_Off(); break; case "3" : mLED_4_On(); break; case " 4" : mLED_4_Off(); break; default: break; ) )

Efter att ha anslutit enheten till USB känner systemet igen den nya enheten


Ris. 3

Och installerar ny utrustning


Ris. 4

Vi väljer installation från den angivna platsen och anger sökvägen till platsen för filen mcpusb.inf från källkodspaketet för AN956-programmet. Efter detta installeras den nya enheten i systemet.


Ris. 5

Så den nya enheten är redo att användas. En ny virtuell COM-port har dykt upp i systemet.


Ris. 6

Nu i vårt program kan vi välja den virtuella COM-porten som verkar kommunicera med enheten...


Ris. 7

... och se att enheten faktiskt började fungera via COM-porten som dök upp i systemet via en USB-anslutning.

Det bör noteras att USB tillhandahåller datakontroll och korrigering, så begrepp som flödeshastighet, paritet och flödeskontrollbitar blir abstrakta begrepp, och i vårt fall kan de väljas av vem som helst, den enda informationsparametern är numret på den virtuella COM hamn.

PICDEM CDC-fönster


Ris. 8

När man använder PIC18Fxx5x-mikrokontroller med en inbyggd USB 2.0-modul kan en virtuell COM-port ge dataöverföringshastigheter på upp till 80 Kbyte per sekund (640 Kbps), vilket avsevärt överstiger den möjliga överföringshastigheten via RS-232, samtidigt som vi se, det finns inget behov av att ändra den datorprogramvara som krävs!

Exempel på program, dokumentation och diagram som används i lektion 1.

  1. PICDEM CDC-program + källkoder för Delphi-nedladdning
  2. Ladda ner Delphi-komponent för att arbeta med COM-port
  3. AN956+ ursprungliga källkoder
  4. Fil user_uart.c (alla ändringar av det ursprungliga programmet från AN956 gjordes endast i den här filen. För att köra exemplet i lektion 1 måste du kopiera den här filen till katalogen C:\MCHPFSUSB\fw\Cdc\user\, ersätt user.c-fil i projektet med user_uart .c, kompilera projektet och flasha mikrokontrollern)
  5. Förenklat diagram över en USB-enhet


Ris. 9

Obs: Den ursprungliga designen av PICDEM FS USB-kortet använder automatisk detektering av kortets strömkälla (extern källa eller USB). När du använder ett förenklat schema måste du därför kommentera raden #define USE_USB_BUSSENSE_IO i filen usbcfg.h

Lektion 2: Skapa en USB 2.0-kompatibel HID Joystick-enhet

De vanligaste USB-enheterna är Human Interface Devices (HID). Typiska representanter för denna klass är USB-tangentbord, möss, joysticks, paneler för bildskärmsinställning, streckkodsläsare, kortläsare, etc. Fördelarna med HID-enheter är:

  • enkel implementering;
  • kompakt kod;
  • Windows-stöd (inga ytterligare drivrutiner behövs).

På Microchips webbplats finns ett exempel på implementeringen av en HID-musmanipulator. Låt oss överväga implementeringen av den enklaste spelmanipulatorn baserat på detta exempel. För detta projekt kommer vi att använda PICDEM FS-USB demokortet (DM163025). PICDEM FS-USB-utvecklingskortet har ett variabelt motstånd och 2 knappar, så joysticken som utvecklas kommer att ha ett minimum av kontrollelement (2 knappar och till exempel en gasregulator).

Först och främst måste vi skriva om enhetsbeskrivningen för joysticken som skapas. För att förenkla uppgiften kan du använda programmet HID Descriptor Tool, som kan laddas ner från webbplatsen www.usb.org

Programmet kommer med exempelkonfigurationer av vissa HID-enheter, som du kan justera för att passa din uppgift eller skapa din egen HID-enhet.


Ris. 10

Så i vårt fall kommer flera typer av data att användas - det här är en simulering av kontrollen - Simuleringskontroller, och specifikt är detta gashandtaget (pedal) och kontrollknapparna (Knapp). För att operativsystemet ska "veta" hur man hanterar dessa datatyper är det nödvändigt att beskriva de maximala och lägsta värdena och storleken på data. I vårt fall är "gas" ett 8-bitars värde (report_size = 8, report_count = 1), och knapparnas tillstånd definieras som ett fält med en-bitars värden. Exemplet använder endast 2 knappar, men det är nödvändigt att justera fältet till ett bytevärde (report_size = 1, report_count = 8). Totalt, när du begär data från en dator, måste mikrokontrollern överföra 2 byte - gasnivån och knapparnas tillstånd i enlighet med den genererade enhetsbeskrivningen (för en detaljerad beskrivning av möjliga deskriptorer, se specifikationen för HID-enheter www.usb.org). Den skapade enhetsbeskrivningsbeskrivningen kan sparas i olika format, inklusive som en rubrikfil.h

Dessutom måste du justera storleken på den mottagna enhetsbeskrivningen i HID Class-Specific Descriptor-beskrivningen och ändra storleken på data som överförs genom endpointen i endpoint-deskriptorn (i vårt fall sänder vi 2 byte, så storleken är HID_INT_IN_EP_SIZE=2).

De angivna ändringarna räcker för att Windows ska känna igen den anslutna enheten som en joystick. Nu kan vi justera strängdata så att enheten har det namn vi vill ha (till exempel "PIC18F4550 Joystick"). För att kunna tilldela enheten ett namn på ryska måste du ange en strängbeskrivning i UNICODE-kodning. Detta avslutar beskrivningen av joysticken och du måste förbereda data för överföring till PC:n.

ReadPOT(); // startpotentiometer spänningsmätning buffert = ADRESH; // bearbetningsknappen anger if(sw2==0) buffert |= 0x01; annars buffert &= ~0x01; if(sw3==0) buffert |= 0x02; annars buffert &= ~0x02; // dataöverföring Emulate_Joystick();

Efter att ha kompilerat projektet och programmerat mikrokontrollern kan du ansluta enheten till USB-porten. Brädan definieras som en HID-spelenhet, installerad i systemet och redo att användas.


Ris. elva

Genom kontrollpanelen i Windows kan vi öppna de tillgängliga spelenheterna, välja vår joystick, kalibrera den och testa dess funktionalitet.


Ris. 12

När du ändrar enhetskonfigurationen - lägger till kontroller eller knappar, är det nödvändigt att inte bara ändra beskrivningen av enhetsbeskrivningen, utan också att överföra data strikt i enlighet med den skapade deskriptorn. Så genom att ändra det maximala antalet knappar i beskrivningen av USAGE_MAXIMUM (KNAPP 2) enhetsbeskrivning från 2 till 8, får vi en joystick med 8 knappar.


Ris. 13

När deskriptorn blir mer komplex kan vi få en mer komplett implementering av joysticken, men vi måste komma ihåg att ändra följande parametrar: descriptor size, endpoint size, och det är nödvändigt att skicka så mycket informationsdata som deklareras i deskriptorn.


Ris. 14

Exempel på program, dokumentation och diagram som används i lektion 2.

  1. Originalkällkoder för implementeringen av HID-musen.
  2. Källkoder för implementeringen av HID-joysticken.

Lektion 3. Sammansatt USB-enhet

Varje USB-enhet kan ha flera konfigurationer och varje konfiguration har flera gränssnitt. Denna USB-egenskap gör att den skapade enheten kan kännas igen av datorn som flera USB-enheter med olika gränssnitt. En mus kan till exempel ha en inbyggd kortläsare och interagera med datorn som två oberoende enheter.

Enhetsbeskrivningsstruktur:


Ris. 15

Baserat på standardexemplet med en mus och en skapad joystick, kommer vi att skapa en sammansatt USB-enhet som kommer att upptäckas av datorn som två oberoende HID-enheter.

1. Skapa en deskriptor.

Låt oss ändra strukturen för deskriptorn (fil usbdsc.h)

Enheten kommer att ha 2 gränssnitt, vart och ett med en slutpunkt.

#define CFG01 rom struct \ ( USB_CFG_DSC cd01; \ USB_INTF_DSC i00a00; \ USB_HID_DSC hid_i00a00; \ USB_EP_DSC ep01i_i00a00; \ USB_INTF_DSC i01a00; 2i_i01a00; \ ) cfg01
  1. I enlighet med den ändrade strukturen måste du ändra deskriptorn i filen usbdsc.c.
  2. I filen usbcfg.h definierar du gränssnittsidentifierare, slutpunkter som används och storlek på rapportbeskrivningar.
  3. I hid.c-filen måste du initiera ytterligare slutpunkter (i HIDInitEP-funktionen) och ändra funktionen för att hantera HID-förfrågningar (USBCheckHIDRequest-funktionen).
  4. Varje enhet, mus och joystick, måste var och en överföra data till sin egen slutpunkt. Därför måste vi lägga till funktioner för att överföra data till specifika slutpunkter och kontrollera att den önskade slutpunkten är ledig (lägg till funktioner som liknar mHIDTxIsBusy och HIDTxReport i hid.c-filen).

Då kommer dataöverföringen för musen att se ut

Efter att ha kompilerat projektet, flashat styrenhetens firmware och anslutit enheten till USB, kommer datorn att upptäcka en ny sammansatt enhet och lägga till en mus och joystick.


Ris. 16


Ris. 17

Källkoder för en sammansatt HID-enhet.

Kommentar. Glöm inte att ändra PID när du skapar en ny enhet eller tar bort en tidigare enhet med samma PID från systemet.

Lektion 4. Experimentera med PICkit2-programmeraren

Microchip Technology Inc. släpper en billig utvecklarprogrammerare PICkit2, som främst används för programmering av Flash-kontroller. En utmärkande egenskap hos denna programmerare är tillgången till komplett dokumentation och källkoder för den fasta programvaran för mikrokontrollern och skalprogrammet för datorn. PICkit2 tar emot ström från USB, genererar justerbar programmering och strömspänningar och har även 3 ingångs-utgångslinjer för anslutning till en programmerbar enhet. För att göra det möjligt att uppdatera programmerarens firmware har PICkit2 ett bootloader-program.


Ris. 18

CDC-enhet baserad på PICkit2

Genom att använda alla dessa funktioner, baserade på PICkit2-programmeraren, är det möjligt att skapa och felsöka din egen USB-enhet med möjligheten att återgå till programmeringsfunktionerna när som helst. Med hjälp av starthanteraren som flashas in i programmeraren kan du flasha andra program till PICkit2, till exempel ett virtuellt COM-portstödsprogram. För att göra detta, ta exemplet med CDC, byt namn på projektet och gör följande

  1. i main.c-filen ändrar vi adressen till firmwareplatsen (PICkit2 bootloader överför kontrollen till användarprogrammet till adressen 0x002000.
    #pragmakod _RESET_INTERRUPT_VECTOR = 0x002000
  2. i filen io_cfg.h tar vi bort allt om port D (du kan ställa in lysdioden att blinka på PORTC0).

    Eftersom PICKIT2 alltid drivs från USB ställer vi in

    #define usb_bus_sense 1 // enheten är alltid ansluten #define self_power 0 // enheten får ström från USB

  3. i filen usbcfg.h lägger vi kommentarer på 2 rader
    //#define USE_SELF_POWER_SENSE_IO //#define USE_USB_BUS_SENSE_IO
  4. I filen user.c matar vi ut data vi behöver till USB
  5. anslut länkfilen pickit2.lkr

Efter detta kan du kompilera projektet och ladda upp ny firmware genom PICkit2-skalet.

Efter omprogrammering av PICkit2 upptäcker datorn utseendet på en ny COM-port, och genom hyperterminalen kan vi se att PICkit2 skickar data genom den virtuella COM-porten.

Källkoden för detta exempel är tillgänglig på länk.

Baserat på detta exempel och med hjälp av de externa stiften på PICkit2-programmeraren kan du ta emot data från externa enheter och överföra den till en dator via USB. Med PICkit2 kan du alltså mata ut data till COG LCD-indikatorer, läsare av I2C, SPI och 1-trådsenheter, såsom temperatursensorer och andra enheter.

Radio HID-tangentbord baserat på PICkit2


Ris. 19

Låt oss titta på ett annat exempel på den "olämpliga" användningen av PICkit2-programmeraren - en tangentbordsemulator med ett radiogränssnitt. En sådan enhet kan användas till exempel för presentationer - för att bläddra genom bilder bort från datorn.

För att implementera en sådan enhet behöver vi:

  • PICkit2
  • demokort från PICkit2 (DV164120)
  • radiomottagare (rfRXD0420) och radiosändare (rfPIC12F675) från rfPICkit.

Vi ansluter en radiomottagare till demokortet. Mikrokontrollern på kortet kommer att ta emot data från mottagaren, bearbeta den och, när den detekterar nedtryckning av en av de två knapparna på radionyckelbrickan, ställa in log.1-nivån på ett av de 2 stiften som är anslutna till PICkit2.

PICkit2 kommer att utföra följande funktioner:

  • när den är ansluten till en dator via USB, upptäcks den som ett HID-tangentbord
  • generera +5V matningsspänning för demokortet med mottagaren
  • polla 2 externa utgångar från mottagarens styrenhet och, om det finns en logg. 1 skicka koder för att trycka på PageUp- eller PageDown-knapparna till datorn.

Två virtuella COM-portar (FTDI2232-chipemulering) baserade på PICKit2

Det här exemplet är endast för att lära dig hur USB fungerar. Läs igenom FTDI-körkortskraven före användning!

Exemplet visar hur man gör 2 virtuella COM-portar baserade på en mikrokontroller med USB-port.Först måste du installera drivrutiner för FTDI2232-chippet. För att sedan ladda in i PICkit2 måste du välja firmwareuppdateringsobjektet i PICkit2-skalet och peka på filen TestVCP2.hex från arkiv. Efter omprogrammering av PICkit2 kommer du att ha 2 oberoende seriella COM-portar i ditt system.

Exempel taget från sajten http://forum.microchip.com/tm.aspx?m=261649

För att återställa PICkit2 som en programmerare måste du koppla bort PICkit2 från USB och, medan du trycker på knappen, återanslut USB-kabeln och sedan välja att ladda programmerarens standardfirmware.

Alla exemplen ovan är baserade på MCHPFSUSB Framework v1.3. Med tillkomsten av PIC24- och PIC32-kontroller med USB OTG har Microchip släppt en ny version av stacken - USB-stack v. 2.x.

I den nya versionen av USB-stack v. 2.3, förutom USB-enhetsstackarna, som implementerar funktionaliteten hos en USB-klient, USB Embedded host, som implementerar funktionaliteten hos värden, har en USB-stack med dubbla roller också tagits fram, som implementerar funktionerna för både värden och Klienten; och USB OTG, som stöder Host Negotiation Protocol (HNP), Session Request Protocol (SRP) och är helt kompatibel med USB OTG-specifikationen. Implementerat i applikationsexempel:

  • Inbäddad värd
    • Skrivarklassvärd - stöd för ESC/POS, PostScript® och PCL5-skrivare
    • CDC Class-värd - stöd för ACM-enheter (abstrakt kontrollmodell).
    • HID-tangentbord
  • Enhet
    • HID bootloader - lagt till stöd för PIC32MX460F512L och PIC18F14K50 familjer
    • HID tangentbord, mus
    • MSD intern flash-demo - använder intern flash för att lagra filer
    • MSD + HID-kompositexempel - exempel på en sammansatt MSD- och HID-enhet
    • CDC - COM-portemulering
    • PIC32MX460F512L familjestöd för alla PC-demoprojekt
    • HID, MCHPUSB och WinUSB-exempel stöder nu Microsoft Plug-and-Play (PnP)-funktion för automatisk avkänning.
  • Dokumentation
    • en fullständig beskrivning av alla API:er finns i mappen "\Microchip\Help".

Microchip tillhandahåller gratis drivrutiner för de mest populära USB-klasserna:

  1. Användargränssnitt (HID). Detta utbytesläge används i nästan alla tangentbord, möss och andra in-/utdataenheter
  2. Kommunikationsenhet (CDC). Detta läge är det enklaste att byta från RS-232 seriellt gränssnitt till USB. På datorer med WinXP/2K skapas en virtuell COM-port och emuleras när en mikrokontroller ansluts. Program som arbetar med COM1..4-portar kommer att fungera oförändrat med en virtuell port, men med en högre hastighet (cirka 1 Mbit/s)
  3. Masslagringsenheter (MSD). Det här är enheter som fungerar som informationslagringsenheter - flashenheter, SD/MMC-kort, diskar, etc.
  4. Skrivarklassenheter. Detta läge är utformat för användning av USB-skrivare, vilket gör att slutenheten på en PIC-mikrokontroller med en USB-modul kan mata ut nödvändig information direkt till en USB-skrivare
  5. Microchip resident bootloader. Det enklaste läget, som endast används för uppdatering av mikrokontrollerprogramvara via USB. På PC-sidan installeras ett litet program, liknande en drivrutin
  6. Egen förare (Anpassad). Den mest kompletta användningen av USB2.0-resurser för avancerade användare: möjligheten att välja bussdriftlägen (isokron, avbrottsbaserad, volymetrisk, kontroll), hög överföringshastighet. Kräver djupgående kunskaper om bussdrift och Windows mjukvaruutveckling

Bootloader med USB-minne

Firmwareuppdatering från en vanlig flashenhet.

För att uppdatera firmware för en mikrokontroller med en USB-OTG-modul (PIC24 eller PIC32) är det inte nödvändigt att använda speciell programvara. Närvaron av värdläge gör att du kan ansluta konventionella USB-datalagringsenheter (Flash Drive) till mikrokontrollern. Ett exempel finns publicerat på Microchips webbplats ( betaversion), som låter dig uppdatera mikrokontrollerns programvara från en ansluten USB-enhet.

För att köra exemplet måste du ladda bootloader-firmwaren till ett PIC32 USB-kort eller Explorer 16 (med PIC32 USB PIM-processormodulen installerad och USB PICtail Plus-dotterkortet installerat). Om du sätter på strömmen till kortet medan knappen är intryckt, går styrenheten in i firmwareuppdateringsläge. Om du nu ansluter en Flash-enhet med en inspelad firmwareuppdateringsfil, kommer mikrokontrollern att läsa denna fil och skriva om den till sitt programminne.

USB-utvecklingskort och utvecklingsverktyg

Programmerare-debugger PICkit2 (beställningsnummer PG164120)

Närvaron av en bootloader låter dig ladda upp din egen programvara för att bemästra USB-färdigheter


Ris. 20

PICDEM FS-USB utvecklingskort (beställningsnummer DM163025)

Designad för utveckling och demonstration av enheter baserade på mikrokontrollern PIC18F4550 med USB2.0-buss. Kortet innehåller en PIC18F4550-kontroller i ett TQFP44-paket.


Ris. 21

USB-utvecklingssats med lågt antal stift (beställningsnummer DM164127)

USB-utvecklingssatsen med lågt antal pinnar ger ett enkelt sätt att utvärdera mikrokontrollernas kapacitet hos Microchip PIC18F14K50 och PIC18F13K50 20-stifts USB-mikrokontroller. Satsen innehåller allt du behöver för att komma igång med USB-kontroller (programvara, exempel källfiler, dokumentation).


Ris. 22

PIC18F87J50 Full Speed ​​​​USB PIC18F87J50 FS USB-demokort (beställningsnummer MA180021)

PIC18F87J50 FS USB-demokort används för att felsöka Full Speed ​​​​USB 2.0-mikrokontroller i PIC18F87J50-familjen. Förutom autonom drift kan kortet även användas som en processormodul för PIC18 Explorer Board.


Ris. 23

PIC24 Starter Kit (beställningsnummer DM240011)

PIC24F Starter Kit innehåller allt du behöver för att komma igång med den högpresterande PIC24F-familjen av kontroller. Detta prisvärda kit innehåller en integrerad felsökare och programmerare i kretsen, en PIC24F-kontroller med ett USB-gränssnitt (värd- och enhetsfunktioner kan implementeras på kortet), en trefärgad LED, en kapacitiv pekskärm och en grafisk OLED-display. Demoprogrammet via den grafiska menyn låter dig spela in data till ett externt USB-minne, konfigurera pekpanelen och köra grafiska uppgifter.


Ris. 24

PIC32 USB-kort (beställningsnummer DM320003)

Låter dig behärska USB-OTG-modulen i PIC32-kontroller


Ris. 25

Utvecklingstavla "Explorer 16 Development Board" (beställningsnummer DM240001)

Detta är ett billigt felsökningsverktyg för att komma igång med den högpresterande PIC24-familjen av 16-bitars mikrokontroller och dsPIC33F digitala signalbehandlingskontroller.


Ris. 26

Dotterkort "USB PICtali Plus" (beställningsnummer AC164131)

Tillsammans med USB-processor Plug-In-moduler låter den dig utveckla och felsöka USB-enheter Host, Device, USB-OTG.


Ris. 27

Ilja Afanasyev,
Företag

Låt oss börja med minimum:
inkluderar 18f2455 -- bibliotek för den använda MK
--
aktivera_digital_io() -- växlar alla ingångar till digitalt läge
--
alias Knapp är pin_B7 -- eftersom vi har en knapp ansluten, låt oss förklara det
pin_B7_direction = ingång -- vår knapp fungerar för inträde
--
-- en rad - och vi har allt du behöver för att arbeta med USB CDC
include usb_serial -- bibliotek för att arbeta med usb
--
usb_serial_init() -- --initiera USB CDC
forever loop-- huvudslinga, exekveras kontinuerligt
usb_serial_flush() -- Usb-uppdatering. Denna procedur utför alla nödvändiga
-- åtgärder för att upprätthålla anslutningen till PC
ändslinga

Genom att kompilera den här koden, skriva den resulterande HEX-filen till MK med hjälp av en bootloader och starta enheten, kan du observera hur en ny enhet definieras i systemet: Virtual com-port.

Nu när enheten redan fungerar, låt oss lära den att kommunicera.

För att läsa den mottagna byten finns en funktion usb_serial_read( byte ) :boolesk. Om det finns en mottagen byte, lagrar den den i den angivna variabeln och returnerar Sann, annars återkommer falsk.

Det finns en procedur för att skicka en byte usb_serial_data. Den är förklädd som en variabel, så för att skicka en byte behöver du bara tilldela den värdet på den byte som skickas.

Låt oss deklarera en bytestor variabel före huvudslingan, i huvudslingan kommer vi att kontrollera om det finns mottagna bytes, och om de finns, skicka tillbaka dem.

inkluderar 18f2455
--
aktivera_digital_io()
--
alias Knapp är pin_B7
pin_B7_direction = ingång
--
--
inkludera usb_serial
--
usb_serial_init()
var byte kap -- deklarera en variabel
forever loop-- huvudslinga
usb_serial_flush()
om(usb_serial_read(ch)) sedan-- om en byte tas emot, kommer den att skrivas till kap
usb_serial_data = kap -- skicka tillbaka den mottagna byten
sluta om
ändslinga

Vi kompilerar, håller ned knappen, byter strömförsörjning, startar bootloader, ändrar firmware, startar.
Enheten har upptäckts i systemet igen, nu behöver vi programvara för att testa enhetens funktion.

Även om vi inte har vår egen, använder vi en färdig terminal: jag använde RealTerm-programmet.
Öppna porten med önskat nummer och skicka data.


Och vi får tillbaka det vi skickade. Det betyder att allt fungerar som det ska.

programvara

Så vår mikrokontroller kan ta emot bytes och omedelbart skicka tillbaka dem. Låt oss nu skriva vår egen programvara för att kommunicera med den (jag kommer att använda Delphi).

Vi skapar ett nytt projekt, ordnar de nödvändiga komponenterna enligt formuläret:
SpinEdit1 - för att ange portnumret
Knapp1 - för att upprätta en anslutning
Knapp 2 - för att koppla från
SpinEdit2 - för att ange byte i decimalform
Knapp3 - för att skicka en byte
Memo1 - för att visa mottagen information.

Som nämnts ovan måste du arbeta med com-porten på samma sätt som med en vanlig textfil: Använder funktionerna CreateFile, WriteFile och ReadFile.

Utan att gå in på detaljer, låt oss ta ett färdigt bibliotek för att arbeta med en com-port: ComPort.

Vi bifogar den nödvändiga uppgiften till varje knapp och får den slutliga koden:

enhet Enhet1;

gränssnitt

Används
Windows, meddelanden, SysUtils, varianter, klasser, grafik, kontroller, formulär,
Dialoger, StdCtrl, Spin, ComPort;

Typ
TForm1 = klass(TForm)
SpinEdit1:TSpinEdit;
Knapp1: TBnapp;
Knapp2: TBnapp;
SpinEdit2:TSpinEdit;
Knapp3: TBnapp;
Memo1: TMemo;
procedure OnRead(Avsändare: TObject; ReadBytes: array av Byte );
procedure Button1Click(Avsändare: TObject);
procedure Button2Click(Avsändare: TObject);
procedure FormDestroy(Avsändare: TObject);
procedure Button3Click(Avsändare: TObject);
privat
(Privata deklarationer)
Port: TComPort;
offentlig
(Offentliga deklarationer)
slutet;

var
Form1: TForm1;
num:heltal;
genomförande

Procedur TForm1.Button1Click(Avsändare: TObject);
Börja
Port:= TComPort.Create(SpinEdit1.Value, br115200); //skapa en anslutning
Port.OnRead:= OnRead; //skapa en ström för att läsa mottagen data
Button2.Enabled:= true ; //aktivera knappen för att stänga anslutningen
slutet;

Procedur TForm1.Button2Click(Avsändare: TObject);
Börja
Port.Free; //stäng anslutningen
Button2.Enabled:= false ; //avaktivera knappen
slutet;

Procedur TForm1.Button3Click(Avsändare: TObject);
Börja
om Button2.Enabled då Port.Write();
slutet;

Procedur TForm1.FormDestroy(Avsändare: TObject);
Börja
om Button2.Enabled då
Port.Free;
slutet;

Procedur TForm1.OnRead(Sändare: TObject; ReadBytes: array av Byte );
var
i:heltal;
Börja
för i:= Low(ReadBytes) till High(ReadBytes) gör //passera genom arrayen av mottagna byte
Börja
Memo1.Text:= Memo1.Text + "." +InttoHex(ReadBytes[i],2); //lägg till dess HEX-värde i fönstret
inc(antal); //räkna antalet mottagna byte
slutet;
om num > 10 så börja
Memo1.Lines.Add("" ); // linda linjen
antal:= 0;
slutet;
slutet;

Vi startar, upprättar en anslutning, skickar bytes:

Så vår enklaste terminal är redo att fungera med den enklaste USB-enheten.

Som du kan se sker läsning och skrivning i dynamiska byte-arrayer.

Genom att behandla den mottagna informationen kan du skapa det nödvändiga utbytesprotokollet som är lämpligt för den aktuella uppgiften.

inkluderar 18f2455
--
aktivera_digital_io()
--
alias Knapp är pin_B7
pin_B7_direction = ingång
--
--
inkludera usb_serial
--
usb_serial_init()
var byte kap
var byte i -- deklarera den andra variabeln
forever loop-- huvudslinga
usb_serial_flush()
om(usb_serial_read(ch)) sedan-- Om byten tas emot, utför de nödvändiga åtgärderna
fall ch av -- gå igenom bytenumret
0 : usb_serial_data = 0xff
1 : usb_serial_data = Knapp -- Skicka knappstatus
ANNAT blockera-- om något annat tas emot
för 16 använder sig av i slinga-- skicka 10 byte med data
usb_serial_data = ch +i -- från ch till ch+15
ändslinga
ändblock
slutfall
sluta om
ändslinga

Ytterligare egenskaper

Om vi ​​slutar här får vi en vanlig artikel med en detaljerad beskrivning av ett exempel på användning av biblioteket, som det finns gott om på Internet. Därför kommer jag att lägga till lite mer djupgående information.

Gör det lättare att skicka data

Att skicka information en byte i taget är inte alltid bekvämt. Biblioteket kan komma till användning väldigt ofta skriva ut. Den innehåller procedurer för att skicka data av alla möjliga längder i alla möjliga format: byte, hex, dec, bin, boolean, vilket kan förenkla utmatningen av data i programmet.
> inkludera tryck
...
var dword data
print_dword_hex(usb_serial_data, data)

Namnen på alla kommandon finns i biblioteksfilen.

Väntar på att ansluta till PC

Om det är nödvändigt att först upprätta en anslutning till datorn innan du startar huvudcykeln för mikrokontrollern, kan du lägga till raderna framför den
medan(usb_cdc_line_status() == 0x00) slinga
ändslinga

Tilldela ett portnummer till enheten

Om du lämnar allt som det är kommer systemet att tilldela det första lediga portnumret för varje ny anslutning. Det betyder att du alltid måste hålla ett öga på honom.
För att förhindra att detta händer måste du tilldela ett unikt serienummer till enheten innan du ansluter usb-biblioteket:
Numret kan vara av valfri längd och innehålla olika tecken.
const byte USB_STRING3 =
{
24 , -- arraylängd
0x03, -- bDescriptorType
"0" , 0x00 ,
"1" , 0x00 ,
"2" , 0x00 ,
"3" , 0x00 ,
"4" , 0x00 ,
"5" , 0x00 ,
"6" , 0x00 ,
"7" , 0x00 ,
"8" , 0x00 ,
"9" , 0x00 ,
"X", 0x00
}

Ändra enhetens namn till ditt

Du kan ändra namnet på enheten som är synlig i systemet innan du installerar drivrutinerna genom att deklarera en array med samma namn som serienummer måste detta göras innan du ansluter USB-biblioteket.
const byte USB_STRING2 =
{
28 , --
0x03, -- bDescriptorType
"D", 0x00 ,
"e", 0x00 ,
"m", 0x00 ,
"o", 0x00 ,
" " , 0x00 ,
"B", 0x00 ,
"o", 0x00 ,
"a", 0x00 ,
"r", 0x00 ,
"d", 0x00 ,
" " , 0x00 ,
"=" , 0x00 ,
")" , 0x00
}

Men tyvärr, efter att ha installerat drivrutinerna kommer enheten att byta namn till det som anges i .inf-filen, så vi ändrar namnet där också


DESCRIPTION="Demo CDC"

Vi organiserar automatisk anslutning av enheten

Tyvärr, det finns inga direkta sätt att slutföra denna uppgift, så du måste bli smart.

Först och främst måste du tilldela ett unikt tillverkare- och produktvärde till din enhet för att enkelt kunna identifiera den bland hundratals andra vanliga CDC-firmwares.
VID och PID delas ut för pengar, så låt oss följa kinesernas väg: ta tyst de uppenbart fria värdena.

Firmware:
I den fasta programvaran måste du deklarera två variabler innan du ansluter USB-biblioteket

konstord USB_SERIAL_PRODUCT_ID = 0xFF10
konstord USB_SERIAL_VENDOR_ID = 0xFF10

Istället för FF10 kan du infoga två valfria ord (2 byte). Det slutliga resultatet finns i bifogat arkiv.

Drivrutiner:
Eftersom drivrutinerna inte är designade för vår kombination av VID och PID kommer vi att lägga till våra värden till .inf-filen manuellt:


%DESCRIPTION%=Installera drivrutiner, USB\VID_FF10&PID_FF10


%DESCRIPTION%=Installera drivrutiner, USB\VID_FF10&PID_FF10

Programvara:
Låt oss ansluta ComponentUSB-biblioteket för att fånga enhetens anslutnings-/nedkopplingshändelser. Jag tror inte att det är nödvändigt att förklara varje rad: alla ändringar kan ses i det bifogade projektet.

Resultat

Det är svårt att se på skärmdumpen, men sändknappen är bara aktiv när det finns en ansluten enhet, och var 50:e ms skickar programmet en begäran om att få knappens status (vilket dock är felaktigt, eftersom att trycka på knappen ska bearbetas på MK).

Som du kan se är det inte den svåraste uppgiften att organisera datautbyte mellan en MK och en PC via USB. Den resulterande anslutningen kan användas inte bara för slutliga ändamål: den är också lämplig för att felsöka programmet. När allt kommer omkring är det mycket tydligare att skicka beräkningsresultat och aktuella tillstånd för register och variabler till en dator än att blinka ett par lysdioder i morsekod.

Och till sist: Jag råder dig att titta på källkoden för stämningslampan. Där kan du hitta ett ganska bra alternativ för att bearbeta mottagen data för att organisera ett bekvämt utbytesprotokoll.


Topp