USB-HID Tastatur mit Atmel-Prozessor
In diesem Projekt emuliert ein Atmel-Prozessor ein HID-Device für den USB-Port. Auslöser war die Notwendigkeit
für eine Mini-Tastatur mit nur 2 Tasten die an einem Tablet benutzt werden kann.
Der Atmel-Prozessor wird per Software zu einem low-speed USB Device programmiert. Es wird keine spezielle
USB-Hardware benötigt.
Human Interface Device ist eine USB-Geräteklasse für Tastatur, Maus und ähnliches. Die Treiber
dafür sind fester Bestandteil von Windows und die Geräte sind dadurch direkt einsatzbereit.
Funktion und Ergebnis
Das Gerät funktioniert ausgezeichnet und problemlos:)
Direkt nach dem Anstecken am PC wird es vom Gerätemanager als HID-Device erkannt. Die Tasten verhalten sich exakt wie
eine ganz normale Tastatur, in allen Situationen und Programmen. Das gleiche gilt für den Betrieb an einem Android-Tablet.
Das Tablet muss aber USB-OTG unterstützen und man benötigt einen entsprechenden HW-Adapter.
V-USB
Die Basis ist das Software-Paket
V-USB von Objective Development Software.
Das Paket ist ebenfalls auf
GitHub verfügbar.
V-USB emuliert eine USB-Schnittstelle in Software. Das USB-Signaltiming ist sehr herausfordernd und wird deshalb
teilweise durch Assembler-Routinen sichergestellt. Zusätzlich sind alle Protokolle enthalten um ein primitives Device
nachzubilden und im Windows anzumelden.
Die usprünglichen Quellen scheinen deutlich älter als 10 Jahre zu sein. Immerhin sind die letzten Änderungen
vor nur ca 2 Jahren eingepflegt worden. Das Alter scheint auch sonst keine Nachteile zu haben. In meiner Win10 Umgebung läuft
alles sauber, Win11 habe ich nicht getestet.
Im Verzeichnis
Example Projects liegen, wie der Name bereits
vermuten lässt, jede Menge Beispiele. Viele sind ursprünglich für die ATTiny45 und 85 Prozessoren geschrieben.
Eine Adaption auf bspw ATmega168 ist kein Problem, ein paar Details sind aber zu beachten. So können
z.B. offensichtlich nur Devices mit interner PLL (ATTiny) ihren internen Oszillator bis über 16MHz hochdrehen.
Ein ATmega168 kann das nicht. Ebenso variieren die Namen der diversen Register über die Prozessortypen.
Alles ist für die
WinAVR
Entwicklungsumgebung ausgelegt, das kommt mir sehr gelegen :).
Hardware
Auf der V-USB-Seite sind jede Menge Schaltungsbeispiele angegeben. Für meinen Einsatz habe ich daraus die beiden
folgenden Schaltpläne abgeleitet. Links mit, rechts ohne Quarz. Man beachte besonders die unterschiedliche
Belegung von INT0:
Die Schaltung mit Quarz ist möglicherweise nachbausicherer und in der SW anspruchsloser. Dadurch sollte sie
unkritischer im Timing sein und mehr Resourcen für eigene SW-Teile verfügbar machen.
Die Hardware ohne Quarz verdreht den internen 8MHz Oszillator sehr extrem, bis auf 12.8MHz. Das liegt
(gerade noch) innerhalb der typischen Daten, ist aber keine zugesicherte Eigenschaft. Egal, einen Quarz
spart man gerne ein wenn er nicht zwingend notwendig ist.
Mindestens eine der USB-Leitungen muss an den Interrupt INT0 angeschlossen sein. Die Portbelegung kann man
bei Bedarf im Config-File ändern, ich würde aber mit dem Default beginnen.
Der Pull-Up auf der D- Leitung signalisiert dem PC dass es sich um ein Low-Speed Device handelt.
Die beiden Taster (nicht eingezeichnet) ziehen die Ports PD5 bzw. PD6 nach Masse. Die beiden 1k sind nur als
primitive Absicherung gegen Überspanung eingefügt.
Für die Spannungsversorgung wird ein 3V3 Low-Drop Spannungsregler eingesetzt. Der kommt perfekt mit den
5V vom USB zurecht und man vermeidet die fragwürdigen Z-Dioden-Konstrukte aus den Beispielen.
An einem PC (=USB-Host) sollte das Device direkt erkannt und aktiviert werden.
An anderen Geräten (Smartphone, Tablet, etc.) muss möglicherweise zusätzlich
USB-OTG aktiviert werden.
Software
Der gesamte usbdrv-Ordner vom GitHub muss zum eigenen Projekt hinzugefügt werden.
Readme.txt und usbconfig.h unbedingt lesen. Dort werden
entscheidende Informationen zum Verständnis der Konfiguration gegeben.
Die Datei usbconfig.h enthält die HW-Konfiguration. Sie muss passend editiert werden.
Viele Beispiele verwenden die Default-Portbelegung wie sie in usbconfig.h definiert ist. Sobald man davon
abweicht funktioniert nichts mehr weil usbconfig.h nicht in allen Makefiles für einem
neuen Build berücksichtigt wird. Mein Makefile habe ich aus mehreren Quellen zusammengestückelt.
Leider bin ich kein C-Experte und kann nicht sagen ob das alles richtig und passend ist. Immerhin funktioniert alles..
Vorsicht beim Mischen der Beispiele, die Versionsstände und die HID-Beschreibungen sind unterschiedlich.
Download der Dateien für mein 2-Tasten-Projekt (HID.zip)
Die Zip-Datei enthält die von mir verwendeten Dateien main.c, Makefile
und usbconfig.h.
Die V-USB-Bibliothek wird ebenfalls benötigt und muss gesondert von
GitHub heruntergeladen werden.
Die Revision der von mir verwendeten V-USB Bibliothek ist 2012-12-06 (falls es eine Rolle spielt).
Oszillatoren und Frequenzen
Für die HW und SW stehen verschiedene Frequenzen zur Auswahl. Alle Details sind im Readme.txt
im usbdrv-Ordner beschrieben. 12MHz ist die untere Grenze mit der das USB-Timing noch garantiert werden kann.
Direkte Vielfache des USB-Takts (1.5MHz) sind vorteilhaft und 18MHz scheint ein Optimum zu sein.
Weitere Frequenzen wurden hinzugenommen um die populären Quarze der Arduino-Boards direkt zu unterstützen.
Die Bibliothek enthält für jeden Takt speziell ausgelegte Assembler-Bausteine.
Mögliche Quarzfrequenzen: 12, 15, 16, 18 oder 20MHz.
Mögliche Frequenzen des internen RC-Oszillators (ohne Quarz): 12.8 oder 16.5MHz.
Die Betriebsart der RC-Oszillatoren geht hart an deren Abstimmungsgrenzen. Und die 16.5MHz sind nur bei Atmel-Typen
wählbar die eine interne 64MHz PLL haben (ATTiny), aber z.B. nicht bei der ATmega8-Familie.
Der interne RC-Oszillator ist relativ ungenau und instabil (im Vergleich mit einem Quarz). Deshalb muss er
regelmässig neu abgeglichen werden. Dazu wird der USB-Takt als Referenz verwendet. Der dafür notwendige Interrupt
wird aus dem D- Signal abgeleitet, weshalb dieses Signal mit INT0 verbunden sein muss. Ebenso müssen die zugehörigen
Routinen aktiviert werden (in der usbconfig.h). In Summe kostet der Verzicht auf den Quarz eine Menge interne
Rechenleistung und Speicher-Resourcen (die man aber nicht immer wirklich benötigt).
Die Kalibrierroutine misst die Zeit zwischen den Interupts und verdreht das OSCCAL-Register bis die Zeit,
und damit die Frequenz, stimmt.
Aus dem Diagramm kann man im Bereich um 12MHz eine Steigung der Kennlinie von 3MHz/32 Bit ablesen.
Das entspricht ca 93KHz/Bit. Die 1% Genauigkeitsanforderung für die 12MHz kann damit gerade so erfüllt werden.
Ein unangenehmer Nebeneffekt ist das das gesamte interne Timing des Prozessors an diesen Takt gekoppelt ist.
Dadurch wird z.B. auch das Timing für die internen Eeprom Zugriffe stark beschleunigt (dort wird der OSCCAL-Wert
gespeichert..), und das kann grenzwertig werden.
Links
V-USB Main Page
V-USB GitHub
4-Tasten-Keyboard-Beispiel
Key-Injector-Beispiel