Programmieren verschiedener Geräte über USB. Programmieren von USB*-Geräten. Programmierung von HID-Geräten auf „oberster Ebene“


Abb.1 Darstellung des Betriebs eines Android-Geräts im USB-Host- und Zubehörmodus (Abbildung von der Website http://developer.android.com)

Beachten Sie, dass die Verwendung von USB nicht die einzige Möglichkeit ist, mit demselben zu kommunizieren selbstgebautes Gerät. Mit Android können Sie mehr verwenden, NFC, Wi-Fi P2P, SIP sowie Standard Netzwerkverbindung. Im Arsenal der Entwickler gibt es also genügend Möglichkeiten, ihre wildesten Ideen umzusetzen.

Eine weitere gängige Möglichkeit, mit verschiedenen Geräten zu kommunizieren, ist nach wie vor die Verwendung eines USB-COM-Adapters. Es gibt im Netz Material zur Verwendung des USB-COM-Adapters in Android - siehe zum Beispiel. Die Popularität einer solchen Verbindung ist auf das Vorhandensein einer großen Anzahl von Geräten zurückzuführen, die bereits mit verschiedenen Mikrocontrollern entwickelt wurden, deren Kommunikation über einen COM-Port (serielle Schnittstelle) erfolgt, was vor 10 Jahren fast eine Standardmethode zur Datenübertragung war vom Computer bis zur selbstgebauten Hardware.

Im Vergleich zum COM-Port kann die Verwendung von USB die Geschwindigkeit der Datenübertragung deutlich erhöhen und diesen Vorgang benutzerfreundlicher gestalten. Übertragungsgeschwindigkeit, die selbst bei Geräten mit niedriger Geschwindigkeit (Tastaturen, Mäuse, Joysticks) 10-1500 Kbps beträgt, Einfachheit und geringe Kosten für Verkabelung und Anschlüsse, Selbstidentifikation von Geräten mit automatischer Konfiguration, Ausblenden von elektrischen Verbindungsdetails vor Endbenutzer (plus die Möglichkeit, das Kabel zu trennen, ohne die Geräte auszuschalten), Fehlerkontrolle und deren Wiederherstellung auf Protokollebene - dies sind die unbestreitbaren Vorteile dieser Technologie (siehe S.12).

Im Allgemeinen wäre es nützlich, das Buch "USB Interface" von P. Agurov zu erwähnen, wenn es um die Verwendung von USB für die Datenübertragung geht. Obwohl sie im Netz oft kritisiert wurde und zuletzt 2006 veröffentlicht wurde, half sie mehr als einmal, sie zu finden die richtige Entscheidung bei der Suche nach Informationen zu verschiedenen Aspekten der Anwendung dieser Technologie. Das Buch behandelt Fragen: von der Auswahl eines Mikroschaltkreises und einer Schaltung für den Controller bis zum Schreiben eines Mikrocontrollerprogramms und Beispielen für die Programmierung der Datenübertragung über das USB-Protokoll vom Computer. Es ist unmöglich, die "Originalquelle" der Daten zu diesem Thema nicht anzugeben - die Website der gemeinnützigen Organisation USB IF (USB Implementers Forum), die die Spezifikationen dieser Schnittstelle entwickelt -, Wahrheit gegebenen Stoff auf der Englische Sprache. Dort finden Sie jedoch umfassende Informationen zum USB-Schnittstellengerät. Es gibt eine gute Übersetzung von Teilen der Spezifikation - . Wer sich für Softwarelösungen von der Mikrocontroller-Seite interessiert, findet ebenfalls den Link.

Dieser Artikel richtet sich in erster Linie an diejenigen, die welche haben elektronisches Gerät(von Ihnen selbst oder jemand anderem entwickelt), das Kommunikationsprotokoll, mit dem bekannt ist (z. B. gibt es bereits ein Programm, das mit diesem Gerät unter Windows / Linux funktioniert), und ich hätte gerne ein Programm, das damit unter Android funktioniert .

Ein wenig über USB-Geräteklassen

Es ist zu beachten, dass die Entwicklung von Software für den Datenaustausch mit einem bestimmten Gerät stark von ihrer Implementierung auf Mikrocontroller-Ebene abhängt. Aus offensichtlichen Gründen ist es unmöglich, in einem Artikel Beispiele für Kommunikationsprogramme für alle Arten von USB-Geräten zu geben (erste Informationen zum Programmieren verschiedener Gerätetypen finden Sie in). Wir beschränken uns jedoch darauf, den Code vorzustellen, der die Gerätesuche und den Zugriff auf seine Kontrollpunkte für den Informationsaustausch implementiert. Wir analysieren auch Sendedaten am Beispiel einer der Arten von USB-Geräten, nämlich der HID-Geräteklasse (Human Interface Device - eine Klasse von Geräten zur Interaktion mit einer Person). Diese Klasse umfasst "langsame" Geräte wie Tastatur, Maus, Joystick, und es gibt genügend Beispiele für ihre Implementierung mit verschiedenen Mikrocontrollern im Netzwerk (z. B. in ).

Warum liebt die HID-Klasse Hersteller verschiedener hausgemachter Geräte so sehr? Um Wikipedia zu zitieren: „Zusätzlich zu den detaillierten Spezifikationen klassischer Eingabegeräte (wie Tastaturen und Mäuse) definiert der HID-Standard eine spezielle Klasse von Geräten ohne detaillierte Spezifikationen. Diese Klasse heißt USB HID Consumer Control und ist im Wesentlichen ein Ad-hoc-Kommunikationskanal mit dem Gerät. In diesem Fall verwendet das Gerät den gleichen Standard für Betriebssystem Treiber wie eine Maus mit einer Tastatur. Somit ist es möglich, ein USB-Gerät zu erstellen, das keine Erstellung und Installation spezieller Treiber in den meisten gängigen Computerbetriebssystemen erfordert. Es bleibt nur hinzuzufügen, dass diese Spezifikation auch im Android-Betriebssystem funktioniert (CyanogenMod-Firmware nicht ausgenommen).

Eine Option für den Datenaustausch mit einem HID-Gerät ist die Interrupt-Übertragung, die verwendet wird, wenn kleine Datenpakete (die maximale Paketgröße hängt von der Übertragungsrate ab und liegt zwischen 64 und 1024 Bytes) nach einem bestimmten Zeitintervall übertragen werden müssen . Das zu übermittelnde Paket wird Report genannt (engl. - report, siehe S.71, 95). Diese Reportlänge reicht in der Regel aus, um mit einem selbstgebauten Gerät Informationen auszutauschen, 64 Bytes Informationen in einem Paket beispielsweise sind für eine Steuerung schon recht viel, denn 1 Bit an Informationen reicht aus, um die Zustände einer LED oder eines einfachen zu übertragen Sensor.

notwendige Werkzeuge

Wir brauchen also - ein Tablet oder ein Telefon mit Android-Version 3.1 oder höher. An dieser Stelle sei angemerkt, dass die obige USB-Host-API nicht auf allen Mobilgeräten vollständig implementiert ist (dies wird auch auf der Website developer.android.com erwähnt, siehe Link). Einige Tablets/Telefone verwenden den USB-Anschluss nur zum Aufladen und für die PC-Verbindung. Noch einmal schicke ich den Leser zur Liste der für unsere Experimente geeigneten oder ungeeigneten mobilen Geräte (siehe).

Sie benötigen außerdem eine Art USB-Gerät (für die ersten Experimente reicht ein normaler USB-Stick), OTG-Adapter(On-The-Go – siehe Abb. 2) und/oder ein USB-Kabel, um mit dem Gerät zu kommunizieren. Wikipedia über OTG sagt: „Bei einer Verbindung über USB OTG wird der Rang des Geräts (Master oder Slave) durch das Vorhandensein oder Fehlen einer Brücke zwischen den Pins 4 und 5 im Verbindungskabelstecker bestimmt. Bei einem USB-OTG-Kabel ist ein solcher Jumper nur in einem der beiden Stecker verbaut (siehe).» Dementsprechend benötigen wir einen solchen Jumper von der Seite des Mobilgeräts.


Abb. 2 Unterschiede im Schema eines herkömmlichen USB-Kabels und eines OTG-Kabels (Abbildung von http://tech.firstpost.com)

Sie können ein solches OTG-Kabel für Ihr Gerät auch selbst löten. Dazu müssen Sie im Radiogeschäft einen geeigneten Stecker kaufen und beispielsweise den Autor verwenden altes Kabel von einer tragbaren Festplatte:

Eine gute Hilfe bei der Arbeit ist auch das aus dem Google Store installierte Programm USB Device Info Spiel Markt. Das Programm kann Geräte erkennen, die an den USB-Anschluss des Tablets / Telefons angeschlossen sind, sowohl über die Java-API als auch über den Linux-Kernel. Das heißt, wenn Ihr Gerät nicht über die Java USB Host API in USB Device Info erkannt wird, ist es mit hoher Wahrscheinlichkeit vergeblich, ein (einschließlich Ihres eigenen) Android-Programms, das mit Java geschrieben wurde, für dieses mobile Gerät zu verwenden. und USB-Host-API.

Manchmal sind auch die Informationen, die der lsusb-Befehl des Betriebssystems ausgibt, sehr nützlich. Linux-Systeme. Mit den Optionen -v und -d zeigt lsusb alles oder fast alles über ein USB-Gerät an, was ein Softwareentwickler für Geräte dieser Klasse benötigt (siehe Abbildung 3).


Abb. 3 Beispielausgabe der Befehle lsusb und lsusb -v -d

Als nächstes benötigen Sie einen Computer mit installiertem Android SDK und eine integrierte Eclipse-Entwicklungsumgebung (IDE) mit dem ADT-Plugin (obwohl Sie auch nur mit dem SDK auskommen können). Wie Sie beispielsweise eine Android-Anwendung erstellen und installieren, erfahren Sie im oder im Internet.

Und natürlich ist es mindestens genauso wichtig wie der Wunsch, Ergebnisse zu erzielen, ohne es in irgendeiner Weise! Ich notiere das, um einiges zu verdeutlichen Technische Probleme Anwendung von USB in Android durch den Autor, dauerte es Wochen mühsamer Suche nach Informationen.

Java-Klassen für die Arbeit mit USB in der Android-API

Wie es auf der Website der USB-Host-API für Android-Entwickler heißt (siehe) - "Bevor Sie beginnen, ist es wichtig zu verstehen, welche Klassen Sie bei Ihrer Arbeit verwenden werden." Tabelle 1 beschreibt die wichtigsten Klassen für die Arbeit mit der USB-Host-API (ein Versuch, Informationen von http://developer.android.com zu übersetzen).

Tabelle 1. Beschreibung der Klassen für die Arbeit mit USB in Android

Klassenname Beschreibung
UsbManager Ermöglicht die Aufzählung und Kommunikation mit angeschlossenen USB-Geräten.
Ermöglicht Ihnen, ein angeschlossenes USB-Gerät zu erkennen und mit ihm zu kommunizieren.
USB Gerät Stellt ein angeschlossenes USB-Gerät dar und enthält Methoden für den Zugriff auf seine identifizierenden Informationen, Schnittstellen und Endpunkte.
Stellt ein angeschlossenes USB-Gerät dar und enthält Methoden für den Zugriff auf seine Identität, Schnittstellen und Endpunkte.
USB-Schnittstelle Stellt eine Schnittstelle eines USB-Geräts dar, die eine Reihe von Funktionen für das Gerät definiert. Ein Gerät kann über eine oder mehrere Schnittstellen verfügen, über die es kommunizieren kann.
Stellt die "Schnittstelle" eines USB-Geräts dar, das eine Reihe von Funktionen für definiert Dieses Gerät. Ein Gerät kann eine oder mehrere Schnittstellen zum Informationsaustausch haben.
UsbEndpoint Stellt einen Schnittstellenendpunkt dar, der ein Kommunikationskanal für diese Schnittstelle ist. Eine Schnittstelle kann einen oder mehrere Endpunkte haben und hat normalerweise Eingangs- und Ausgangsendpunkte für die bidirektionale Kommunikation mit dem Gerät.
Stellt den "Endpunkt" einer Schnittstelle dar, der der Kommunikationskanal für diese Schnittstelle ist. Eine Schnittstelle kann einen oder mehrere Endpunkte haben und hat normalerweise Endpunkte zum Empfangen und Übertragen von Informationen.
USBDeviceConnection Stellt eine Verbindung zum Gerät dar, das Daten an Endpunkte überträgt. Mit dieser Klasse können Sie Daten synchron oder asynchron hin und her senden.
Stellt eine "Verbindung" zu diesem Gerät dar. Erforderlich, um Daten an den Endpunkt zu senden. Diese Klasse ermöglicht das synchrone oder asynchrone Empfangen oder Senden von Daten.
UsbRequest Stellt eine asynchrone Anforderung zur Kommunikation mit einem Gerät über eine UsbDeviceConnection dar.
Stellt eine asynchrone Anforderung zur Kommunikation mit einem Gerät über eine UsbDeviceConnection dar.
UsbConstants Definiert USB-Konstanten, die den Definitionen in linux/usb/ch9.h des Linux-Kernels entsprechen.
Definiert Konstanten, die den Definitionen in linux/usb/ch9.h des Linux-Kernels entsprechen.

In fast allen Fällen der Verwendung der USB-Host-API verwendet der Programmierer diese Klassen in seiner Arbeit. Der Algorithmus für ihre Anwendung sieht ungefähr so ​​aus: Wir definieren Geräte (das Ziel ist Programmgesteuerter Zugriff an die UsbDevice-Klasse), die über den UsbManager mit dem Host (Mobilgerät) verbunden ist. Nachdem programmgesteuert auf ein Gerät zugegriffen wurde, müssen das entsprechende UsbInterface und der UsbEndpoint definiert werden, um damit zu kommunizieren. Sobald Sie den Endpunkt in Ihrem Besitz haben, öffnen Sie UsbDeviceConnection, um mit dem USB-Gerät zu kommunizieren. Wenn sich der Endpunkt im asynchronen Modus befindet, verwenden Sie die UsbRequest-Klasse.

Versuchen wir, dies alles zu verstehen, indem wir eine einfache Anwendung erstellen, die mithilfe dieser API das mit dem Host verbundene Gerät mit Android-Betriebssystem ermittelt und einige Informationen darüber auf dem Bildschirm des Telefons oder Tablets anzeigt.

Erstellen Sie ein Projekt

In Eclipse wird ein Projekt über die Menüpunkte File->New->Android Application Project erstellt. Beachten Sie auch, dass der folgende Code aus den Beispiel-Apps stammt, die mit dem Android SDK geliefert werden (Ordner android sdk samples/android-N(API Level)/USB). wir reden Informationen zum USB-Spielzeugverwaltungsprogramm Missile Launcher (siehe Abb. 4) Beispielanwendungen werden über den Android SDK-Manager heruntergeladen (Sie müssen den Punkt „Beispiele für SDK“ aktivieren). In den folgenden Auflistungen sind die Codebeispiele kommentiert, um zu erklären, was vor sich geht.


Abb.4 Lustiges Spielzeug "Raketenwerfer"

Vergessen Sie beim Erstellen eines Projekts nicht, den erforderlichen API-Level in der Option Minimum Requared SDK zu markieren (API-Level 12, entspr Android-Versionen 3.1 /Honeycomb/, oder höher). Das Projekt wird eine sehr einfache Benutzeroberfläche haben – das Hauptfenster (Aktivität) und eine Textansicht zum Anzeigen von Informationen. Ein ähnliches Projekt wird ausführlich in diskutiert.

In der automatisch generierten Klasse für die Aktivität unseres Projekts müssen Sie die folgenden Klasseninstanzen für die Arbeit mit USB definieren:

private Textansicht lgView;
privater USBManager mUsbManager;
privates USB-Gerät mDevice;
private USBDeviceConnection mConnection;
privater UsbEndpoint mEndpointIntr;

LGView = (TextView) findViewById(R.id .logTextView ) ;

und Zugriff auf die Klasse UsbManager erhalten

MUsbManager = (UsbManager) getSystemService (Kontext .USB_SERVICE ) ;

Lassen Sie uns einen weiteren Event-Handler onResume() erstellen. Lassen Sie uns das Ziel erreichen – dass Informationen über verbundene Geräte aktualisiert werden, wenn das Fenster unserer Anwendung aktiviert wird (siehe Listing 1).

Listing 1. Der Ereignishandler onResume()

public void onResume()(
super .onResume();

// Füllen Sie den Container mit einer Liste von Geräten
Hashmap< String , UsbDevice>Geräteliste = mUsbManager.getDeviceList();
Iterator< UsbDevice>DeviceIterator = DeviceList.values() .iterator() ;

lgView.setText ( "Geräteanzahl:" + deviceList.size () );

while (deviceIterator.hasNext()) (
UsbDevice Gerät = (UsbDevice) deviceIterator.next() ;

//Beispiel zur Ermittlung der ProductID des Gerätes
\n"+ "Produkt-ID des Geräts: " + device.getProductId () ) ;
}
//den im Filter beschriebenen Intent definieren
// Absicht AndroidManifest.xml
absicht absicht = getIntent() ;
lgView.setText(lgView.getText() + " \n"+ "Absicht: " + Absicht) ;
String action = intention.getAction();

//Wenn das Gerät verbunden ist, übergeben Sie den Link an
//an die Funktion setDevice()
UsbDevice-Gerät = (UsbDevice) intention.getParcelableExtra(UsbManager.EXTRA_DEVICE );
if (UsbManager.ACTION_USB_DEVICE_ATTACHED .equals(action) ) (
setDevice(Gerät) ;
lgView.setText(lgView.getText() + " \n" + "UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action) ist TRUE") ;
) sonst wenn (UsbManager.ACTION_USB_DEVICE_DETACHED .equals(action) ) (
if (mDevice != null && mDevice.equals (Gerät) ) (
setDevice(null) ;
lgView.setText(lgView.getText() + " \n" + "UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action) ist TRUE") ;
}
}

Als Nächstes erstellen wir für die Aktivität die Funktion setDevice(), die für die Arbeit mit unserem Gerät erforderlich ist (siehe Listing 2). Im onResume()-Handler und in der setDevice()-Funktion haben wir uns genau an den im vorherigen Abschnitt beschriebenen Algorithmus zur Verwendung der USB-Host-API gehalten.

Listing 2. Funktion setDevice()

private void setDevice(UsbDevice-Gerät) (
lgView.setText(lgView.getText() + " \n"+ "setDevice" + Gerät) ;

// Verfügbare Geräteschnittstellen definieren
if (device.getInterfaceCount () != 1 ) (

lgView.setText(lgView.getText() + " \n"+ "Schnittstelle konnte nicht gefunden werden" ) ;
Rückkehr;
}
UsbInterface intf = device.getInterface(0) ;

//Geräteendpunkte definieren
if (intf.getEndpointCount() == 0 ) (

lgView.setText(lgView.getText() + " \n"+ "Endpunkt konnte nicht gefunden werden" ) ;
Rückkehr;
) anders (
lgView.setText(lgView.getText() + " \n"+ "Anzahl der Endpunkte: " + intf.getEndpointCount () ) ;
}

UsbEndpoint epIN = null ;
UsbEndpoint epOUT = null ;

//Nach Endpunkten suchen, um Interrupts weiterzuleiten
für (int i = 0 ; i< intf.getEndpointCount () ; i++ ) {
if (intf.getEndpoint(i).getType() == UsbConstants.USB_ENDPOINT_XFER_INT) (
if (intf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN) (
epIN = intf.getEndpoint (i) ;
lgView.setText(lgView.getText() + " \n"+ "IN Endpunkt: " + intf.getEndpoint (i) ) ;
}
anders(
epOUT = intf.getEndpoint (i) ;
lgView.setText(lgView.getText() + " \n"+ "OUT Endpunkt: " + intf.getEndpoint (i) ) ;
}
) sonst (lgView.setText(lgView.getText() + " \n" + "keine Endpunkte für INTERRUPT_TRANSFER") ; }
}

MDevice = Gerät;
mEndpointIntr = epOUT;

//Gerät für Datenübertragung öffnen
if (Gerät != null ) (
UsbDeviceConnection connection = mUsbManager.openDevice (Gerät) ;
if (connection != null && connection.claimInterface (intf, true ) ) (

lgView.setText(lgView.getText() + " \n"+ "Gerät öffnen ERFOLG!" ) ;
mVerbindung = Verbindung;

) anders (

lgView.setText(lgView.getText() + " \n"+ "Gerät öffnen FEHLGESCHLAGEN!" ) ;
mVerbindung = null ;
}
}
}
}

Neben dem oben genannten Code, der, wie der aufmerksame Leser schon erraten haben muss, das Gerät zum Empfangen und Senden von Daten öffnet, bleibt nur noch das Datenaustauschprotokoll zu verwenden, das dem Entwickler, ich wiederhole es, bestens bekannt sein sollte. Hier ist nur, wie versprochen, der Code, der ein Nachrichtendatenpaket an das HID-Gerät sendet, indem die Interrupt-Übertragung, die UsbRequest-Klasse und der entsprechende Endpunkt verwendet werden - siehe Listing 3.

Listing 3. Beispielcode zum Senden von Daten an ein Gerät

// Bestimmen der Größe des zu sendenden Puffers
//ausgehend von maximale Größe Paket
int bufferDataLength = mEndpointIntr.getMaxPacketSize();

lgView.setText(lgView.getText() + " \n"+ mEndpointIntr.getMaxPacketSize () ) ;

ByteBuffer-Puffer = ByteBuffer.allocate (bufferDataLength + 1 );

UsbRequest-Anfrage = new UsbRequest() ;

zwischenspeichern (Nachricht) ;

request.initialize(mConnection, mEndpointIntr) ;

Anfrage.Warteschlange (Puffer, Pufferdatenlänge) ;

if (request.equals (mConnection.requestWait () ) )

// erfolgreich senden
//lgView.setText(lgView.getText() + "\n" + "sende CLEAR!!!");

fangen (Ausnahme Bsp.)

//Stimmt etwas nicht...
//lgView.setText(lgView.getText() + "\n" + "Senden nicht klar...");

Gerätefilterung in AndroidManifest.xml

Obwohl in unserer Anwendung keine Suche erforderlich ist bestimmtes Gerät mit bekannter VID (Vendor-ID) und PID (Produkt-ID), Google-Ingenieure stellen keine Beispiele für Anwendungen ohne einen Intent-Filter-Abschnitt in der Manifestdatei bereit, und der Autor war nicht in der Lage, das Programm ohne Gerätefilterung in AndroidManifest.xml zum Laufen zu bringen.

Ich möchte Sie daran erinnern, dass Vendor-ID und Product-ID eindeutige Kennungen für USB-Geräte sind. Das heißt, Sie können mithilfe von Filtern eine Anwendung erstellen, die nur mit einem bestimmten Gerät oder einer bestimmten Geräteklasse interagiert. Beachten Sie, dass Gerätehersteller diese Nummern mit der USB IF-Organisation vereinbaren müssen.

Eine Anwendung, deren Manifest-Datei in Listing 4 und deren Filterbedingungsdatei in Listing 5 zu sehen ist, erkennt beispielsweise erfolgreich USB-Sticks, die an das mobile Gerät angeschlossen sind, erkennt jedoch nicht die Tastatur und die Maus des Autors. Diese Anwendung kann zusammen mit dem Quellcode über den Link heruntergeladen werden.

Listing 4. AndroidManifest.xml-Datei


" > http://schemas.android.com/apk/res/android"
> package="en.learn2prog.usbhostexample"
android:versionCode="1"
android:Versionsname="1.0" >


android:minSdkVersion="12"
android:targetSdkVersion="14" />


android:allowbackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >

android:name= "de.learn2prog.usbhostexample.MainActivity"
android:label="@string/app_name" >
>

"android.intent.category.DEFAULT" />

"android.intent.category.LAUNCHER" />

>

>

>
"android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
>
>

>

Listing 5. Filterdatei Device_filter.xml (Verzeichnis /res/xml)

>

>

Die Operationen zum Erstellen und Installieren unserer Anwendung unterscheiden sich nicht von den üblichen (siehe Beispiele in , ). Ich möchte auf die Aktionen des Absichtsfilters achten – wenn das Gerät eine Verbindung zum Host herstellt, fordert das Betriebssystem den Benutzer auf, unsere Anwendung zu starten.

Literatur/Links: 11.
12.
13. http://developer.android.com/guide/topics/connectivity/usb/host.html – eine Übersicht über die Klassen, die für die Arbeit mit USB in Android erforderlich sind
14. Link zu Anwendungsquellen

Bild 1

Die USB-Schnittstelle wird als Kommunikationsschnittstelle immer beliebter Peripheriegeräte mit einem PC und moderne Computer verfügen oft nicht über die übliche RS-232-Schnittstelle. Die Popularität von USB hat viele Gründe, hier sind die wichtigsten:

  • hoher Wechselkurs, hohe Störfestigkeit
  • Datenflusskontrolle, Integritätskontrolle und Fehlerkorrektur
  • die Möglichkeit, über Hubs zu verzweigen und eine große Anzahl von Geräten anzuschließen.
  • Bus-Stromversorgung
  • Bus-Vielseitigkeit - die Möglichkeit, verschiedene Geräte (Tastatur, Drucker, Modem) anzuschließen
  • automatische Systemerkennung und Konfiguration, Plug and Play

Es gibt jedoch (oft unvernünftige) Faktoren, die die Mainstream-Nutzung von USB durch MCU-Entwickler zurückhalten:

  • die Notwendigkeit, Treiber für Windows zu programmieren
  • relativ geringe Verbreitung von Mikrocontrollern mit eingebauter USB-Schnittstelle
  • Lektion 2: Erstellen Sie ein USB 2.0-kompatibles HID-Joystick-Gerät.

Diese Artikelserie soll zeigen, dass es ganz einfach ist, diese Schwierigkeiten zu überwinden und jeder sein Gerät von der üblichen RS-232 auf USB „aufrüsten“ oder ein neues Gerät mit USB-Schnittstelle erstellen kann.

Als Mikrocontroller in den Beispielen wird ein von Microchip hergestellter Mikrocontroller betrachtet. PIC18F4550 mit USB 2.0 Schnittstelle (unterstützt Low Speed ​​und Full Speed).

Lektion 1. USB ohne Windows-Programmierung, virtueller COM-Port

Eine der Aufgaben, die bei der Entwicklung von USB-Geräten anfallen, ist der Übergang von der RS-232-Schnittstelle zu USB, und wenn ein "altes" Gerät modifiziert wird oder das Gerät mit bestehenden Protokollen und PC-Software kompatibel sein muss, dann ist dies wünschenswert Entfernen Sie alle Software-Modifikationen Software auf dem Computer. Eine Lösung für dieses Problem besteht darin, die USB-Schnittstelle als virtuellen COM-Port zu verwenden. Die Verwendung dieses Verfahrens eliminiert die Notwendigkeit, die Computersoftware zu modifizieren, weil. Der USB-Anschluss wird vom Personal Computer als zusätzlicher COM-Port angesehen. Ein weiterer wichtiger Vorteil ist, dass Standard-Windows-Treiber verwendet werden und keine benutzerdefinierten Treiber erstellt werden müssen.

Die USB-Spezifikation beschreibt eine Klasse von Kommunikationsgeräten (Communication Device Class - CDC), die eine Reihe von Verbindungsmodi für Telekommunikation (Modems, Terminals, Telefone) und Netzwerkgeräte (Ethernet-Adapter und -Hubs, ADSL-Modems) einschließlich der Emulation serieller Ports definiert .

Nehmen wir als Beispiel ein Gerät, das Spannungsdaten von einem Potentiometer und Temperatur von einem TC77-Digitalsensor über RS-232 überträgt und auch Befehle zum Ein- und Ausschalten von zwei LEDs empfängt (der Einfachheit halber implementieren wir dieses Beispiel auf dem PICDEM™ FS USB DEMONSTRATION BOARD Board, aber Sie können eine einfachere Schaltung zusammenbauen - siehe unten).

Das PICDEM FS-USB-Debug-Board wurde für die Entwicklung und Demonstration von Geräten entwickelt, die auf dem PIC18F4550-Mikrocontroller mit einem USB2.0-Bus basieren. Das Board verfügt über einen PIC18F4550-Controller in einem TQFP44-Gehäuse, das die folgenden Merkmale aufweist:

  • Maximale Betriebsfrequenz - 48 MHz (12 MIPS);
  • 32 KB Flash-Programmspeicher (Enhanced Flash-Technologie);
  • 2 KB Datenspeicher (davon 1 KB Dual-Port-RAM);
  • 256 Bytes EEPROM-Datenspeicher;
  • FS USB2.0-Schnittstelle mit Unterstützung für 12Mbps-Geschwindigkeit mit eingebautem Transceiver und Spannungsregler.

Der Vorstand hat:

  • Quarz 20 MHz;
  • RS-232-Schnittstelle zur Demonstration der Möglichkeit, von USART zu USB zu wechseln;
  • Anschluss für In-Circuit-Programmierung und Debugging
  • Spannungsstabilisator mit der Möglichkeit, auf USB-Bus-Power umzuschalten;
  • PICtail™ Erweiterungsanschluss;
  • Temperatursensor TC77 über I2C angeschlossen;
  • Variabler Widerstand, der mit dem ADC-Eingang verbunden ist;
  • LEDs, Tasten.

Dieses Gerät verfügt über ein PC-Programm zur Steuerung des Gerätes und zur Anzeige von Spannungs- und Temperaturwerten. So können wir das Gerät an RS-232 anschließen, den im System verfügbaren COM-Port auswählen und mit unserem Gerät die Austauschrate, die Anzahl der Datenbits, die Anzahl der Stoppbits sowie die Parameter der Paritätsbits und einstellen Flusssteuerung gemäß dem Mikrocontroller-Programm (dafür müssen wir die Initialisierungsparameter unseres Controllers kennen)


Reis. 2

Fangen wir an, unser Gerät an USB anzuschließen.

Microchip Technology Inc. Bietet ein fertiges Anwendungsbeispiel AN956, das USB-CDC-Unterstützung für die Mikrocontroller PIC18F2550, PIC18F2455, PIC18F4455, PIC18F4550 implementiert. Das Programm ist modular aufgebaut, was eine einfache Modernisierung und Integration in fertige Projekte ermöglicht.

Nach der Erstinitialisierung des Controllers kann das Programm über mehrere vorgefertigte Funktionen mit dem PC über die USB-Schnittstelle kommunizieren:

Lassen Sie uns unser Programm ändern, um Daten über USB zu senden und zu empfangen.

Fragment des Programms zum Aufbereiten und Übertragen von Daten:

Datenempfang:

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(); Pause; Standard: Pause; ) )

Nachdem Sie das Gerät an USB angeschlossen haben, erkennt das System das neue Gerät


Reis. 3

Und installiert neue Geräte


Reis. vier

Wir wählen die Installation aus dem angegebenen Speicherort aus und geben den Pfad für den Speicherort der Datei mcpusb.inf aus dem Satz von Quellcodes für das Programm bis AN956 an. Danach wird ein neues Gerät im System installiert.


Reis. 5

Das neue Gerät ist also einsatzbereit. Das System hat einen neuen virtuellen COM-Port.


Reis. 6

Jetzt können wir in unserem Programm den angezeigten virtuellen COM-Port auswählen, um mit dem Gerät zu kommunizieren ...


Reis. 7

... und sehen Sie, dass das Gerät wirklich über den im System über eine USB-Verbindung angezeigten COM-Anschluss zu arbeiten begann.

Es sollte beachtet werden, dass USB Datenkontrolle und -korrektur bereitstellt, sodass Konzepte wie Flussrate, Paritätsbits und Flusskontrolle zu abstrakten Konzepten werden, und in unserem Fall können sie von jedem gewählt werden, der einzige Informationsparameter ist die virtuelle COM-Portnummer.

PICDEM CDC-Fenster


Reis. acht

Bei Verwendung von PIC18Fxx5x-Mikrocontrollern mit eingebautem USB 2.0-Modul kann der virtuelle COM-Port eine Datenübertragungsrate von bis zu 80 KByte pro Sekunde (640 Kbps) bereitstellen, was die mögliche Übertragungsrate über RS-232 deutlich übertrifft, während, wie wir können Sehen Sie, es besteht keine Notwendigkeit, Software für einen Computer zu modifizieren, den es brauchte!

Beispielprogramme, Dokumentation und Diagramm, die in Lektion 1 verwendet wurden.

  1. Laden Sie PICDEM CDC + Delphi-Quellen herunter
  2. Delphi-Komponente, mit der gearbeitet werden soll COM-Port Download
  3. AN956+ Original-Quellcodes
  4. Datei user_uart.c (alle Änderungen am ursprünglichen Programm von AN956 wurden nur in dieser Datei vorgenommen. Um das Beispiel für Lektion 1 auszuführen, müssen Sie diese Datei in das Verzeichnis C:\MCHFFSUSB\fw\Cdc\user\ kopieren, ersetzen Sie die user.c Datei im Projekt mit user_uart .c, kompilieren Sie das Projekt und flashen Sie den Mikrocontroller)
  5. Vereinfachtes Diagramm eines USB-Geräts


Reis. 9

Hinweis: Die Originalschaltung des PICDEM FS USB-Boards verwendet eine automatische Erkennung der Stromquelle des Boards (extern oder USB). Daher müssen Sie bei Verwendung eines vereinfachten Schemas die Zeile #define USE_USB_BUSSENSE_IO in der Datei usbcfg.h auskommentieren

Lektion 2: Erstellen eines USB 2.0-kompatiblen HID-Joystick-Geräts

Die gängigsten USB-Geräte sind Human Interface Devices (HID). Typische Vertreter dieser Klasse sind USB-Tastaturen, -Mäuse, -Joysticks, Monitoreinstellungsfelder, Barcodeleser, Kartenleser usw. Die Vorteile von HID-Geräten sind:

  • Leichtigkeit der Durchsetzung;
  • kompakter Code;
  • Windows-Unterstützung (keine zusätzlichen Treiber erforderlich).

Die Microchip-Website enthält eine Beispielimplementierung einer HID-Maus. Betrachten Sie die Implementierung des einfachsten Gamecontrollers basierend auf diesem Beispiel. Für dieses Projekt verwenden wir das PICDEM FS-USB-Demoboard (DM163025). Das PICDEM FS-USB-Debug-Board verfügt über einen variablen Widerstand und 2 Tasten, sodass der in der Entwicklung befindliche Joystick ein Minimum an Bedienelementen haben wird (2 Tasten und beispielsweise ein Gashebel).

Zunächst müssen wir den Gerätedeskriptor für den erstellten Joystick neu schreiben. Um die Aufgabe zu vereinfachen, können Sie das Programm HID Descriptor Tool verwenden, das von der Website heruntergeladen werden kann www.usb.org

Im Programm enthalten sind Beispielkonfigurationen einiger HID-Geräte, die Sie für Ihre Aufgabe anpassen oder Ihr eigenes HID-Gerät erstellen können.


Reis. zehn

In unserem Fall werden also mehrere Arten von Daten verwendet - dies ist eine Simulation der Steuerung - Simulation Controls, und insbesondere das Gaspedal (Pedal) (Throttle) und die Steuertasten (Button). Damit das Betriebssystem „wissen“ kann, wie es mit diesen Datentypen umgeht, ist es notwendig, die Maximal- und Minimalwerte sowie die Größe der Daten zu beschreiben. In unserem Fall ist „gas“ ein 8-Bit-Wert (report_size = 8, report_count = 1), und der Status der Schaltflächen ist als Feld mit 1-Bit-Werten definiert. Das Beispiel verwendet nur 2 Schaltflächen, aber es ist notwendig, das Feld auf einen Bytewert auszurichten (report_size = 1, report_count = 8). Insgesamt muss der Mikrocontroller beim Anfordern von Daten vom Computer 2 Bytes übertragen - den Gaspegel und den Zustand der Tasten gemäß dem generierten Gerätedeskriptor (eine detaillierte Beschreibung möglicher Deskriptoren finden Sie in der Spezifikation für HID-Geräte www.usb.org). Die erstellte Beschreibung des Gerätedeskriptors kann in verschiedenen Formaten gespeichert werden, unter anderem als Header-Datei.h

Außerdem müssen Sie die Größe des empfangenen Gerätedeskriptors in der Beschreibung des HID Class-Specific Descriptor anpassen und die Größe der über den Endpunkt übertragenen Daten im Endpunktdeskriptor ändern (in unserem Fall übertragen wir 2 Bytes, also die Größe ist HID_INT_IN_EP_SIZE=2).

Diese Änderungen reichen aus, damit Windows das angeschlossene Gerät als Joystick erkennt. Jetzt können wir die Stringdaten so anpassen, dass das Gerät den gewünschten Namen hat (zB "PIC18F4550 Joystick"). Um dem Gerät einen Namen auf Russisch zuzuweisen, müssen Sie einen String-Deskriptor in UNICODE-Kodierung angeben. Hier endet die Beschreibung des Joysticks und wir müssen die Daten für die Übertragung auf den PC vorbereiten.

ReadPOT(); // Potentiometer-Spannungsmessungspuffer starten = ADRESH; // Schaltflächenzustände verarbeiten if(sw2==0) buffer |= 0x01; Puffer &= ~0x01; if(sw3==0) Puffer |= 0x02; Puffer &= ~0x02; // Datenübertragung Emulate_Joystick();

Nachdem Sie das Projekt kompiliert und den Mikrocontroller programmiert haben, können Sie das Gerät an den USB-Anschluss anschließen. Das Board ist als HID-Gaming-Gerät definiert, im System installiert und einsatzbereit.


Reis. elf

Über die Systemsteuerung in Windows können wir die verfügbaren Spielgeräte öffnen, unseren Joystick auswählen, kalibrieren und die Funktionalität testen.


Reis. 12

Beim Ändern der Gerätekonfiguration - Hinzufügen von Steuerelementen oder Schaltflächen - ist es nicht nur erforderlich, die Beschreibung des Gerätedeskriptors zu ändern, sondern auch Daten strikt in Übereinstimmung mit dem erstellten Deskriptor zu übertragen. Wenn wir also die maximale Anzahl von Tasten von 2 auf 8 in der Beschreibung des Gerätedeskriptors USAGE_MAXIMUM (BUTTON 2) ändern, erhalten wir einen Joystick mit 8 Tasten.


Reis. 13

Wenn der Deskriptor komplizierter wird, können wir eine vollständigere Implementierung des Joysticks erhalten, während Sie daran denken müssen, die folgenden Parameter zu ändern: die Größe des Deskriptors, die Größe des Endpunkts und Sie müssen so viele Informationsdaten senden wie im Deskriptor angegeben.


Reis. vierzehn

Beispielprogramme, Dokumentation und Diagramm, die in Lektion 2 verwendet wurden.

  1. Die ursprünglichen Quellcodes für die Implementierung der HID-Maus.
  2. HID-Joystick-Implementierungsquellcodes.

Lektion 3

Jedes USB-Gerät kann mehrere Konfigurationen haben, und jede Konfiguration hat mehrere Schnittstellen. Diese USB-Eigenschaft ermöglicht, dass das erstellte Gerät vom Computer als mehrere USB-Geräte mit unterschiedlichen Schnittstellen erkannt wird. Eine Maus kann beispielsweise einen eingebauten Kartenleser haben und als zwei unabhängige Geräte mit dem Computer interagieren.

Struktur des Gerätedeskriptors:


Reis. fünfzehn

Basierend auf dem Standardbeispiel einer Maus und dem erstellten Joystick erstellen wir ein zusammengesetztes USB-Gerät, das vom Computer als zwei unabhängige HID-Geräte definiert wird.

1. Erstellen Sie einen Deskriptor.

Ändern Sie die Struktur des Deskriptors (Datei usbdsc.h)

Das Gerät verfügt über 2 Schnittstellen mit jeweils einem Endpunkt.

#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;\USB_HID_DSC hid_i01a00;\USB_EP_DSC ep02i_i01)
  1. Entsprechend der geänderten Struktur müssen Sie den Deskriptor in der Datei usbdsc.c ändern.
  2. Definieren Sie in der Datei usbcfg.h Schnittstellenkennungen, verwendete Endpunkte und Berichtsdeskriptorgrößen.
  3. In der Datei hid.c müssen Sie zusätzliche Endpunkte (in der Funktion HIDInitEP) initialisieren und die Funktion zur Verarbeitung von HID-Anforderungen (Funktion USBCheckHIDRequest) ändern.
  4. Jedes der Geräte, Maus und Joystick, muss Daten an seinen eigenen Endpunkt übertragen. Daher müssen wir Funktionen hinzufügen, um Daten an bestimmte Endpunkte zu übertragen und zu überprüfen, ob der gewünschte Endpunkt frei ist (Funktionen ähnlich wie mHIDTxIsBusy und HIDTxReport in der Datei hid.c hinzufügen).

Dann sieht die Datenübertragung für die Maus aus

Nach dem Kompilieren des Projekts, dem Flashen des Controllers und dem Anschließen des Geräts an USB wird ein neues Composite-Gerät vom Computer erkannt und eine Maus und ein Joystick werden hinzugefügt.


Reis. 16


Reis. 17

Zusammengesetzte HID-Gerätequellcodes.

Kommentar. Vergessen Sie nicht, die PID zu ändern, wenn Sie ein neues Gerät erstellen, oder löschen Sie ein vorheriges Gerät mit derselben PID aus dem System.

Lektion 4

Microchip Technology Inc. veröffentlicht preiswerten Entwicklerprogrammierer PICkit2, das hauptsächlich zum Programmieren von Flash-Controllern verwendet wird. Eine Besonderheit dieses Programmierers ist die Verfügbarkeit einer vollständigen Dokumentation und Firmware-Quellcodes für den Mikrocontroller und ein Shell-Programm für den Computer. PICkit2 wird über USB mit Strom versorgt, erzeugt einstellbare Programmier- und Leistungsspannungen und verfügt außerdem über 3 Eingangs-Ausgangsleitungen zum Anschluss an ein programmierbares Gerät. Um die Firmware des Programmierers in PICkit2 aktualisieren zu können, wurde ein Bootloader-Programm implementiert.


Reis. achtzehn

CDC-Gerät basierend auf PICkit2

Mit all diesen Funktionen, die auf dem PICkit2-Programmierer basieren, ist es möglich, Ihr eigenes USB-Gerät zu erstellen und zu debuggen, wobei Sie jederzeit auf seine Programmiererfunktionen zurückgreifen können. Mit Hilfe des Bootloaders, der in den Programmer geflasht wird, können andere Programme in das PICkit2 geflasht werden, zum Beispiel das virtuelle COM-Port-Unterstützungsprogramm. Dazu nehmen wir das Beispiel CDC, benennen das Projekt um und gehen wie folgt vor

  1. In der Datei main.c ändern wir die Adresse des Firmware-Speicherorts (der PICkit2-Bootloader überträgt die Steuerung an das Benutzerprogramm auf die Adresse 0x002000.
    #Pragmacode _RESET_INTERRUPT_VECTOR = 0x002000
  2. In der Datei io_cfg.h entfernen wir alles über Port D (Sie können die LED so einstellen, dass sie auf PORTC0 blinkt).

    Da PICKIT2 immer über USB mit Strom versorgt wird, legen wir fest

    #define usb_bus_sense 1 // Gerät ist immer eingesteckt #define self_power 0 // Gerät wird über USB mit Strom versorgt

  3. In der usbcfg.h-Datei haben wir zwei Zeilen kommentiert
    //#define USE_SELF_POWER_SENSE_IO //#define USE_USB_BUS_SENSE_IO
  4. In der Datei user.c geben wir die Daten, die wir benötigen, auf USB aus
  5. Binden Sie die Linker-Datei pickit2.lkr ein

Danach können Sie das Projekt kompilieren und die neue Firmware über die PICkit2-Shell laden.

Nach der Neuprogrammierung des PICkit2 erkennt der Computer das Erscheinen eines neuen COM-Ports, und über das Hyperterminal können wir sehen, dass das PICkit2 Daten über den virtuellen COM-Port sendet.

Der Quellcode für dieses Beispiel ist unter verfügbar Verknüpfung.

Basierend auf diesem Beispiel und unter Verwendung der externen Pins des PICkit2-Programmierers können Sie Daten von externen Geräten empfangen und über USB auf einen Computer übertragen. Daher können Sie mit PICkit2 Daten an COG-LCD-Anzeigen, I2C-Lesegeräte, SPI- und 1-Draht-Geräte wie Temperatursensoren usw. ausgeben.

Funk-HID-Tastatur basierend auf PICkit2


Reis. 19

Betrachten wir ein weiteres Beispiel für die "unangemessene" Verwendung des PICkit2-Programmierers - eines Tastaturemulators mit einer Luftschnittstelle. Ein solches Gerät kann zum Beispiel für Präsentationen verwendet werden – zum Blättern durch Folien abseits des Computers.

Um ein solches Gerät zu implementieren, benötigen wir:

  • PICkit2
  • PICkit2-Demoboard (DV164120)
  • Funkempfänger (rfRXD0420) und Funksender (rfPIC12F675) von rfPICkit.

Wir verbinden den Funkempfänger mit dem Demoboard. Der Mikrocontroller auf der Platine empfängt Daten vom Empfänger, verarbeitet sie und stellt beim Drücken einer der beiden Tasten auf der Fernbedienung den log.1-Pegel auf einen der 2 mit PICkit2 verbundenen Ausgänge ein.

PICkit2 führt die folgenden Funktionen aus:

  • Wenn es über USB mit einem Computer verbunden ist, wird es als HID-Tastatur definiert
  • eine +5V Versorgungsspannung für ein Demoboard mit Empfänger erzeugen
  • 2 externe Ausgänge des Empfängercontrollers abfragen und, falls vorhanden, ein Protokoll. 1 Codes zum Drücken der PageUp- oder PageDown-Tasten an den Computer senden.

Zwei virtuelle COM-Ports (FTDI2232-Chip-Emulation) basierend auf PICKit2

Dieses Beispiel dient nur zum Erlernen der Funktionsweise von USB. Überprüfen Sie vor der Verwendung die FTDI-Führerscheinanforderungen!

Das Beispiel zeigt, wie man 2 virtuelle COM-Ports basierend auf einem Mikrocontroller mit einem USB-Port erstellt.Zuerst müssen Sie Treiber für den FTDI2232-Chip installieren. Um dann in PICkit2 zu booten, müssen Sie das Firmware-Update-Element in der PICkit2-Shell auswählen und auf die Datei TestVCP2.hex verweisen Archiv. Nach der Neuprogrammierung von PICkit2 haben Sie 2 unabhängige serielle COM-Ports in Ihrem System.

Beispiel von der Website übernommen http://forum.microchip.com/tm.aspx?m=261649

Um PICkit2 als Programmierer rückgängig wiederherzustellen, müssen Sie PICkit2 von USB trennen und, während Sie die Taste drücken, das USB-Kabel wieder anschließen und dann wählen, die Standard-Firmware des Programmierers zu laden.

Alle obigen Beispiele basieren auf MCHFFSUSB Framework v1.3. Mit dem Aufkommen von PIC24- und PIC32-Controllern mit USB-OTG hat Microchip eine neue Version des Stacks veröffentlicht – USB-Stack v. 2.x.

In der neuen Version von USB Stack v. 2.3, zusätzlich zu den USB-Gerätestapeln, die die Funktionalität eines USB-Clients implementieren, dem eingebetteten USB-Host, der die Host-Funktionalität implementiert, wurde auch ein USB-Dual-Role-Stack erhalten, der die Funktionen sowohl des Hosts als auch des Clients implementiert; und USB OTG, das das Host Role Negotiation Protocol (HNP) und das Session Request Protocol (SRP) unterstützt und vollständig mit der USB-OTG-Spezifikation kompatibel ist. In den Anwendungsbeispielen umgesetzt:

  • Eingebetteter Host
    • Druckerklassen-Host – Unterstützung für ESC/POS-, PostScript®- und PCL5-Drucker
    • CDC-Klassenhost – Unterstützung für ACM-Geräte (abstraktes Steuerungsmodell)
    • HID-Tastatur
  • Gerät
    • HID-Bootloader – Unterstützung für die Familien PIC32MX460F512L und PIC18F14K50 hinzugefügt
    • HID-Tastatur, Maus
    • Demo des internen MSD-Flashs – Verwendung des internen Flashs zum Speichern von Dateien
    • Beispiel für ein zusammengesetztes MSD + HID - Beispiel für ein zusammengesetztes MSD- und HID-Gerät
    • CDC - COM-Port-Emulation
    • Unterstützung der PIC32MX460F512L-Familie für alle PC-Demoprojekte
    • Die Beispiele HID, MCHPUSB und WinUSB unterstützen jetzt die Plug-and-Play-Funktion (PnP) von Microsoft für die automatische Erkennung.
  • Dokumentation
    • eine vollständige Beschreibung aller APIs befindet sich im Ordner "\Microchip\Help"

Microchip bietet kostenlose Treiber für die gängigsten USB-Klassen:

  1. Benutzeroberfläche (HID). Dieser Austauschmodus wird in fast allen Tastaturen, Mäusen und anderen Ein-/Ausgabegeräten verwendet.
  2. Kommunikationsgerät (CDC). In diesem Modus lässt sich am einfachsten von seriell RS-232 auf USB umschalten. Auf WinXP/2K-Rechnern wird beim Anschluss eines Mikrocontrollers ein virtueller COM-Port angelegt und emuliert. Programme, die mit COM1..4-Ports arbeiten, funktionieren ohne Änderungen mit einem virtuellen Port, aber mit einer höheren Geschwindigkeit (ca. 1 Mbit/s)
  3. Massenspeichergeräte (MSDs). Dies sind Geräte, die als Speichermedien fungieren - Flash-Laufwerke, SD / MMC-Karten, Festplatten usw.
  4. Geräte der Druckerklasse. Dieser Modus ist für die Verwendung mit USB-Druckern konzipiert, wodurch das Endgerät auf einem PIC-Mikrocontroller mit USB-Modul die notwendigen Informationen direkt an den USB-Drucker ausgeben kann.
  5. Mikrochip-residenter Bootloader. Der einfachste Modus, der nur zum Aktualisieren der Mikrocontroller-Software über USB verwendet wird. Auf der PC-Seite wird ein kleines Programm installiert, ein Analogon des Treibers
  6. Eigener Fahrer (Benutzerdefiniert). Die vollständigste Nutzung von USB2.0-Ressourcen für fortgeschrittene Benutzer: die Möglichkeit, Busbetriebsmodi auszuwählen (isochron, Interrupt, Surround, Control), hohe Übertragungsgeschwindigkeit. Erfordert umfassende Buskenntnisse und Fähigkeiten in der Windows-Softwareentwicklung

Bootloader mit USB-Stick

Aktualisieren der Firmware von einem normalen Flash-Laufwerk.

Um die Firmware eines Mikrocontrollers mit einem USB-OTG-Modul (PIC24 oder PIC32) zu aktualisieren, ist keine spezielle Software erforderlich. Das Vorhandensein des Host-Modus ermöglicht es Ihnen, gewöhnliche USB-Datenlaufwerke (Flash Drive) an den Mikrocontroller anzuschließen. Ein Beispiel wurde auf der Microchip-Website veröffentlicht ( Beta-Version), mit der Sie die Mikrocontroller-Software von einem angeschlossenen USB-Laufwerk aktualisieren können.

Um das Beispiel auszuführen, müssen Sie die Bootloader-Firmware in ein PIC32-USB-Board oder Explorer 16 laden (mit einem PIC32-USB-PIM-Prozessormodul und einem installierten PICtail Plus-USB-Tochterboard). Wenn die Platine mit Strom versorgt wird, während die Taste gedrückt wird, wechselt der Controller in den Firmware-Aktualisierungsmodus. Wenn Sie nun einen USB-Stick mit einer aufgezeichneten Firmware-Update-Datei anschließen, liest der Mikrocontroller diese Datei und überschreibt sie in seinem Programmspeicher.

Entwicklungsboards und Entwicklungstools für USB

PICkit2-Debugger-Programmierer (Bestellnummer PG164120)

Das Vorhandensein eines Bootloaders ermöglicht es Ihnen, Ihre Software hochzuladen, um die Fähigkeiten der Arbeit mit USB zu beherrschen


Reis. zwanzig

PICDEM FS-USB Entwicklungsboard (Bestellnummer DM163025)

Konzipiert für die Entwicklung und Demonstration von Geräten auf Basis des Mikrocontrollers PIC18F4550 mit USB2.0-Bus. Das Board verfügt über einen PIC18F4550-Controller in einem TQFP44-Gehäuse.


Reis. 21

Low Pin Count USB Development Kit (Bestellnummer DM164127)

Das Low Pin Count USB Development Kit bietet eine einfache Möglichkeit, die Mikrocontroller-Fähigkeiten der Microchip PIC18F14K50 und PIC18F13K50 20-Pin-USB-Mikrocontroller zu evaluieren. Das Kit enthält alles, was Sie für den Einstieg in USB-Controller benötigen (Software, Beispiel-Quelldateien, Dokumentation).


Reis. 22

PIC18F87J50 Full Speed ​​USB PIC18F87J50 FS USB Demoboard (Bestellnummer MA180021)

Das PIC18F87J50 FS USB Demo Board dient zum Debuggen von Full Speed ​​USB 2.0 Mikrocontrollern der PIC18F87J50 Familie. Neben dem autonomen Betrieb kann das Board auch als Prozessormodul für das PIC18 Explorer Board verwendet werden.


Reis. 23

PIC24 Starter Kit (Bestellnummer DM240011)

Das PIC24F Starter Kit enthält alles, was Sie für den Einstieg in die leistungsstarke PIC24F-Controller-Familie benötigen. Dieses kostengünstige Kit enthält einen integrierten In-Circuit-Debugger und -Programmierer, einen USB-PIC24F-Controller (Host- und Gerätefunktionen können auf der Platine implementiert werden), eine dreifarbige LED, ein kapazitives Touchpanel und ein OLED-Grafikdisplay. Das Demoprogramm ermöglicht Ihnen über das grafische Menü, Daten auf ein externes USB-Flash-Laufwerk zu schreiben, das Touchpanel zu konfigurieren und Grafikaufgaben auszuführen.


Reis. 24

PIC32 USB Board (Bestellnummer DM320003)

Ermöglicht das Mastern des USB-OTG-Moduls in PIC32-Controllern


Reis. 25

Entwicklungsboard „Explorer 16 Development Board“ (Bestellnummer DM240001)

Dies ist ein kostengünstiges Debug-Tool für den Einstieg in die Hochleistungs-PIC24-16-Bit-Mikrocontroller-Familien und dsPIC33F-Digitalsignalverarbeitungs-Controller.


Reis. 26

Tochterplatine „USB PICtali Plus“ (Bestellnummer AC164131)

Zusammen mit USB-Prozessor-Plug-in-Modulen ermöglicht es Ihnen, USB-Geräte Host, Device, USB-OTG zu entwickeln und zu debuggen.


Reis. 27

Ilja Afanasiev,
Gesellschaft

Beginnen wir mit dem Minimum:
include 18f2455 - Bibliothek für gebrauchte MK
--
enable_digital_io() -- alle Eingänge in den Digitalmodus schalten
--
alias Taste ist pin_B7 -- Da wir einen Button angeschlossen haben, deklarieren Sie ihn
pin_B7_direction = Eingang -- der Knopf funktioniert bei uns am Eingang
--
-- eine Zeile - und wir haben alles, was Sie für die Arbeit mit USB CDC benötigen
include usb_serial – USB-Bibliothek
--
usb_serial_init() -- --USB-CDC initialisieren
ewige Schleife-- Hauptschleife, läuft kontinuierlich
usb_serial_flush() -- USB-Update. Dieses Verfahren erledigt alles Notwendige
-- Aktionen zur Aufrechterhaltung der Verbindung mit dem PC
Endschleife

Nachdem Sie diesen Code kompiliert haben, schreiben Sie die resultierende Hex-Datei in der MK mit dem Bootloader und dem Starten des Geräts kann beobachtet werden, wie ein neues Gerät im System definiert wird: Virtueller Com-Port.

Nun, da das Gerät bereits funktioniert, wollen wir ihm das Kommunizieren beibringen.

Um das empfangene Byte zu lesen, gibt es eine Funktion usb_serial_read( Byte ) : boolesch. Wenn es ein empfangenes Byte gibt, speichert es es in der angegebenen Variablen und kehrt zurück Stimmt, ansonsten zurück FALSCH.

Es gibt eine Prozedur, um ein Byte zu senden usb_serial_data. Es ist als Variable getarnt, um also ein Byte zu senden, reicht es aus, ihm den Wert des gesendeten Bytes zuzuweisen.

Lassen Sie uns vor der Hauptschleife eine Variable mit einer Größe von Bytes deklarieren. In der Hauptschleife prüfen wir, ob empfangene Bytes vorhanden sind, und senden sie gegebenenfalls zurück.

gehören 18f2455
--
enable_digital_io()
--
alias Taste ist pin_B7
pin_B7_direction = Eingang
--
--
schließen Sie usb_serial ein
--
usb_serial_init()
Var-Byte CH -- Deklarieren Sie eine Variable
ewige Schleife-- Hauptschleife
usb_serial_flush()
wenn(usb_serial_read(ch)) dann-- wenn ein Byte empfangen wird, wird es in ch geschrieben
usb_serial_data=ch -- sende das empfangene Byte zurück
Ende wenn
Endschleife

Wir kompilieren, halten die Taste gedrückt, verzerren die Stromversorgung, starten den Bootloader, ändern die Firmware, starten sie.
Das Gerät wurde erneut im System erkannt, jetzt benötigen wir Software, um die Funktion des Geräts zu testen.

Obwohl wir kein eigenes haben, verwenden wir ein fertiges Terminal: Ich habe das RealTerm-Programm verwendet.
Wir öffnen den Port mit der gewünschten Nummer und senden die Daten.


Und wir bekommen zurück, was wir gesendet haben. Also alles funktioniert wie es soll.

Sanft

Unser Mikrocontroller kann also Bytes empfangen und sofort zurücksenden. Lassen Sie uns jetzt unsere eigene Software schreiben, um damit zu kommunizieren (ich werde Delphi verwenden).

Wir erstellen ein neues Projekt, streuen die erforderlichen Komponenten in der Form:
SpinEdit1 - um die Portnummer anzugeben
Button1 - um eine Verbindung herzustellen
Button2 - um die Verbindung zu unterbrechen
SpinEdit2 - um ein Byte in Dezimalform einzugeben
Button3 - um ein Byte zu senden
Memo1 - um empfangene Informationen anzuzeigen.

Wie oben erwähnt, müssen Sie mit dem Com-Port genauso arbeiten wie mit einer normalen Textdatei: mit den Funktionen CreateFile, WriteFile und ReadFile.

Um nicht ins Detail zu gehen, nehmen wir eine fertige Bibliothek für die Arbeit mit einem Com-Port: ComPort.

Wir hängen die notwendige Aufgabe an jede Schaltfläche und erhalten den endgültigen Code:

Einheit Einheit1;

Schnittstelle

Verwendet
Windows, Nachrichten, SysUtils, Varianten, Klassen, Grafiken, Steuerelemente, Formulare,
Dialoge, StdCtrls, Spin,ComPort;

Typ
TForm1 = Klasse (TForm)
SpinEdit1: TSpinEdit;
Taste1: TTaste;
Taste2: TTaste;
SpinEdit2: TSpinEdit;
Taste3: TTaste;
Memo1:TMemo;
Prozedur OnRead(Sender: TObject; ReadBytes: Array of Byte );
Prozedur Button1Click (Sender: TObject);
Prozedur Button2Click(Sender: TObject);
Prozedur FormDestroy (Sender: TObject);
Prozedur Button3Click (Sender: TObject);
Privatgelände
(Private Erklärungen)
Anschluss: TComPort;
Öffentlichkeit
(Öffentliche Erklärungen)
Ende;

Var
Formular1: TForm1;
Zahl: ganze Zahl;
Implementierung

Prozedur TForm1.Button1Click(Sender: TObject);
Start
Port:= TComPort.Create(SpinEdit1.Value, br115200); // Verbindung herstellen
Port.OnRead:= OnRead; // Erstelle einen Stream zum Lesen der empfangenen Daten
Button2.Enabled:= true ; //Schaltfläche zum Schließen der Verbindung aktivieren
Ende;

Prozedur TForm1.Button2Click(Sender: TObject);
Start
Portfrei; // Verbindung schließen
Button2.Enabled:= false ; //Schaltfläche deaktivieren
Ende;

Prozedur TForm1.Button3Click(Sender: TObject);
Start
wenn Button2.Enabled dann Port.Write();
Ende;

Prozedur TForm1.FormDestroy(Sender: TObject);
Start
wenn Button2.Enabled dann
Portfrei;
Ende;

Prozedur TForm1.OnRead(Sender: TObject; ReadBytes: Array von Byte );
Var
i: ganze Zahl;
Start
für i:= Low(ReadBytes) bis High(ReadBytes) tun //das Array der empfangenen Bytes durchlaufen
Start
Memo1.Text:= Memo1.Text + "." +InttoHex(ReadBytes[i],2); //Füge seinen HEX-Wert zum Fenster hinzu
inkl. (Zahl); // Anzahl der empfangenen Bytes zählen
Ende;
wenn num > 10 dann beginnen
Memo1.Lines.Add("" ); // Übertragungsleitung
Zahl:=0;
Ende;
Ende;

Wir starten, bauen eine Verbindung auf, senden Bytes:

So ist unser einfachstes Terminal bereit, mit dem einfachsten USB-Gerät zu arbeiten.

Wie Sie sehen können, handelt es sich beim Lesen und Schreiben um dynamische Byte-Arrays.

Durch die Verarbeitung der empfangenen Informationen ist es möglich, das für die aktuelle Aufgabe geeignete notwendige Austauschprotokoll zu erstellen.

gehören 18f2455
--
enable_digital_io()
--
alias Taste ist pin_B7
pin_B7_direction = Eingang
--
--
schließen Sie usb_serial ein
--
usb_serial_init()
Var-Byte CH
Var-Byte ich -- zweite Variable deklarieren
ewige Schleife-- Hauptschleife
usb_serial_flush()
wenn(usb_serial_read(ch)) dann-- Wenn das Byte empfangen wird, führen Sie die erforderlichen Aktionen aus
Fall ch von - Iterieren Sie über die Bytenummer
0 : usb_serial_data = 0xff
1 : usb_serial_data = Schaltfläche - Schaltflächenstatus senden
ANDERNFALLS Block-- wenn etwas anderes empfangen wird
zum 16 verwenden ich Schleife-- 10 Byte Daten senden
usb_serial_data = ch +i -- ch bis ch+15
Endschleife
Endblock
Endfall
Ende wenn
Endschleife

Zusatzfunktionen

Wenn Sie dort aufhören, erhalten Sie einen regulären Artikel mit detaillierte Beschreibung ein beispiel für die nutzung der bibliothek, von denen es genug im web gibt. Daher füge ich noch ein paar vertiefende Informationen hinzu.

Vereinfachen Sie das Senden von Daten

Das Senden von Informationen Byte für Byte ist nicht immer bequem. Die Bibliothek kann sehr nützlich sein drucken. Es enthält Prozeduren zum Senden von Daten aller möglichen Längen in allen möglichen Formaten: Byte, Hex, Dez, Bin, Boolean, was die Ausgabe von Daten im Programm vereinfachen kann.
> Druck einfügen
...
varword Daten
print_dword_hex (usb_serial_data , data )

Die Namen aller Befehle finden Sie in der Bibliotheksdatei.

Warten auf Verbindung zum PC

Wenn vor dem Starten des Hauptzyklus des Mikrocontrollers zuerst eine Verbindung zum PC hergestellt werden muss, können Sie die Zeilen davor hinzufügen
während(usb_cdc_line_status() == 0x00) Schleife
Endschleife

Binden Sie die Portnummer an das Gerät

Wenn Sie alles so lassen wie es ist, vergibt das System für jede neue Verbindung die erste freie Portnummer. Und das heißt, man muss es im Auge behalten.
Um dies zu verhindern, müssen Sie dem Gerät einen eindeutigen Seriennummerwert zuweisen, bevor Sie die USB-Bibliothek anschließen:
Die Nummer kann beliebig lang sein und verschiedene Zeichen enthalten.
konstantes Byte USB_STRING3=
{
24 , -- Array-Länge
0x03 , --bDescriptorType
"0" , 0x00 ,
"1" , 0x00 ,
"2" , 0x00 ,
"3" , 0x00 ,
"4" , 0x00 ,
"5" , 0x00 ,
"6" , 0x00 ,
"7" , 0x00 ,
"8" , 0x00 ,
"9" , 0x00 ,
"X" 0x00
}

Ändern Sie den Gerätenamen in Ihren eigenen

Sie können den im System sichtbaren Namen des Geräts ändern, bevor Sie die Treiber installieren, indem Sie ein Array mit dem Namen wie der Seriennummer deklarieren. Dies muss vor dem Anschließen der USB-Bibliothek erfolgen.
konstantes Byte USB_STRING2=
{
28 , --
0x03 , --bDescriptorType
"D", 0x00 ,
"e", 0x00 ,
"m", 0x00 ,
"Ö", 0x00 ,
" " , 0x00 ,
"B", 0x00 ,
"Ö", 0x00 ,
"a", 0x00 ,
"r", 0x00 ,
"d", 0x00 ,
" " , 0x00 ,
"=" , 0x00 ,
")" 0x00
}

Aber leider ändert das Gerät nach der Installation der Treiber seinen Namen in den in der .inf-Datei angegebenen Namen, also werden wir den Namen auch dort ändern


DESCRIPTION="Demo-CDC"

Wir organisieren die automatische Verbindung des Geräts

Leider gibt es keine direkten Wege, um diese Aufgabe zu erledigen, also müssen Sie sich etwas einfallen lassen.

Zunächst müssen Sie Ihrem Gerät einen eindeutigen Hersteller- und Produktwert zuweisen, um es unter Hunderten anderer Standard-CDC-Firmware leicht identifizieren zu können.
VID und PID werden für Geld ausgegeben, gehen wir also den Weg der Chinesen: Nehmen wir uns ruhig selbst offensichtlich freie Werte.

Firmware:
Zwei Variablen müssen in der Firmware deklariert werden, bevor die USB-Bibliothek angeschlossen wird

konstantes Wort USB_SERIAL_PRODUCT_ID = 0xFF10
konstantes Wort USB_SERIAL_VENDOR_ID = 0xFF10

Anstelle von FF10 können Sie zwei beliebige Wörter (2 Bytes) einfügen. Das Endergebnis ist im beigefügten Archiv enthalten.

Treiber:
Da die Treiber nicht für unsere Kombination aus VID und PID ausgelegt sind, werden wir unsere Werte manuell in die .inf-Datei einfügen:


%DESCRIPTION%=Treiberinstallation, USB\VID_FF10&PID_FF10


%DESCRIPTION%=Treiberinstallation, USB\VID_FF10&PID_FF10

Sanft:
Um Verbindungs-/Trennungsereignisse von Geräten abzufangen, verbinden wir die ComponentUSB-Bibliothek. Ich halte es nicht für nötig, jede Zeile zu erklären: Alle Änderungen sind im beigefügten Projekt ersichtlich.

Ergebnis

Auf dem Screenshot ist es schwer zu erkennen, aber der Senden-Button ist nur aktiv, wenn ein angeschlossenes Gerät vorhanden ist, und das Programm sendet alle 50 ms eine Anfrage, um den Status des Buttons zu erhalten (was jedoch falsch ist, da der Tastendruck verarbeitet werden sollte auf MK).

Wie Sie sehen, ist es nicht die schwierigste Aufgabe, den Datenaustausch zwischen MK und PC über USB zu organisieren. Die resultierende Verbindung kann nicht nur für Endzwecke verwendet werden, sondern eignet sich auch zum Debuggen eines Programms. Schließlich ist das Senden der Ergebnisse von Berechnungen, der aktuellen Zustände von Registern und Variablen an einen Computer viel klarer als das Blinken eines LED-Paares im Morsecode.

Und schließlich rate ich Ihnen, sich umzusehen Quelle Stimmungslampen. Dort finden Sie eine ziemlich gute Möglichkeit, empfangene Daten zu verarbeiten, um ein bequemes Austauschprotokoll zu organisieren.

Es reicht jedoch nicht aus, das Gerät nur physisch mit dem Computer zu verbinden, Sie müssen auch den Datenaustausch zwischen ihnen herstellen. Wie wähle ich einen Port aus und organisiere eine Verbindung? Vor einigen Jahren war die Standardlösung die Verwendung eines COM-Ports. Übrigens verbauen diverse Spezialisten immer noch 8, 16 oder sogar 32 COM-Ports auf Industrierechnern (es gibt eine ganze Kategorie unterschiedlicher PCI-Erweiterungskarten für serielle Ports, Controller etc.). Wer also mehrere externe Geräte mit RS-232-Schnittstelle anschließen will, braucht unter Umständen teure Adapter und exotische Erweiterungsplatinen, die nach alter Tradition wochenlang auf Dampfschiffen nach Russland segeln. Übrigens kann der Name eines gewöhnlichen Adapters "DB9m / DB25f-Adapter" einen Computergeschäftsleiter nur irritieren.

Was ist ein HID-Gerät?

Mittlerweile werden fast alle Geräte über eine USB-Schnittstelle mit einem Computer verbunden. Daher haben viele neue PCs überhaupt keinen COM-Port.

USB-Schnittstelle - eine typische Lösung zum Koppeln eines neuen externes Gerät mit einem Computer, genauer gesagt, handelt es sich um eine HID-Schnittstelle, die auf dem USB 1.1-Protokoll basiert.

Obwohl viele Leute denken, dass die HID-Schnittstelle (Human Interface Device) ausschließlich für Tastatur, Maus und Joystick gedacht ist, eignet sie sich für viele Lösungen im Zusammenhang mit der Anbindung externer Geräte und eines Computers.

Wenn der Benutzer einen Datenaustausch mit niedriger Geschwindigkeit (bis zu 64 kbps) durchführen muss und gleichzeitig die Zeit für die langwierige Entwicklung seiner eigenen Treiber reduzieren möchte, ist HID für ihn gut geeignet. Die Ausgabe wird einfach und ruhig sein moderne Lösung basierend auf einer Standard-USB-Softwareschnittstelle mit garantierter Unterstützung aller gängigen Softwareplattformen.

HID-Geräteeigenschaften

Aus Sicht der Organisation des Software-Supports für ein HID-Gerät sieht alles recht attraktiv aus: Für die Arbeit unter Windows können Sie schnell verständlichen kompakten Code auf der Grundlage vorgefertigter bewährter Algorithmen erstellen. In diesem Fall hat der Entwickler genügend Zeit, sein eigenes Datenaustauschprotokoll der obersten Ebene zu implementieren, da die notwendige Abstraktionsebene bereits durch das HID-Protokoll organisiert ist (siehe Tabelle). Außerdem ist es für einen Programmierer einfach, ein geschriebenes Austauschprotokoll zu debuggen (natürlich, wenn es ein funktionierendes HID-Gerät gibt) – aufgrund der relativen Starrheit des Protokolls selbst reicht es aus, einfach ein Programm zur Unterstützung des Geräts zu entwickeln durch einen Computer. Würde trotzdem! Der Schöpfer des HID-Geräts hat bereits viel Arbeit geleistet.

Herstellen des Datenaustauschs zwischen einem HID-Gerät und einem Computer

Um die Interaktion eines HID-Geräts mit einem Computer zu beschreiben, verwenden wir den Begriff „Host“. In diesem Fall bezieht es sich auf ein Steuergerät in der allgemeinen physikalischen Architektur der Kommunikation über das USB-Protokoll. Alle Ports in einem Computer sind also Hosts. Sie können verschiedene USB-Geräte daran anschließen (Flash-Laufwerke, Mäuse, Webcams, Kameras usw.), die keinen Host haben. Der Host bietet Erkennung, Verbindung, Trennung, Gerätekonfiguration sowie Statistikerfassung und Energieverwaltung.

Das HID-Gerät selbst kann die Abfragefrequenz einstellen, während der das Vorhandensein neuer Daten festgestellt wird. Das bedeutet, dass der Programmierer dem System selbst auf einem so niedrigen Niveau vertrauen kann, da die Abfragerate und andere Kommunikationsparameter im HID-Gerätesteuerungsprogramm voreingestellt werden müssen. Darin unterscheidet sich das HID-Protokoll von der allgemeinen Beschreibung von USB 1.1 oder USB 2.0, die keine strengen Anforderungen an die Organisation des Protokolls stellen. Bei bestimmten Aufgaben, die ein hohes Maß an Sicherheit erfordern, kann es jedoch ziemlich schwierig sein, zyklische Abfragen loszuwerden, wenn ständig fast dieselben Datenblöcke übertragen werden.

Funktionen zum Programmieren von HID-Geräten

HID-Geräte haben spezielle Deskriptoren. Wenn der Host feststellt, dass das Gerät zur HID-Klasse gehört, überträgt er die Kontrolle darüber an den entsprechenden Treiber. Es wird davon ausgegangen, dass der weitere Datenaustausch unter seiner Führung erfolgt.

Unter Windows wird der Zugriff auf HID-Geräte gehandhabt von Systemdienst HidServ. Weitere Einzelheiten zu den Funktionen von Anfragen an HID-Geräte und andere Merkmale der Arbeit mit dem HID-Treiber sind in der Arbeit von P. V. Agurov „USB-Schnittstelle. Die Praxis des Benutzens und Programmierens“ (St. Petersburg: BHV-Petersburg, 2005).

Programmieren von HID-Geräten auf « Höchststufe»

Das harte Leben "angewandter" Programmierer, die an Pascal arbeiten, wird durch das bewährte HID-Modul erleichtert. PAS, die Shell für versteckt. dll (Hid User Library - wie in den Dateieigenschaften angegeben). Die Kommentare zu der Datei besagen, dass sie auf den Modulen hidsdi.h und hidpi.h der Microsoft Corporation basiert. Und die HID-Datei selbst. PAS ist Teil des JEDI()-Pakets.

Um mit einem HID-Gerät in der Umgebung von Delphi für win32 zu arbeiten, wird die TJvHidDeviceController-Komponente verwendet, die ein praktischer globaler Manager für den Zugriff auf HID-Geräte ist. Und bereits auf seiner Grundlage können Sie eine Objektinstanz für die Arbeit mit einem bestimmten Gerät erhalten.

Haupteigenschaften und Ereignisse der TJvHidDeviceController-Komponente

Betrachten wir die TJvHidDeviceController-Komponente genauer. Das OnArrival-Ereignis wird ausgelöst, wenn ein HID-Gerät beim System ankommt (eine Verbindung herstellt). Der Zugriff auf das Gerät wird im Handler dieses Ereignisses über eine Instanz der TJvHidDevice-Klasse bereitgestellt. Das einfache Event OnDeviceChange reagiert auf eine Zustandsänderung des Geräts, es signalisiert lediglich Änderungen im System. Das OnDeviceData-Ereignis wird ausgelöst, wenn Daten von einem der HID-Geräte eintreffen, und übergibt Folgendes an den Handler: HidDev: TJvHidDevice; - das Gerät, von dem die Daten empfangen wurden;

Das OnDeviceDataError-Ereignis benachrichtigt einen Datenübertragungsfehler, indem HidDev-Parameter an die Verarbeitungsprozedur übergeben werden: TJvHidDevice; - HID-Gerät und Fehler: DWORD; - Fehlercode. Das OnDeviceUnplug-Ereignis benachrichtigt Sie, dass ein Gerät aus der Liste der auf dem System installierten Geräte entfernt wurde. Die Typen von Eventhandlern bei Plug und Unplug sind gleich (im Quelltext: TJvHidUnplugEvent = TJvHidPlugEvent). Ein Objekt der TJvHidDevice-Klasse, das dem HID-Gerät entspricht, wird an den Handler übergeben.

Um die im System verfügbaren HID-Geräte durch Aufruf der Methode Enumerate sequentiell aufzuzählen, ist das Event OnEnumerate vorgesehen, d.h. im Eventhandler werden die gefundenen Geräte sequentiell als Objekte übertragen. Dieses Ereignis wird zwangsweise durch die Enumerate-Methode ausgelöst, die verwendet wird, um vorhandene HID-Geräte durch den Handler zu „leiten“, beispielsweise wenn der Zustand von HID-Geräten geprüft wird, die vom Host (Computer) initiiert wurden.

Das OnRemoval-Ereignis wird ausgelöst, wenn das Gerät physisch aus dem System entfernt wird, und hat denselben TJvHidUnplugEvent-Handlertyp wie OnDeviceUnplug. Die Funktion CountByProductName gibt die Anzahl der Geräte zurück, die mit dem im Argument angegebenen Produktnamen übereinstimmen, und CountByVendorName gibt die Anzahl der im Argument angegebenen Anbieternamen zurück.

Haupteigenschaften und Ereignisse der TJvHidDevice-Klasse

Die TJvHidDevice-Klasse ist eine virtuelle Darstellung eines einzelnen HID-Geräts. Ein neues Objekt dieser Klasse kann, wie bereits erwähnt, aus dem OnArrival- oder OnEnumerate-Event bezogen werden. Die Funktionalität der Klassen TJvHidDeviceController und TJvHidDevice ist teilweise dupliziert, da die erste von ihnen ein gemeinsames Toolkit für die Arbeit mit einer Reihe von im System verfügbaren HID-Geräten und einen Mechanismus für den Zugriff auf eines von ihnen integriert. Ein Gerät kann anhand seiner Eigenschaften SerialNumber, ProductName und VendorName eindeutig identifiziert werden. Mit Hilfe eines solchen Objekts können Sie sich über das OnData-Ereignis Informationen über das Eintreffen von Daten holen. Daten werden über die WriteFile-Methode (im engeren Sinne über eine Funktion) gesendet. WriteFile ist ein Wrapper Systemfunktion WriteFile(kernel32).

Um zu steuern, dass das Gerät entfernt wird, sollten Sie dem OnUnplug-Ereignis einen eigenen Handler zuweisen. Bevor Sie den Datenaustausch mit einem HID-Gerät starten, müssen Sie sicherstellen, dass ein solcher Austausch mit HasReadWriteAccess möglich ist. Diese Klasse hat sogar ein separates OnDataError-Event für das Auftreten eines Datenaustauschfehlers.

Schauen wir uns nun Codefragmente aus einem "Live"-Projekt an, das eine Test-Client-Anwendung zum Organisieren des Datenaustauschs mit einem nicht standardmäßigen Gerät implementiert - HID-basierte Plastikchipkarten. Im Ringen um Realismus nahm sich der Autor die Freiheit, „zusätzliche“ technologische Code-Bindings nicht aus den Listings zu streichen.

Die ScanDevices-Methode (Listing 1) soll den Prozess des Durchsuchens des Systems nach dem erforderlichen HID-Gerät einleiten. Der größte Teil des Codes, mit Ausnahme des Aufrufs der Enumerate-Methode, ist optional und bietet Anwendungsflexibilität, sodass Sie beispielsweise demselben Testprogramm die Möglichkeit hinzufügen können, an einer Nicht-HID-Schnittstelle zu arbeiten. Die AddError-Methode gibt Debugging-Informationen im Fenster aus, während das Programm ausgeführt wird.

Listing 2 zeigt den OnEnumerate-Eventhandler zum Auffinden des benötigten externen Geräts. Der Einfachheit halber gehen wir davon aus, dass das Programm nur mit einem Gerät des benötigten Typs arbeiten kann.

Bevor wir über die weitere Umsetzung des Projekts nachdenken, sollten wir ein wenig über das akzeptierte Datenaustauschformat der obersten Ebene sprechen, dh über die Struktur, die als Vermittler zwischen den Methoden zum Empfangen und Übertragen von Daten und der zu lösenden spezifischen angewandten Aufgabe dienen soll . Tatsache ist, dass hier dem Entwickler die Möglichkeit gegeben wird, seine kreativen Fähigkeiten zu verwirklichen. Oder besser gesagt Entwickler, denn der Prozess der Erstellung eines neuen Protokolls ist sehr oft zweiseitig, und die erste Geige spielt derjenige, der es schwieriger findet, den Austauschalgorithmus zu implementieren. Im Allgemeinen ist es unabhängig vom Austauschprotokoll immer schön, jede Softwareentität so visuell und autark wie möglich zu gestalten, selbst auf Kosten einiger allgemein akzeptierter Traditionen. Denn die beste Lösung ist die, die in kurzer Zeit mit minimalem Bezug umgesetzt werden kann Softwareumgebung und mit tolle Möglichkeiten weitere Entwicklung. Basierend auf diesen Prinzipien wurde ein Austauschprotokoll der obersten Ebene erstellt, bei dem das Hauptkonzept „Befehl“ ist. Listing 3 zeigt, wie sehr der Autor String-Daten liebt, die ihn mehr als einmal beim Debuggen gerettet haben Softwaremodule. Wie schön, dass wir überhaupt einen String-Typ haben! Alle Protokollbefehle sind in Kategorien (Klassen) eingeteilt, innerhalb derer es einen Befehlscode gibt, der seinen Zweck eindeutig charakterisiert. Der Parameter edParam wird verwendet, um Daten an das Gerät zu senden, und der Parameter edAnswerData enthält die vom Gerät empfangenen Daten. Der Zeichenfolgentyp der beschriebenen Datensatzmitglieder ermöglicht es Ihnen, Daten im HEX-Zeichenfolgenformat frei und visuell zu manipulieren. Und was am angenehmsten ist, das Format des beschriebenen Datensatzes steht ideologisch irgendwo in der Mitte zwischen seinem direkten Zweck und verschiedenen Formen seiner Darstellung (INI, HEX, XML usw.)

Die Befehlsausführung, also das Senden von Daten an das Gerät, erfolgt über das Senden von Datenpaketen mit einer Länge von 8 Byte (Listing 4). Diese Länge ist nicht die einzige Entscheidung, diese Wahl wird durch die Anforderungen des Protokolls der oberen Schicht diktiert und kann in jedem spezifischen Fall unterschiedlich sein. Das nennt man Geschmackssache. Das seltsame IsUSBMode-Flag in der ExecuteCommand-Methode (Listing 5 in PC Disk World) erinnert daran, dass wir statt mit USB möglicherweise einen COM-Port oder eine andere Schnittstelle verwenden müssen. Am Anfang der gesendeten Datengruppe wird eine Sync-Sequenz eines willkürlich gewählten Formats (z. B. 3E3E3E2B) an das Gerät übertragen, die das Gerät darüber informiert, dass es vollständig legale Daten am Eingang hat. Ich möchte Sie daran erinnern, dass wir in diesem Fall nicht so sehr über HID sprechen, sondern über ein spezifisches Top-Level-Protokoll, das ideologisch von der Hardware getrennt ist und zur Lösung spezieller Anwendungsprobleme entwickelt wurde.

Im GetDataExecutor-Handler der vom Gerät empfangenen Daten (Paket von 8 Bytes) wurden die zunächst verarbeiteten Daten mit einem eigens erstellten OnNewInputData-Event unter Angabe ihrer alten und neuen Werte zur weiteren Verarbeitung übergeben (Listing 6 auf der „World der PC-Festplatte"). Somit werden die Ereignisse des Eintreffens von Rohdaten und eine Anzeige der weiteren Verarbeitung entkoppelt, was es ermöglicht, einen bestimmten Warnalgorithmus in einem frühen Stadium für fehlerhafte, wiederholte oder unnötige Eingabeinformationen hinzuzufügen.

Die hier vorgestellten Beispiele für die Arbeit mit einem HID-Gerät veranschaulichen die allgemeine Idee des Artikels - die relative Einfachheit der Programmierung von nicht standardmäßigen HID-Geräten mit Delphi-Tools.

Der USB-Bus (Universal Serial Bus – Universal Serial Bus) erschien am 15. Januar 1996 mit der Genehmigung der ersten Version des Standards durch Intel, DEC, IBM, NEC, Northen Telecom und Compaq.

Das Hauptziel des Standards, der seinen Entwicklern vorgelegt wird, ist es, Benutzern zu ermöglichen, im Plug&Play-Modus mit Peripheriegeräten zu arbeiten. Das bedeutet, dass es möglich sein muss, das Gerät an einen laufenden Computer anzuschließen, es sofort nach dem Anschließen automatisch zu erkennen und dann die passenden Treiber zu installieren. Außerdem ist es wünschenswert, Geräte mit geringem Stromverbrauch über den Bus selbst mit Strom zu versorgen. Die Busgeschwindigkeit sollte für die allermeisten Peripheriegeräte ausreichen. Der USB-Controller sollte unabhängig von der Anzahl der an den Bus angeschlossenen Geräte nur einen Interrupt nehmen, das heißt, um das Problem des Mangels an Ressourcen auf den internen Bussen eines IBM-PC-kompatiblen Computers zu lösen.

Fast alle Aufgaben wurden im USB-Standard gelöst, und im Frühjahr 1997 tauchten Computer auf, die mit Anschlüssen für ausgestattet waren USB-Anschlüsse Geräte. Mittlerweile wird USB von Herstellern von Computerperipheriegeräten so aktiv implementiert, dass es beispielsweise im iMAC-Computer von Apple Computers nur noch USB als externen Bus gibt.

USB-Fähigkeiten 1.0 sind wie folgt:

1. Ho(volle Geschwindigkeit) - 12 Mb es/Mit;

2. maximale Länge Kabel für Hochgeschwindigkeitsaustausch - 5 Meter;

3. niedrige Datenübertragungsrate (niedrige Geschwindigkeit) - 1,5 MB es/Mit;

4. maximale Kabellänge für niedrigen Wechselkurs - 3 Meter;

5. die maximale Anzahl der angeschlossenen Geräte beträgt 127;

6. möglich gleichzeitige Verbindung Geräte mit unterschiedlichen Wechselkursen;

8. maximale Stromaufnahme pro Gerät - 500 mA.

Daher ist es ratsam, fast alle Peripheriegeräte mit Ausnahme von digitalen Videokameras und Hochgeschwindigkeitsfestplatten an USB 1.0 anzuschließen. Diese Schnittstelle ist besonders nützlich, um häufig verbundene/getrennte Geräte wie Digitalkameras anzuschließen.
Die Fähigkeit, nur zwei Datenraten zu verwenden, schränkt die Anwendbarkeit des Busses ein, reduziert jedoch die Anzahl der Schnittstellenleitungen erheblich und vereinfacht die Hardwareimplementierung.
Die Stromversorgung direkt über USB ist nur für Geräte mit geringem Stromverbrauch wie Tastaturen, Mäuse, Joysticks usw. möglich.

USB-Signale werden über ein 4-adriges Kabel übertragen, wie in der folgenden Abbildung schematisch dargestellt:

Abbildung 2.6.1 - USB-Signalleitungen

Hier ist GND ein gemeinsamer Drahtkreis zur Stromversorgung von Peripheriegeräten, Vbus - +5 V auch für Stromkreise. Der D+-Bus dient zum Übertragen von Daten auf dem Bus, und der D-Bus dient zum Empfangen von Daten.
Das Kabel zur Unterstützung der vollen Busgeschwindigkeit (Full-Speed) ist als verdrilltes Paar ausgeführt, durch eine Abschirmung geschützt und kann auch für den Betrieb im Modus mit minimaler Geschwindigkeit (Low-Speed) verwendet werden. Das Kabel für den Betrieb nur mit minimaler Geschwindigkeit (z. B. zum Anschluss einer Maus) kann beliebig und ungeschirmt sein.
Die zum Anschließen von Peripheriegeräten verwendeten Anschlüsse sind in Serien unterteilt: Die Anschlüsse der „A“-Serie (männlich und weiblich) dienen nur zum Anschließen an eine Quelle, wie z Peripheriegerät.

USB-Anschlüsse haben die folgende in Tabelle 2.6.1 gezeigte Pin-Nummerierung.

Tabelle 2.6.1 - Zweck und Kennzeichnung von USB-Kontakten

1999 dasselbe Konsortium Computerunternehmen, der die Entwicklung der ersten Version des USB-Busstandards initiierte, begann aktiv mit der Entwicklung der Version 2.0 von USB, die sich durch die Einführung eines zusätzlichen Hochgeschwindigkeitsmodus (Hi-Speed) auszeichnet. Die Busbandbreite wurde um das 40-fache auf bis zu 480 Mbit/s erhöht, wodurch die Übertragung von Videodaten über USB möglich wurde.
Die Kompatibilität aller zuvor veröffentlichten Peripheriegeräte und Hochgeschwindigkeitskabel bleibt vollständig erhalten. Der Controller des 2.0-Standards ist bereits in die Systemlogik programmierbarer Geräte integriert (z. B. Hauptplatine persönlicher Computer).

In 2008 von Intel, Microsoft, Hewlett-Packard, Texas Instruments, NEC und NXP Semiconductors haben die USB 3.0-Spezifikation erstellt. In der USB 3.0-Spezifikation sind die Anschlüsse und Kabel des aktualisierten Standards physisch und funktional mit USB 2.0 kompatibel, aber zusätzlich zu den vier Kommunikationsleitungen wurden vier weitere hinzugefügt. Allerdings neue Kontakte rein USB-Anschlüsse 3.0 befinden sich getrennt von den alten auf einer anderen Kontaktreihe. Die USB 3.0-Spezifikation erhöht die maximale Datenübertragungsrate auf 5 Gbit/s – eine Größenordnung höher als die 480 Mbit/s, die USB 2.0 bieten kann. Darüber hinaus wurde der maximale Strom von 500 mA auf 900 mA pro Gerät erhöht, wodurch Sie einige Geräte mit Strom versorgen können, die zuvor eine separate Stromversorgung benötigten.

Angenommen, Sie haben ein USB-Gerät entwickelt, mit dem Sie auf einem Computer arbeiten möchten. Dies kann auf mindestens zwei Arten erreicht werden:

1. Entwicklung eines voll funktionsfähigen Betriebssystemtreibers;

2. Verwendung einer USB-Schnittstelle einer besonderen Klasse - Geräte, die als HID-Geräte (Human Interface Device) bezeichnet werden.

Die erste Methode ist universell: Wenn Sie über ausreichende Kenntnisse im Bereich des Schreibens von Treibern verfügen, können Sie sie so programmieren, dass sie mit jedem Gerät mit jeder von USB unterstützten Geschwindigkeit funktioniert. Aber das ist eine ziemlich schwierige Aufgabe.

Der zweite Weg ist wie folgt. Es gibt eine Schnittstelle, die von modernen Betriebssystemen für Computer-Mensch-Interaktionsgeräte oder HID-Geräte unterstützt wird, wie zum Beispiel:

1. Tastaturen, Mäuse, Joysticks;

2. verschiedene Sensoren und Leser;

3. Wildlenkung und Pedale;

4. Knöpfe, Schalter, Regler.

Jedes derartige Gerät wird automatisch vom System erkannt, wenn es die Anforderungen für HID-Geräte erfüllt, und es müssen keine speziellen Treiber geschrieben werden. Außerdem ist das Programmieren normalerweise viel einfacher als das Schreiben eines benutzerdefinierten Gerätetreibers. Leider hat das Verfahren einen entscheidenden Nachteil: Die Geschwindigkeit des Informationsaustausches mit dem HID-Gerät ist sehr begrenzt und beträgt maximal 64 kB/s.

Grundsätzlich ist es auf Basis der HID-Technologie möglich, die Interaktion mit jedem Gerät zu organisieren, auch wenn es sich nicht im engeren Sinne um ein Schnittstellengerät zwischen Mensch und Computer handelt. Dies eliminiert die zeitaufwändige Entwicklung eines einzigartigen Gerätetreibers und spart Zeit bei der Entwicklung eines neuen USB-Geräts. Auf der Host-Seite wird der Austausch mit dem Gerät von einem Standard-HID-Treiber verwaltet, der in der Betriebssystem-Distribution enthalten ist. Sie müssen nur von der Geräteseite aus ausführen Mindestanforderungen USB-HID-Protokoll.

Es ist erwähnenswert, dass viele USB-Geräte, die auf den ersten Blick nicht unter die Definition von Geräten für die menschliche Interaktion fallen, noch logischer als HID-Geräte zu implementieren sind. Dieses Phänomen tritt häufig im Bereich der Produktionsanlagen auf, die in letzter Zeit eine massive Einführung von USB-Technologien erfahren haben. Betrachten Sie zum Beispiel ein Labornetzteil mit der Möglichkeit, die Parameter seiner Ausgangssignale von einem Computer aus über eine USB-Schnittstelle einzustellen. Ohne Zweifel ist die Energiequelle selbst kein Mittel zur Interaktion mit einer Person. In diesem Fall duplizieren die über eine USB-Verbindung implementierten Funktionen jedoch die Tastatur, Bedienelemente und Anzeigen, die auf dem Gerät selbst installiert sind. Und diese Kontrollen fallen einfach unter die Definition von HID. Dementsprechend ist die Stromversorgung mit diesen USB-Funktionen am logischsten als HID-Gerät organisiert.

Im betrachteten Beispiel z normale Operation eine niedrige Datenübertragungsrate reicht aus, in anderen Fällen können Geräte sehr hohe Anforderungen an die Wechselkurse stellen. Die niedrige Übertragungsrate ist die Hauptbeschränkung des HID-Gerätedesigns, was im Vergleich zu 12 Mbit/s der vollen Geschwindigkeit des USB 1.0-Busses wie ein großer Nachteil der HID-Technologie bei der Auswahl einer bestimmten USB-Implementierung aussieht. Für viele Kommunikationsaufgaben reicht diese Geschwindigkeit jedoch völlig aus, und die HID-Architektur nimmt als spezialisiertes Werkzeug einen würdigen Platz unter den Möglichkeiten ein, den Datenaustausch zu organisieren.

Es gibt zwei Arten von HID-Geräten: teilnehmende (booten) und nicht teilnehmende. Bootstrap Computer. Das auffälligste Beispiel für ein bootfähiges USB-HID-Gerät ist die Tastatur, die mit dem Start des Computers zu arbeiten beginnt.

Bei der Entwicklung eines HID-Geräts müssen die folgenden Anforderungen der Spezifikation erfüllt werden:

1. HID-Gerät mit voller Geschwindigkeit kann 64000 Bytes pro Sekunde oder 64 Bytes alle 1 ms übertragen; Ein HID-Gerät mit niedriger Geschwindigkeit kann bis zu 800 Bytes pro Sekunde oder 8 Bytes alle 10 ms übertragen.

2. Das HID-Gerät kann seine Abfragerate bestimmen, um festzustellen, ob es neue Daten zu übertragen hat.

3. Der Datenaustausch mit dem HID-Gerät erfolgt über eine spezielle Struktur, die als Bericht (Report) bezeichnet wird. Jeder definierte Bericht kann bis zu 65535 Byte Daten enthalten. Die Berichtsstruktur ist sehr flexibel organisiert, sodass Sie jedes Datenübertragungsformat beschreiben können. Damit ein bestimmtes Berichtsformat dem Host bekannt wird, muss der Mikrocontroller eine spezielle Beschreibung enthalten – einen Berichtsdeskriptor.

Die USB-Kommunikation wird auf verschiedene Arten direkt auf dem Mikrocontroller implementiert:

1. Verwendung eines Controllers mit Hardwareunterstützung, wie z. B. AT90USB*, von atmega;

2. Verwendung der Software-Emulation der USB-Schnittstelle auf einem beliebigen Mikrocontroller.

Für die Softwareimplementierung gibt es derzeit eine Reihe fertiger Lösungen für verschiedene Familien von Mikrocontrollern. Zum AVR-Mikrocontroller B. Atmega8 ist es möglich, die folgenden freien C-Bibliotheken zu verwenden:

Beide sind ziemlich einfach zu bedienen, bieten eine vollständige Emulation von USB 1.1-Low-Speed-Geräten mit Ausnahme der Behandlung von Kommunikationsfehlern und Elektrische Eigenschaften und laufen auf fast allen AVR-Controllern mit mindestens 2 Kilobyte Flash-Speicher, 128 Byte RAM und einer Frequenz von 12 bis 20 MHz.

Zum Schreiben von Bewerbungen mit Unterstützung Windows-USB HID-Geräte benötigen die hid*-Header-Dateien, die im WDK (Windows Driver Kit) enthalten sind, oder Sie können die kostenlose hidlibrary-Bibliothek oder ähnliches verwenden.

Also hinein Allgemeiner Fall Die USB-Programmierung ist eine ziemlich komplexe Aufgabe, die einen speziellen Mikrocontroller mit Hardwareunterstützung und das Schreiben eines Betriebssystemtreibers erfordert. In der Praxis ist es jedoch möglich, bei der Entwicklung von Geräten eine viel einfachere HID-Schnittstelle zu verwenden - Geräte, deren Unterstützung auf der Ebene eines Standardsystemtreibers implementiert ist, und die Programmierung wird mithilfe vorhandener Funktionsbibliotheken vereinfacht.

Testfragen

  1. Was ist der Unterschied zwischen den D- und GND-Leitungen bei USB? Warum können Sie nicht ein gemeinsames Kabel für Strom und Signal verwenden?
  2. Wie viele USB-Geschwindigkeitsmodi gibt es heute (einschließlich Version 3.0)?
  3. Was ist ein HID-Gerät? Warum müssen sie keine Treiber schreiben, um in modernen Betriebssystemen zu funktionieren?
  4. Ist eine Umsetzung möglich USB-Geräte Verwenden Sie einen Mikroprozessor ohne integrierte Schnittstellenunterstützung?
  5. Was sind die Hauptunterschiede zwischen USB 3.0 und früheren Versionen?