Kampis Elektroecke

Anschluss einer PS/2 Tastatur

Raspberry Pi

In diesem Artikel zeige ich, wie eine PS/2 Tastatur an einen PSoC Mikrocontroller angeschlossen und die Tastatureingaben in einem LCD dargestellt werden können.

Die Hardware:

Die Pinbelegung eines PS/2 Anschluss ist standardisiert und entspricht immer diesem Muster:

1 Data 4 Vcc (+5 V)
2 5 Clock
3 Masse 6

 

Quelle: wikipedia.de

Die Schnittstelle ist als Open-Collector ausgeführt, weswegen zwei zusätzliche Pull-up Widerstände notwendig sind:

Für die Pull-Up Widerstände verwende ich die chipinternen Widerstände, sodass ich keine zusätzlichen Bauteile benötige.

Kurzer Überblick über das PS/2 Protokoll einer Tastatur:

Im nächsten Schritt, werfen wir einen kurzen Blick auf die Kommunikation einer PS/2 Tastatur mit einem Hostdevice (im Regelfall ein Computer).
Ein PS/2 Datenpaket besteht aus 11 Bits, welche LSB First gesendet werden. Von diesen 11 Bits ist 1 Bit für Start/Stop und 1 Bit für eine Paritätskontrolle reserviert, sodass jedes Datenpaket 8 Datenbits enthält.
Die Tastatur generiert beim Senden des Datenpakets zudem ein Taktsignal, welches allerdings sehr stark schwanken kann.
Schauen wir uns diese Kommunikation einmal genau an…

Als Startbit wird immer 0x00 übertragen und das Stopbit ist immer eine 1. Der Wert des Paritätsbits hängt von der Anzahl übertragender Einsen im Datenpaket ab. Es wird gesetzt (1), wenn die Anzahl enthaltener Einsen gerade ist und wird dem entsprechend gelöscht (0), wenn die Anzahl enthaltener Einsen ungerade ist.
Aus dem oben gezeigten Signalverlauf kann man also folgendes entnehmen:

Bei der Dekodierung der Nachricht darf man nicht vergessen, dass das niederwertigste Bit immer zuerst gesendet wird!
Wenn man sich eine Übertragung einer Tastatur etwas genauer anschaut wird man feststellen, dass die Tastatur immer folgenden Ablauf einhält:

  1. Taste wird gedrückt -> Tastatur sendet einen entsprechenden Code.
  2. Wird die Taste länger als 500ms (standardmäßig) gedrückt, wiederholt die Tastatur das Senden des Codes in sehr schneller Folge, bis die Taste losgelassen wird.
  3. Beim Loslassen der Taste sendet die Tastatur ein 0xF0 gefolgt von dem Zahlencode der entsprechenden Taste. Auf diese Weise weiß der Host, dass die Taste losgelassen wurde.

Die Software für den Mikrocontroller:

Zeit um sich der Mikrocontroller Software zu widmen. Diese Software liest einzelne Tastendrücke einer Tastatur aus und stellt sowohl den Scancode, wie auch den entschlüsselten Scancode auf einem LCD dar.
Für die Ansteuerung eines LCDs verwende ich ein fertiges LCD-Modul, welches ich mit dem Port 2 des Mikrocontrollers verbinde.

Für die Kommunikation mit der Tastatur nutze ich zwei einfache I/Os, welche ich mit einem Pull-Up Widerstand versehe. Da der Takt der Tastatur sehr ungenau ist und sehr stark schwanken kann, nutze ich keinen Timer zum Empfangen der Nachricht, sondern verwende einen Interrupt, welcher bei jeder fallenden Taktflanke ausgelöst wird. Die fertige Pinkonfiguration für den Mikrocontroller sieht dann so aus:

Damit wäre die Hardwarekonfiguration des Chips abgeschlossen.
Die PS/2-Nachricht wird komplett über Interrupts abgearbeitet. Um die Interrupts zu aktivieren, wird als erstes die Zeile

in das Programm main.c eingefügt.

Der Ausdruck “PS2_Interrupt” ist der Name meiner Interrupt Service Routine (ISR), welche bei einem Interrupt ausgeführt wird. Im nächsten Schritt muss in der Datei PSoCGPIOINT.asm der Codeblock unter PSoC_GPIO_ISR wie folgt angepasst werden:

Durch das Einfügen der beiden Codezeilen

in die Datei main.c wird der GPIO Interrupt schlussendlich aktiviert und ist damit einsatzbereit.
In der ISR wird bei jedem Aufruf die Variable Bitcounter um eins hochgezählt. Diese Variable zählt die empfangenen Bits der Tastatur. Beim Empfangen der Nachricht ignoriere ich direkt das Start-, Stop- und Paritätsbit, sodass ich nur 8 Datenbits empfange.

Das Empfangen geschieht mit der ersten If-Abfrage in der ISR. Solange der Bitcounter größer als 1 (damit wurde das Startbit ignoriert) und kleiner als 9 (das übersprungene Startbit + 8 Datenbits) ist wird der erste Zweig der Abfrage ausgeführt:

In dieser Abfrage wird geschaut ob der PS/2-Datenpin (PS2_Data) einen High- oder einen Lowpegel führt.
Führt der Pin einen Highpegel wird das Bitmuster 0x80 auf den Inhalt der Variable Keyboard_In addiert und das Bitmuster innerhalb dieser Variable anschließend um eine Stelle nach rechts geschoben.
Führt der Pin hingegen einen Lowpegel, wird der Variableninhalt nur um eine Stelle nach rechts geschoben. Eine 0 rutscht dann automatisch nach.

Auf diese Weise berücksichtige ich die Sendereihenfolge der Tastatur (LSB first) und bringe die Nachricht gleich in die richtige Reihenfolge.

Im zweiten Zweig der If-Abfrage wird geschaut ob die Variable Bitcounter 11 Bits gezählt hat. Wenn diese Bedingung zutrifft, ist die erste Nachricht komplett empfangen worden und das Ergebnis der Nachricht wird durch eine andere Variable aus der ISR raus kopiert.

Im dritten Zweig der If-Abfrage werden die beiden anderen Nachrichten, die beim loslassen der Taste gesendet werden, abgefangen. Der Bitcounter wird einfach bis 33 erhöht (3×11 Bit) und anschließend gelöscht. Dann kann eine neue Übertragung beginnen.

Im Hauptprogramm wird nun der gesendete Tastaturcode im LCD dargestellt:

Jetzt muss dieser Tastaturcode natürlich noch einer Taste zugewiesen werden. Hierfür habe ich mir einfach ein Array namens Keyboard gemacht, wo ich die entsprechenden Tasten an der Stelle abgespeichert habe, die deren Scancode entspricht, z.B. die Taste F1 hat den Scancode 0x05 und ist deswegen an der 5. Stelle im Array.
So kann ich direkt mit den Scancodes die entsprechende Stelle im Array adressieren und die entsprechende Taste auslesen.

Testen den Software:

Zeit um die Software zu testen. Dazu werden Hardwarekonfiguration und Software des Chips kompiliert und auf den Chip aufgespielt. Sobald nun Spannung auf das Board gegeben wird und ihr eine Taste drückt, wird der Scancode und die dazu gehörige Taste im Display angezeigt:

In diesem Projekt befindet sich auch eine Headerdatei mit einem Array für die entschlüsselten Scancodes, welches alle Buchstaben und Zahlen (kein Nummernblock) der Tastatur enthält. Das komplette Projekt kann bei Git heruntergeladen werden.

→ Zurück zu PSoC

2 Kommentare

  1. Moin Kampi, da gibt es einen kleinen Fehler in deinem Code.

    if(Bitcounter 1) // Nur die acht Datenbits werden empfangen

    Von 2 bis 8 wäre bei mir 7 Bits… richtig ? jo.. :-) solange das höhste Bit null bleibt
    wirst du auch bei einem a = C1 bekommen.

    Kampi noch eine Frage, sendet die Tastatur immer 3 Byte ? wegen deinem Code
    else if(Bitcounter == 33)

    Gruß Frank

    1. Hallo Frank,

      danke für den Hinweis. Ich schaue den Code noch mal durch und aktualisiere ihn mal :)
      Zum Thema Tastatur kannst du dir auch mal das hier durchlesen:

      http://www.marjorie.de/ps2/ps2.pdf

      Und hier noch einmal die Scancodes als Bild:

      http://www.philipstorr.id.au/pcbook/images/scancod1.gif

      Die Anzahl Bytes, die gesendet werden, hängen stark von den Tasten ab die gedrückt werden (siehst du z.B. bei Alt rechts). Die Implementierung von mir ist nur sehr einfach gehalten um die Basistasten abzubilden.
      Hoffe das hilft dir weiter.

      Gruß
      Daniel

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.