Forum: Mikrocontroller und Digitale Elektronik PS/2 Protokoll auf AVR - Tastatur (Maus) emulieren, Fragen zur Schaltung und Programm


von Marc (Gast)


Lesenswert?

Hallo,

ich bin noch recht neu auf dem Gebiet Mikrocontroller und kann bis jetzt 
auch nur einfaches Assembler programmieren, dazu habe ich mich durch 
diverse Tutorials gehangelt und viele Sachen auf dem Steckbrett 
ausprobiert.
Um meinen Horizont zu erweitern, dachte ich mir, ist es vielleicht das 
beste an konkreten "Projekten" zu lernen, was auch bisher ganz gut 
geklappt hat.

Aktuell möchte ich gerne einen PC über die PS/2 Schnittstelle 
ansprechen, d.h. ich möchte ihm eine Tastatur vorgaukeln (emulieren) und 
Scancodes senden (wenn das funktioniert und ich alles richtig verstanden 
habe auch eine Maus).

Nun finden sich hier im Forum jede Menge Beiträge darüber, in denen auch 
immer wieder die selben Quellen genannt werden zur Funktionsweise des 
Protokolls, z.B.:

http://www.marjorie.de/ps2/ps2_protocol.htm
http://www.beyondlogic.org/keyboard/keybrd.htm

Als Einstieg dachte ich mir, ich schreibe ein kleines Programm, dass in 
einer Schleife in Abständen von 3 Sekunden, die Make und Breakcodes z.B. 
der "A"-Taste sendet, also Makecode: 0x1c danach Breakcode: 0xf0 0xf1c 
und dann 3 Sekunden wartet und wieder zum Anfang springt.

Nun habe ich bei meinen Vorüberlegungen aber noch Fragen wie man das am 
besten auf einem AVR atmega8 realisiert und dazu leider keine 
Anfängerfreundlichen Beiträge gefunden (Falls es sie doch gibt, würde 
ich mich auch über Links dazu freuen).

Wie schließe ich die Hardware am besten an?
Ich habe ein PS/2-Kabel aus einer alten Tastatur und einen minimal 
beschalteten atmega8 auf einer Lochrasterplatine mit ISP.
Ich habe das so verstanden, dass ich lediglich die Clock-Leitung 
(PS/2-Pin 5) mit einem I/O-des AVRs (z.B. PD0), die Data-Leitung 
(PS/2-Pin 1) mit einem weiteren I/O des AVR (z.B. PD1) und die 
Ground-Leitung (PS/2-Pin 3) mit dem Ground-Kreis der Platine verbinden 
muss, ist das richtig so?
Kann ich zusätzlich vielleicht auch +5V des PS/2 (Pin 4) benutzen um den 
Controller mit Spannung zu versorgen?

In der Beschreibung auf marjorie.de/... steht, dass man zum Anschluss 
des Controllers an den PC einen Open Collector braucht, diesen aber 
durch die internen Pull-Up Wiederstände ersetzen kann. Stimmt das, oder 
muss ich dazu von den beiden I/Os jeweils einen Widerstand nach VCC 
anlöten (Wie bei einem Taster z.B. 10k) brauche ich in diesem Fall dann 
auch unbedingt die Transistoren die dann an zwei weitere I/Os des AVRs 
angeschlossen werden müssen?

Wenn die Schaltung dann soweit funktionieren sollte, ist meine erste 
Überlegung zur Software ob ich überhaupt einfach die Scan-Codes an den 
PC senden und Linux sie direkt verarbeiten kann, z.B. die empfangenen 
Scancodes als ASCII Zeichen umgewandelt auf einer Konsole ausgeben. Oder 
muss ich vorher die Initialisierung vom BIOS oder Linux durchlaufen? 
(Ich habe ja an dem PS/2 Anschluss nur die AVR Schaltung und keine 
weitere Tastatur, dessen Controller das vorher für mich übernehmen kann) 
Reicht es dafür vielleicht auch aus, wenn ich erst die Tastatur 
anstöpsle und wenn alles gebootet ist, den Controller anstecke?

Falls ich die Initialisierung durchlaufen muss, müsste es doch 
ausreichen auf jede Anfrage ACK zu senden, oder? Da ich ja grundsätzlich 
nur etwas an den PC senden will und nichts empfangen, müsste es doch 
reichen, den AVR erkennen zu lassen, wenn der PC etwas gesendet hat und 
dann blindlings jedesmal mit ACK zu antworten?

Ich hoffe, dass ihr mir diese Fragen zu meinen Vorüberlegungen 
beantworten könnt, dann könnte ich mich nämlich ans eingemachte begeben 
und mit dem Programm loslegen :-)

Gruß,
Marc (der noch viel lernen muss)

von Feier F. (feierfoxx)


Lesenswert?

Hallo Marc,

der Link

http://www.marjorie.de/ps2/ps2_protocol.htm

gibt eigentlich alles an Auskunft, was man braucht. Ich hatte früher mal
eine komplette Emulation der Schnittstelle auf einem 51er geschrieben.

Hat Top funktioniert.
Achtung ist bei den SCAN CODE SETs geboten.
SET 1 brauchst Du  nicht beachten.

SET 3 ist zwar am einfachsten auszuwerten, wird aber von nicht allen
Tastaturen zur Verfügung gestellt.

SET 2 kann nahezu jede PS2 Tastaur mit Mini DIN Stecker.

Hatte auch schon mal Keyboards (Cherry) die nach dem einschalten mit SET 
3
starteten.

Fang erst mal damit an, Dir eine Routine zum Senden und Empfangen zu 
schreiben, ungeachtet dessen, welche Daten dann übertragen werden.

von Marc (Gast)


Lesenswert?

Hallo feierfoxx,

danke für deine Antwort.
Wie die Daten gesendet werden müssen möchte ich schnellstmöglich 
ausprobieren, habe auch schon eine Idee wie ich das machen könnte... 
aber bevor ich damit anfangen kann sollte ich mir doch erstmal sicher 
sein, dass alles technisch funktioniert. Reicht es also wirklich, wie 
ich beschrieben habe, die Data und Clock leitungen jeweils mit einem I/O 
zu verbinden, oder brauche ich noch zusätzliche diese Pull-Up 
Wiederstände zu VCC oder sogar noch zwei weitere I/Os und diese 
Transistoren?

Wie hasst du das früher gemacht, musstest du diesen 
Initialisierungsvorgang vom BIOS und Betriebssystem durchlaufen?

von Marc (Gast)


Lesenswert?

Entschuldigung für den Doppelpost, habe aber gerade nochmal genau 
geschaut und dies entdeckt:
1
In meinen Beispielen habe ich ein paar Tricks benutzt, um ein Open-Collector-Interface mit PIC-Microcontrollern zu implementieren. Ich benutze den selben Port als Eingang und Ausgang und verwende die internen Pull-Up-Widerstände des PICs anstelle von externen Widerständen. Eine Leitung wird auf Low gezogen, indem man den entsprechenden Port als Ausgang setzt und logisch "0" ausgibt. Den hochohmigen Zustand erreicht man, indem der Port als Eingang geschaltet wird. Mit den eingebauten Schutzdioden und dem hohen Stromtreibervermögen der PICs, denke ich, kann man das durchaus so machen.

Heisst das, das ich zu Beginn den hochohmigen Zustand setze in dem ich 
die beiden I/Os für Clock und Data auf Eingang setze. Wenn ich dann was 
übertragen möchte, schalte ich die I/Os wieder auf Ausgang und gebe dann 
den zu übertragenden Bits entsprechend 0 oder 1 aus?

Muss ich, wenn die I/Os als Eingang gesetzt sind und der hochohmige 
Zustand erreicht werden soll die internen Pull-ups aktivieren durch 
Ausgabe von 1 an die entsprechenden Portpins?

von Feier F. (feierfoxx)


Lesenswert?

Hallo Marc,

ich hatte es bei mir folgendermaßen gelöst.
2 leichte PullUps 47K extern + 2 Z-Dioden ZMM5,1 zur Spannunsbegrenzung.
Könntest auch noch NTCs in Reihe einfügen um Kurzschluß von außen zu 
minimieren.

2 Portleitungen reichen.

DATA is Bidirectional
CLK ist generell Eingang, da das Keyboard immer den Taktmaster 
darstellt.

Jetzt solltest Du noch die Auswerte Methode festlegen.

1.) Takt per Interrupt auswerten, spart evtl. Ausführungszeit

oder

2.) per Polling , also Portabfrage
Ich habe in meinem Code die 2. Variante gewählt. Da Sie das Handling der 
Schnittstelle wesentlich vereinfacht, was das umschalten zwischen Senden 
und Empfangen angeht.

von Feier F. (feierfoxx)


Lesenswert?

Das hatte ich vergessen.

Die Portleitungen eines z.B. AT89 sind quasi Bidirectional, wie die der 
Tastatur auch.
Sie werden per PullUp gegen VCC gezogen, habe also keine HI-Side 
Treiberstufe
und lediglich gegen 0 geschaltet.

Der Vorteil hier ist, man kann im Kollisionsverfahren praktisch keinen 
Kurzschluß erzeugen.

Den PullUp an der Datenleitung muß man gegebenenfalls etwas anpassen, 
daher
etwas niederohmiger machen um die Schaltflanke zu verbessern.

von Marc (Gast)


Lesenswert?

1
2 leichte PullUps 47K extern + 2 Z-Dioden ZMM5,1 zur Spannunsbegrenzung

Meinst du wirklich 47k oder vielleicht auch 4k7, habe (glaube ich) in 
einem der Threads mal was von 4k7 gelesen?

Leider habe ich keine ZMM5,1 , kann ich vielleicht auch eine von diesen 
verwenden:

Diode
SB 130

Schalt-/Schottky-Dioden:
PH4148
1N4148
1N4448

Gleichrichterdiode:
1N4001

Die Z-Diode sind doch nur zum Schutz, für die Schaltung ist sie doch an 
sich nicht notwendig, oder?
1
Den PullUp an der Datenleitung muß man gegebenenfalls etwas anpassen,
2
daher etwas niederohmiger machen um die Schaltflanke zu verbessern.

Was meinst du, was ich da für einen Wert nehmen soll, z.B. 1k?

Versteh meine blöden Fragen nicht falsch, ich möchte nur die Hardware 
klar haben, damit ich mich bei der Software nicht über unerklärliche 
Fehler wundere...

von Rudolph R. (rudolph)


Lesenswert?

Ist das nur mein Eindruck oder diskutiert Ihr aneinander vorbei?

Marc, Dein Anliegen ist doch offenbar nicht, eine Tastatur an Deinem 
Controller anzuschliessen, sondern Deinen Controller so zu 
programmieren, dass der sich wie eine Tastatur verhält?

Schau mal hier:
http://picobay.com/dtv_wiki/index.php?title=Keyboard_Twister

Das Teil wird zwischen Tastatur und Rechner gehängt um Scan-Codes 
on-the-fly zu wandeln.

Und basiert auf diesem Projekt:
http://www.circuitcellar.com/avr2006/winners/AT3296.htm

von Marc (Gast)


Lesenswert?

Danke, das könnte natürlich sein, probiere hier nämlich auch gerade 
vergeblich damit zu experimentieren... und hätte das jetzt gar nicht 
gemerkt :-)

Also, ich möchte auf jedenfall den uC als Eingabegerät, als 
Tastatur-(oder Maus)Ersatz, benutzen.

Mein Problem ist, dass bei http://www.marjorie.de/ps2/ps2_protocol.htm 
im Kapitel 2.3 unter Abbildung 4 eine Schaltung abgebildet ist, auf der 
ein Mikrocontroller mit einer Open Collector Schaltung zu sehen ist. Ich 
dachte, dass wäre die Beschaltung um ihn an den PC an zu schliessen...

Wenn man den Absatz darunter liest, steht da ja drin, dass der Autor 
dieses Umgangen hat, in dem er nur zwei Ports seines Mikrocontrollers 
verwendet ohne die abgebildete Open Collector Schaltung.
Die beiden Zustände HIGH (logisch 1) oder LOW (logisch 0) erreicht er 
wohl, in dem er für LOW (=0) den entsprechenden Port als Ausgang 
konfiguriert und 0 ausgibt, und HIGH (=1) in dem er den Port als Eingang 
konfiguriert und 1 ausgibt (also die internen Pull-Ups aktiviert).

Habe ich das so richtig verstanden, oder muss er für HIGH=1 gar nicht 
zusätzlich 1 ausgeben und damit die internen PullUps aktivieren?

Ich habe mir auch die beiden Links angeschaut, den mit der Fernbedienung 
kannte ich schon, prinzipiell will ich genau soetwas machen, nur halt 
ohne IR Empfang und in Assembler (da ich das ja gerade lernen möchte).

Auf der Seite von dem C64 DTV Hack ist auch ein Schaltplan abgebildet, 
auf dem sich nur Widerstände an den I/Os für die Tastatur befinden, beim 
Aschluss zum PC sind die I/Os direkt mit den Clock und Data Leitungen 
verbunden ohne zusätzliche Pull-Ups oder sonstwas...

Also kann ich daraus schließen, dass ich wirklich den uC mit dem PC so 
verdrahten muss und es funktionieren soll?

Um mal ein bisschen zu testen habe ich ein kleines Programm geschrieben, 
dass zu Beginn die beiden I/Os als Eingänge konfiguriert und in einer 
Schleife permanent überprüft ob das Bit am Pin der Clock-Leitung auf 0 
oder 1 ist. Wenn dieses Bit 0 ist, soll es eine LED einschalten, wenn 
dieses Bit 1 ist soll die LED aus sein.

hier mal das relevante Codeschnipsel:
1
;LED initialieseren
2
    ldi     temp, 1<<PB2
3
    out     DDRB, temp
4
    ldi     temp, 1<<PB2
5
    out     PORTB, temp
6
7
;Clock und Data initialisieren
8
    ldi     temp, (0<<PD0 | 0<<PD1)
9
    out     DDRD, temp
10
11
main:
12
    sbis    PORTD, PD0
13
    cbi     PORTB, PB2
14
    sbic    PORTD, PD0
15
    sbi     PORTB, PB2
16
    rjmp    main

Theoretisch müsste doch nach dem einschalten des PCs der Rechner die 
Clock-Leitung für mindestens 100 us auf LOW(=logisch 0 = 0 Volt) ziehen 
um dem Eingabegerät zu signalisieren mit der Generierung des Clock 
Signals zu beginnen und ihm dann die Bits für den BAT (Selbsttest der 
Tastatur) zu senden?

Wenn ich ein Multimeter zwischen Clock und Ground anschliesse, sehe ich, 
dass vor dem Betätigen des Power Knopfes 5,12 Volt anliegen, schalte ich 
den PC ein sinkt die Spannung auf ca 20mV (0,020 Volt) für ca 5 Sekunden 
und steigt dann wieder an auf 5,08 V. Die LED leuchtet allerdings die 
ganze Zeit.

Was läuft da schief, bzw. was verstehe ich vielleicht falsch an der 
ganzen Sache?

Marc

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Wenn ich ein Multimeter zwischen Clock und Ground anschliesse...
Mit dieser Messtechnik wirst du bald am Ende sein. Wenn du ein serielles 
Protokoll auswerten willst, das du nicht (oder nur teilweise) selbst 
bestimmst, brauchst du mindestens ein Oszi. Am schönsten natürlich eines 
mit speicher, aber irgendeines ist besser als gar keines.
Sonst kannst du jetzt und in Zukunft nur raten:
Wie steil sind deine Flanken?
Wann genau erfolgt die Pegelumschaltung?
Wo...?
Wer..?
Warum...?

Für den schnellen Start gibts da sogar Bastellösungen für die 
Soundkarte, aber da bist du mit deiner Baudrate schon ziemlich an der 
Grenze dieser Software-Lösungen angelangt.

BTW:
Dir ist schon klar, dass
1
;Clock und Data initialisieren
2
    ldi     temp, (0<<PD0 | 0<<PD1)
3
    out     DDRD, temp
das selbe ist wie
1
;Clock und Data initialisieren
2
    ldi     temp, 0
3
    out     DDRD, temp

Meinst du statt
>>    sbis    PORTD, PD0
eventuell
>>    sbis    PIND, PD0

Schreib 100 mal:
Ich will das Tutorial lesen und beachten ;-)
http://www.mikrocontroller.net/articles/AVR-Tutorial:_IO-Grundlagen

von Marc (Gast)


Lesenswert?

Hallo,

also ein "kleines" Oszi habe ich auch hier, so ein GDM 704 von Voltcraft 
ist ein Graphisches Digitales Multimeter, mit Frequenzgenerator, 
Logikanalyser und 1-Kanal Oszilloskop (Bandbreite: 200 kHz und 
Abtastrate: 1 MS / Sekunde). Das sollte doch eigentlich ausreichend 
sein, oder? Das einzige Problem ist an dem Ding, dass das Display ein 
wenig klein ist und man über die RS-232 Schnittstelle nur höchstens 3 
Messwerte / Sekunde empfangen kann...

100 Mal "Ich will das Tutorial lesen und beachten"!!! :-)

ok, jetzt funktioniert es war tatsächlich PIN und nicht PORT..

Ach Mensch, ja so ein dummer Fehler... Das werde ich bestimmt nicht 
wieder vergessen :-)

Aber das mit den Bitsschieben war mir klar, hab mir das der Übersicht 
wegen angewöhnt und damit man leichter mal die Pinkonfiguration ändern 
kann. Das ist gerade bei Aufbauten auf dem Steckbrett sehr angenehm.

1
;LED initialieseren
2
    ldi     temp, 1<<PB2 | 1<<PB3
3
    out     DDRB, temp
4
    ldi     temp, 1<<PB2 | 1<<PB3
5
    out     PORTB, temp
6
7
;Clock und Data initialisieren
8
    ldi     temp, (0<<PD0 | 0<<PD1)
9
    out     DDRD, temp
10
11
main:
12
    sbis    PIND, PD0
13
    cbi     PORTB, PB2
14
    sbic    PIND, PD0
15
    sbi     PORTB, PB2
16
    sbis    PIND, PD1
17
    cbi     PORTB, PB3
18
    sbic    PIND, PD1
19
    sbi     PORTB, PB3
20
    rjmp    main

Habe nun auch noch eine 2. LED hinzugefügt, die leuchtet wenn Data low 
ist.
Mir ist aufgefallen, dass wenn ich eine USB-Tastatur angeschlossen habe 
und eine Taste drücke, das Clock-Signal auch auf dem PS/2 entsprechend 
erzeugt wird und die LED in meiner Schaltung blinkt...(Dies tritt 
allerdings nur auf, wenn das Betriebssystem noch nicht geladen wurde)

Wie sieht das denn nun mit dem senden bzw. empfangen aus. Ich habe ja 
schon zweimal geschrieben wie ich das in dem PS/2-Tutorial verstanden 
habe... kann man das so machen:
für LOW=0 Port als Ausgang und 0 ausgeben,
für HIGH=1 Port als Eingang (und 1 ausgeben / Pull-Ups aktivieren???) ?
oder für HIGH=1 Port als Ausgang und 1 ausgeben?

Als nächstes würde ich dann probieren eine Routine zu schreiben, die das 
ACK-Bit erzeugt und so auf die Initialisierung des Hosts reagiert. Und 
erst wenn das klar ist, kann ich doch dazu übergehen testweise Scancodes 
zu schicken und im Konsolenfenster auszugeben, oder?

Vielen Dank für eure Hilfe, bin heute zumindest schonmal ein Stück 
weiter als gestern :-)

Gruß,
Marc

von Michael (Gast)


Lesenswert?

Hallo,

auch auf die Gefahr hin, daß sich dieses Problem schon lange erledigt 
hat, schreibe ich doch mal etwas dazu. Möglicherweise kann jemand 
anderes diese Info brauchen.

Wenn während des Initialisierungsvorgangs die Tastatur nicht auf den 
Befehl "Read ID" mit  ABh und 83h antwortet, und/oder auch nicht auf den 
Befehl "Echo" richtig reagiert, kann es sein, daß die Tastatur vom 
Keyboard-Controller des PCs nicht erkannt und  auch nicht weiter 
abgefragt wird (zumindest bei einer Vielzahl von Mainboards). Die 
Erfahrung habe ich selber beim Programmieren einer Tastatur mit einem 
8051 gemacht.

Also reicht es nicht, auf jedes Byte, das vom PC kommt nur mit FAh (ACK) 
zu antworten. Ohne Befehlsauswertung kann man die Tastatur höchstens 
nach dem Booten umstecken, was irgendwann aber nervig und auch teilweise 
schädlich für die Hardware sein kann.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.