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.htmhttp://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)
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.
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?
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?
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.
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.
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
1N41481N4448
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...
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
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
> 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
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
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.