Anschluss einer PS/2 Tastatur

Raspberry Pi

In diesem Artikel zeige ich euch wie ihr eine normale PS/2 Tastatur an einen PSoC Mikrocontroller anschließen und die Tastatureingaben in einem LCD darstellen könnt.

-> Die Hardware:

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

PS2_Connector 

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

Quelle: wikipedia.de

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

PS2_Schematic
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…

PS2_Communication
Als Startbit wird immer eine 0 ü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:

PS2_Nachricht

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 los lassen 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.

Am Ende des Artikels findet ihr einen Link zu den Scancodes von Tastaturen,  womit ihr den übermittelten Zahlencode einer Taste zuordnen könnt.

-> 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:

PS2_Software(1)

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 1000 0000 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.
Wie dies genau funktioniert, zeigt das Beispiel:

1. Interrupt -> PS2_Data = 1
Ursprungszustand: Keyboard_In = 0
Addieren: Keyboard_In = 0 + 1000 0000
Nach dem Shift: Keyboard_In = 0100 0000

2. Interrupt -> PS2_Data = 1
Ursprungszustand: Keyboard_In = 0100 0000
Addieren: Keyboard_In = 0100 0000 + 1000 0000 = 1100 0000
Nach dem Shift: Keyboard_In = 0110 0000

3. Interrupt -> PS2_Data = 0
Ursprungszustand: Keyboard_In = 0110 0000
Nach dem Shift: Keyboard_In = 0011 0000

Auf diese Weise berücksichtige ich die Sendereihenfolge der Tastatur (wir erinnern uns…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:

PS2_Software(2)
Weiter unten findet ihr das komplette PSoC Designer Projekt, sodass ihr die Schaltung ganz einfach nachbauen / modifizieren könnt.
In diesem Projekt befindet sich auch eine Headerdatei mit einem Array für die entschlüsselten Scancodes. In dieser Headerdatei sind alle Buchstaben und Zahlen (kein Nummernblock) der Tastatur enthalten.

 

Dokumentation:

 

-> Zurück zu PSoC

2 thoughts on “Anschluss einer PS/2 Tastatur
  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

Schreibe einen Kommentar

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

Time limit is exhausted. Please reload CAPTCHA.