Forum: Mikrocontroller und Digitale Elektronik PC-Tastatur mit AVR ersetzen


von Moritz G. (moritz-)


Angehängte Dateien:

Lesenswert?

Hallo!
Ich will mit einem ATmega eine PC-Tastatur programmieren, die nur zwei 
Tasten enthält: Pfeil up und Pfeil down

Dafür muss ich mithilfe des Protokolls (im Anhang) vier Bytes 
übertragen:

E0,F0,6B,75 (alle hex)

Hat jemand schon erfahrungen mit Software-Protokollen? Kann das klappen, 
in der Art:

Pin1 on, Pin2 off, warte 1ms, Pin2 off, warte 1,2ms, Pin1 off, warte 0,5 
ms, Pin1 on,.......

Hier jetzt mal nur so als Beispiel. Ich müsste mir dann die Arbeit 
machen für die 4 oben genanten Bytes Unterprogramme zu schreiben, und 
dann

Bei Taste "Pfeil up"
rcall E0uebertragen

bei Taste "Pfeil up"  wieder losgelassen
rcall ...

usw. Das ist die Holzhacker-Methode, aber ich habe noch keine Idee wie 
es eleganter geht...

Ideen?

Grüsse,
Moritz

von Dirk H. (arm-dran)


Lesenswert?

Moritz Greif wrote:
> Hallo!
> Ich will mit einem ATmega eine PC-Tastatur programmieren, die nur zwei
> Tasten enthält: Pfeil up und Pfeil down
>
> Dafür muss ich mithilfe des Protokolls (im Anhang) vier Bytes
> übertragen:
>
> E0,F0,6B,75 (alle hex)
>
> Hat jemand schon erfahrungen mit Software-Protokollen? Kann das klappen,
> in der Art:
>
> Pin1 on, Pin2 off, warte 1ms, Pin2 off, warte 1,2ms, Pin1 off, warte 0,5
> ms, Pin1 on,.......
>
> Hier jetzt mal nur so als Beispiel. Ich müsste mir dann die Arbeit
> machen für die 4 oben genanten Bytes Unterprogramme zu schreiben, und
> dann
>
> Bei Taste "Pfeil up"
> rcall E0uebertragen
>
> bei Taste "Pfeil up"  wieder losgelassen
> rcall ...
>
> usw. Das ist die Holzhacker-Methode, aber ich habe noch keine Idee wie
> es eleganter geht...
>
> Ideen?
>
> Grüsse,
> Moritz

@Moritz

Wenn Du die Tastatur an einen PC anschließen willst, reicht es nicht 
aus,
nur eben die Codes für beide Tasten zu senden.
Der PC kommuniziert mit der Tastatur, macht am Anfang einen Selbsttest.

Wenn Du nicht entsprechend dem PS2 Protokoll reagierst (Standard Set2),
wird der PC die Tastatur als evtl. nicht anwesend erkennen.

Dirk

PS:  Eine Simulation einer PS2 Tastatur mit einem AVR ist grundsätzlich
Problemlos

von crazy horse (Gast)


Lesenswert?

es gibt nicht nur einen Code für das Drücken der Taste, sondern auch 
fürs loslassen.
Klar kann man das selbst programmieren, dürfte nicht sonderlich schwer 
sein.
Ich würde eine alte Tastatur auchschlachten und die passenden Anschlüsse 
für die Tasten verwenden. Einfach, billig, betriebssicher, schnell 
gemacht.

von Otto (Gast)


Lesenswert?

Hallo Moritz,

ja - viele Wege führen nach Rom - Du
kannst auch die Daten an eine Routine
übergeben, die den Start ausgibt,
das auszugebende Byte in einer Schleife
schiebt und ausgibt und abschliessend
das Stoppbit sendet.

Gruß Otto

von Moritz G. (moritz-)


Lesenswert?

Ja ok, das mit den Codes für anschlag und loslassen hab ich im Internet 
gefunden. Man muss für die Pfeiltasten doooferweise zwei Byte senden für 
gedrückt, und drei Byte für wieder losgelassen.

Das Mit dem Selbsttest am Anfang ist ja eglich. Danke für den Hinweis!
Ich werde mich darüber mal erkundigen.

Aber ihr denkt, dass einfaches, manuelles, an & aus machen von zwei Pins 
ausreicht. Na das probier ich auch dann mal aus.

Eine Frage noch: ist der Takt des Clock Impulses genormt? Kann er 
beliebig lang sein? Und wichtiger: muss er immer gleich getaktet sein, 
oder kann man z.b. bei Bit 5 den Clock takt verlängern (sozusagen die 
Übertragung verzögern/stoppen) oder so? theoretisch handelt es sich doch 
um ein asynchrones Protokoll-Signal!!! (reagiert ja eigentlich auf die 
flanken)

Grüsse
Moritz

von Otto (Gast)


Lesenswert?

Hallo Moritz,

die Tastatur macht einen Selbsttest.

Für den PC ist die Welt in Ordnung,
wenn die Leitungen High-Pegel haben.

"an und aus machen" geht, wird aber
sicher ein wenig lang....

Gruss Otto

von Dirk H. (arm-dran)


Lesenswert?

@Moritz

Und hier der altbekannte Link:

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

So einfach funktioniert das nicht.

1.) Die Tastatur ist immer der Taktmaster
Ein Impuls dauert zwischen 20 und 40 µS (schwankt deswegen, weil die 
Tastaturen meistens keinen Quarz sondern nur ein RC Glied, Resonator 
haben)

2) Der PC richtet sich nach diesem Takt, kann jedoch durch 
"herunterziehen" der Signale von CLK und oder DAT die Tastatur zu 
versch. Aktionen veranlassen.
Du musst dann beide Ports nach dem schreiben zurücklesen und prüfen, ob 
der
PC eine Aktion starten möchte.

Dirk

von Moritz G. (moritz-)


Lesenswert?

Jo, also ich lass die beide pins an, bis der PC den Clock-Pin nicht mehr 
auf null gezogen hat, dann kann ich die übertragung starten.
Als Takt sind 20 bis 40 µs  ja mit nem 8Mhz Quarz am Atmega8 kein 
Problem.
Ich werde dann die sende Pins mit zwei andern pins verbinden, die als 
Eingang konfiguriert sind, dann kann ich zwischendurch immer mal prüfen, 
ob der PC aufmuckt.

Muss ich die manchmal erwähnten "Echo"-Bytes und so auch senden? Ich 
blick da nicht durch in den Codetabellen. Wenn der PC zum Beispiel LED1 
an sendet, kann ich das doch einfach  ignorieren, oder?

moritZ


--> nur mal so nebenbei: Die beiden Pfeiltasten werden mit schönen 
vandalismussicheren Tastern neben den neuen digitalen Vertretungsplan in 
unserer Schule angebracht, sodass die Schüler auf den Monitoren scrollen 
können. Ist ein Projektsche was unsere hilflose Schule armen 
Oberstufenschülern aufhalst :-)... Moritz könnten Sie vielleicht mal ...

von Otto (Gast)


Lesenswert?

Hallo Moritz,

>Wenn der PC zum Beispiel LED1
>an sendet, kann ich das doch einfach  ignorieren, oder?

ja

Otto

von Moritz G. (moritz-)


Lesenswert?

So hier nochmal das Timing zusammengefasst:

"The time from the rising edge of a clock pulse to a Data transition 
must be at least 5 microseconds. The time from a data transition to the 
falling edge of a clock pulse must be at least 5 microseconds and no 
greater than 25 microseconds"
"The clock frequency must be in the range 10 - 16.7 kHz. This means 
clock must be high for 30 - 50 microseconds and low for 30 - 50 
microseconds"

mal auf Deutsch:
----------------------------------------------------------------------
Clock pulse an, mindestens 5 µs warten, dann erst 
Datenleitungs-Pegelwechsel, dann wieder mindestens 5µs (und nicht länger 
als 25µs) und Clocksignal wieder low.
So. Jetzt erstmal warten (der Datenpin behält seinen Bit-Wert. der Clock 
Pin ist low.) und zwar ,sagen wir, 40 µs.

Jetzt wieder Clock an, mind. 5µs warten dann erst 
Datenleitungs-Pegelwechsel, dann wieder mindestens 5µs (und nicht länger 
als 25µs) und Clocksignal wieder low.
usw...
-----------------------------------------------------------------------



Ich mach das dann mal so (Bsp. 122:     0b01111010)

CLK        DATA          Dauer   Beschreibung
------------------------------------------------------------
1          1                     start und init des pc's
----------------------------------------------------------
1          0             20µs
0          0             40µs    Startbit
1          0             20
1          0             20      data transition (erstes bit 0)
0          0             40
1          0             20
1          1             20      data transition
0          1             40
1          1             20
1          1             20      data transition
0          1             40

usw.

Dann ist das Clock signal wie oben aufgeführt 40µs high und 40µs low, 
entspricht einer frequenz von 12,5kHz. Im grünen Bereich.

So, jetzt gehts an die Programmierung!!!

von crazy horse (Gast)


Lesenswert?

Erklärs mir bitte noch mal: du willst ein paar Stunden programmieren 
(solange wirds dauern), ein Platine frickeln, Fehler suchen, 
Programmiereung ändern und und und. Mit Informationssuche und Fragen 
hast du jetzt schon ein paar Stunden vertan. Warum bitte schlachtest du 
nicht eine Tastatur? Nur um sagen zu können: ich habs selbst gemacht??
Eine gute Lösung ist immer auch eine effektive Lösung. Es gibt 
sinnvollere Projekte, wenn es dir ums Basteln geht.
kopfschüttelnd...

von Otto (Gast)


Lesenswert?

Moritz schrieb:

> Ist ein Projektsche was unsere hilflose Schule armen
> Oberstufenschülern aufhalst :-)... Moritz könnten Sie vielleicht mal ...

Otto

von crazy horse (Gast)


Lesenswert?

ja und?
Ich fänds cooler, wenn der gute Moritz am nächsten Morgenmit einer 
Blackbox auftaucht, 4 Drähte anknippert und die Sache läuft.
Es gibt keinen sinnvollen Grund, das selbst zu machen. Alte Tastaturen 
liegen eigentlich immer rum, und eine könnte sogar noch mal einer 
sinnvollen Verwendung zugeführt werden. Aber ne, nur nichts einfach 
machen.

von Moritz G. (moritz-)


Lesenswert?

Na wenn ich den Code erstmal habe, kann ich ja nach belieben Tastaturen 
bauen, mit nur den Tasten, die ich möchte.
Ich habe parallel eine Anfrage bekommen, ein keypad mit einigen Tasten 
zu bauen, um eine CNC-Fräse zu bedienen. Die Mechaniker wollen in der 
Werkstatt nämlich keine ganze Tastatur- und jedesmal eine schlachten ist 
doch Quatsch

ausserdem glaube ich fest daran, dass man auch noch ganz elegant mit 
bits schieben oder so, beliebige bytes senden kann...

von Moritz G. (moritz-)


Lesenswert?

Für eine Abkürzung ist mir kein Umweg zu weit.

von Otto (Gast)


Lesenswert?

> Für eine Abkürzung ist mir kein Umweg zu weit.

und: der Weg ist das Ziel...

Otto

von Dirk H. (arm-dran)


Lesenswert?

Moritz Greif wrote:
> Für eine Abkürzung ist mir kein Umweg zu weit.

Jetzt bruhigt Euch mal wieder.

@Crazy horse

Lass Moritz doch das machen. Auf jeden Fall sammelt er dabei 
Erfahrungen.
Wo ich Dir rechtgebe ist, wenn es schnell gehen soll. Da ist ne 
modifizierte
alte Tastatur mit Sicherheit die bessere Wahl.

@Moritz
Also wenn es schnell gehen soll, ne alte. Stell es Dir aber nicht ganz 
so einfach vor. Mit weglassen oder nicht reagieren auf Befehle vom PC, 
wirst
Du keinen Erfolg haben. Bereite Dich darauf vor, einen 2 Kanal Oszi auf
beide Leitungen zu hängen um mitzulauschen.

Und ganz wichtig, beide PortTreiber dürfen nur source current sein.
Mir highside Treiber zerstörst Du evtl. das Ganze.

Viel Erfolg

Dirk

von crazy horse (Gast)


Lesenswert?

Natürlich kann man das selbst programmieren, gar keine Frage. Noch dazu, 
da es völlig dokumentiuert ist und keinerlei echte Schnüffelarbeit zu 
leisten ist.
Egal, welche Spezialtastatur du brauchst-der Tastaturcontroller kann das 
alles. Es sei denn, du willst ganz eigene Tastaturcodes senden. Damit 
kann dann allerdings keine Software was anfangen, bleibt 
höchstwahrscheinlich schon im Betriebssystem stecken und würde nicht mal 
in einer eigenen Anwendungssoftware ankommen.
Und wenn du je auf einem Wertstoffhof o.ä. warst - dort lagern hunderte, 
die auf den Schredder warten. Fast jeder Computerladen, fast jede Firma, 
die mehr als 3 Computer hat, hat die Dinger rumliegen, garantiert auch 
in deiner Schule (dank Geldknappheit leben die meisten Computerräume von 
Schulen von Spendencomputern, dementsprechend kommt da auch reichlich 
Müll rein. Selbst neu kaufen kannst du die für 3€ (die Tasten selbst 
sind dann natürlich eher unbrauchbar). Und nun rechne mal deinen MC, 
Kabel mit PS2-Stecker, Platine.
Leg dich ins Bett und denke morgen noch mal vorurteilsfrei drüber nach.

von Bernd T. (bastelmensch)


Lesenswert?

Ich gebe da Crazy Horse recht.

Nimm so eine billig-Tastatur und dann bau das was Dich interessiert in 
ein kleines Gehäuse rein.

Damit hast Du bewiesen das Du Kostenbewußt arbeitest. (allerdings nicht 
sehr umweltfreundlich in diesem Fall)

von Christian U. (Gast)


Lesenswert?

Ich habs gestern gemacht da ichs für n Prüfgerät brauchte. War 20 min 
Arbeit danach liefs. Musste 2x mitm Oszi vergleichen. Wo bitte soll das 
Problem sein  einfach den io port schalten und _delay_us is auch 
erfunden. In der Wiki steht der aufbau schön erklärt. Da muss man nicht 
nen 80 Beitrags Thread draus machen.

von Ulf (Gast)


Lesenswert?

@Christian U.

Kannst Du den Code posten ?
Würde mich mal interessieren.

von Christian U. (z0m3ie)


Lesenswert?

Ich hab den code mal auf standart C umgebastelt im Prüfgerät nutz ich 
spezielle IO routinen. so sollt es gehn.
1
void PS2_init(void)
2
{
3
  PS2_DDR  |= ((1<<PS2_CLOCK)|(1<<PS2_DATA));
4
  PS2_PORT |= ((1 << PS2_CLOCK)|(1 << PS2_DATA));
5
}
6
7
void PS2_clock(void)
8
{
9
  _delay_us(15);
10
  PS2_PORT &= ~(1 << PS2_CLOCK)
11
  IO_set(PS2_CLOCK,1);
12
  PS2_PORT |= (1 << PS2_CLOCK)
13
  IO_set(PS2_CLOCK,0);
14
}
15
16
void PS2_send(uint8_t data)
17
{
18
  uint8_t tmp = data;
19
  uint8_t i;
20
  
21
  //Startbit
22
  PS2_PORT &= ~(1 << PS2_DATA)
23
  PS2_clock();
24
  //Daten
25
  for (i=0;i<8;i++)
26
    {
27
      if (tmp & 1)
28
        PS2_PORT &= ~(1 << PS2_DATA);
29
      else
30
        PS2_PORT |= (1 << PS2_DATA);
31
      tmp >>= 1; 
32
      PS2_clock();
33
    }
34
  //Parität
35
  if (tmp & 1)
36
    PS2_PORT &= ~(1 << PS2_DATA);
37
  else
38
    PS2_PORT |= (1 << PS2_DATA);
39
  PS2_clock();
40
  //Stopbit
41
  PS2_PORT |= (1 << PS2_DATA)
42
  PS2_clock();
43
  _delay_ms(1);
44
}

von Moritz G. (moritz-)


Lesenswert?

sowas in assembler wär cool.

Wie kann man einzelne Bits eines Registers rausbekommen, um die einzeln 
in einem Protokoll zu senden?
Hat da jemand einen Ansatz?

Meine Idee wäre, das Register erst mit 0b1000000 zu subtrahieren und 
gucken ob ein Überlauf entsteht, dann mit 0b01000000 , dann mit 
0b00100000, usw.
Doch ist das sehr umständlich und müsste wahrscheinlich ein 
timing-Problem mit dem Host geben.

Was ich im Prinzip möchte, ist ein Register, das man mit einem bel. Wert 
belädt, und dann eine Funktion "rcall send_register" , die dann die 8 
Datenbits mit Stopp,Parity, usw., an den PC sendet.

Bis jezt hab ich nur jedes Byte einzeln programmiert, was extrem nervig 
ist und nur für wenige machbar.

Gruss,
Moritz

von Karl H. (kbuchegg)


Lesenswert?

Moritz Greif wrote:
> sowas in assembler wär cool.
>
> Wie kann man einzelne Bits eines Registers rausbekommen, um die einzeln
> in einem Protokoll zu senden?
> Hat da jemand einen Ansatz?

Du kannst zb. die rotier oder schiebebefehle benutzen um
ein Register um 1 Bit nach Links zu rotieren (schieben).
Das Bit das links rausfällt landet im Carry Flag.
Und dann gibt es da noch Sprungbefehle, die abhängig davon
ob das Carry gesetzt ist einen Sprung durchführen oder nicht.

Studiere doch das mal, da wird das genau so benutzt:
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Schieberegister#Softwarem.C3.A4ssige_direkte_Ansteuerung


von Dirk H. (arm-dran)


Lesenswert?

@Christian U.

Und dieser Code soll funktionieren ?

Ahja...

Dann bitte mal das komplette Programm mit den beiden Tasten (2 Portpins 
zur Simulation dafür) und dem Protokoll-Handling, lauffähig mit jedem 
PC-PS2 Tastaturanschluß.

von Moritz G. (moritz-)


Lesenswert?

@Karl Heinz: Das war genau das, was ich gebraucht habe! Danke!°°°

von Christian U. (z0m3ie)


Lesenswert?

@Dirk Hofmann

hakts ?
Bin ich verpflichtet euch Code zur Verfügung zu stellen ?
Zur Information:

Ich benutze das um ein Embedded Device zu Testen keinen PC.
An dieses Device werden normalerweise PS/2 Tastaturen angeschlossen.
Deshalb brauch ich nur eine routine die mit PS/2 Protokolle sendet. Und 
das ist diese die ich gepostet hab.

>Und dieser Code soll funktionieren ?

Und ja sie hält sich exakt an die Spezifikation und funktioniert.
Ein PC sendet auch Daten an die Tastatur. Was mit diesen routinen 
natürlich nicht gegeben ist. Aber nachzuschauen ob der DATA port für > 
100us auf low ist und dann meine Clockroutine 11x aufzurufen und dabei 
nach jedem Aufruf den status von DATA in eien Variable zu schieben 
sollte kein Problem darstellen damit könnte man auch empfangen.

Ich hab mir die Mühe gemacht extra die Routinen umzubasteln da ich 
spezialisierte IO RRoutinen im PG habe. Und dann kommt wieder jemand wie 
herr Hofmann daher... Was bitte sollte daran denn nicht funktionieren ? 
Hast dus probiert ?

von Moritz G. (moritz-)


Lesenswert?

ok, hier mal meine vorläufige assembler-version
1
.include "m8def.inc"    ; alle Signale müssen noch invertiert werden!!!!
2
3
ldi r16, 0b00000110
4
out DDRB, r16
5
6
ldi r16, LOW(RAMEND)             ; LOW-Byte der obersten RAM-Adresse
7
out SPL, r16
8
ldi r16, HIGH(RAMEND)            ; HIGH-Byte der obersten RAM-Adresse
9
out SPH, r16
10
11
.def temp1=r20
12
.def temp2=r21
13
.def parity=r22
14
15
ldi parity, 1                    ; 0 ist ja gerade, gerade bedeutet parity = 1
16
17
protokoll:
18
sbi Portb, 1
19
sbi Portb, 2
20
21
init:
22
sbic pinb, 4
23
rjmp init
24
;---------------
25
;>>>>> temp1 ist zu übertragenes Byte
26
;>>>>> rcall Schiebe überträgt das Byte
27
;>>>>> danach sind DATA und CLOCK 1
28
29
loop:
30
;...hier kommen die Tastaturbefehle
31
rjmp loop
32
33
Schiebe:
34
rcall Startbit
35
36
    push  temp2
37
    ldi   temp2, 8             ; 8 Bits müssen ausgegeben werden
38
 
39
Schiebe_1:
40
     ;
41
     ; jeweils das höchstwetrige Bit aus temp1 ins Carry Flag schieben
42
     ; Je nach Zustand des Carry Flags wird die Datenleitung entsprechend
43
     ; gesetzt oder gelöscht
44
     ;
45
    rol  temp1                 ; HSB -> Carry
46
    brcs Schiebe_One           ; Carry gesetzt? -> weiter bei Schiebe_One
47
;------------------------; Eine 0 ausgeben-------------------------------------
48
sbi portb, 1
49
rcall warte
50
cbi Portb, 2
51
rcall warte
52
cbi portb, 1
53
rcall warte
54
rcall warte  
55
56
rjmp bitweiter
57
;-------------------------------------
58
59
Schiebe_One:
60
             ; Eine 1 ausgeben
61
sbi portb, 1
62
rcall warte
63
sbi Portb, 2
64
rcall warte
65
cbi portb, 1
66
rcall warte
67
rcall warte
68
;-------------parity aktualisieren
69
cpi parity, 0
70
brne wechsel
71
rjmp sonst
72
wechsel:
73
ldi parity, 0
74
rjmp ende
75
sonst:
76
ldi parity, 1
77
ende:
78
;---------------------------------
79
80
bitweiter: 
81
dec   temp2                ; Anzahl der ausgegebenen Bits runterzählen
82
brne  Schiebe_1            ; Wenn noch keine 8 Bits ausgegeben -> Schleife bilden
83
 
84
pop   temp2
85
86
parity_bit:
87
;----------------------
88
cpi parity, 0
89
breq null
90
rcall send_eins
91
rjmp ende_
92
null:
93
rcall send_null
94
ende_:
95
;----------------------
96
97
rcall stoppbit
98
99
ret
100
101
;---------------------------
102
Startbit:
103
;------------------
104
sbi Portb, 2
105
sbi portb, 1
106
rcall warte
107
cbi Portb, 2
108
rcall warte
109
cbi portb, 1
110
rcall warte
111
rcall warte
112
;------------------
113
ret
114
115
send_Null:
116
;------------------
117
sbi portb, 1
118
rcall warte
119
cbi Portb, 2
120
rcall warte
121
cbi portb, 1
122
rcall warte
123
rcall warte
124
;------------------
125
ret
126
Send_eins:
127
;------------------
128
sbi portb, 1
129
rcall warte
130
sbi Portb, 2
131
rcall warte
132
cbi portb, 1
133
rcall warte
134
rcall warte
135
;------------------
136
ret
137
Stoppbit:
138
;------------------
139
sbi portb, 1
140
rcall warte
141
sbi Portb, 2
142
rcall warte
143
cbi portb, 1
144
rcall warte
145
rcall warte
146
sbi Portb, 1
147
;------------------
148
ret
149
150
;Parity Bit:
151
; Gerade Anzahl von 1en => Parity ist 1
152
; ungerade Anzahl von 1en => Parity ist null
153
154
155
156
warte:  ;15µs
157
; ============================= 
158
;   Warteschleifen-Generator 
159
;     120 Zyklen:
160
; ----------------------------- 
161
; warte 120 Zyklen:
162
          ldi  R17, $28
163
WGLOOP0:  dec  R17
164
          brne WGLOOP0
165
; ============================= 
166
ret

von Roger S. (edge)


Lesenswert?

Christian Ulrich wrote:

> Was bitte sollte daran denn nicht funktionieren ?

entweder fasst dein uint8_t mehr als 8 bit oder dann wird die parity 
wohl kaum nach Spezifikation sein.

von Karl H. (kbuchegg)


Lesenswert?

1
;-------------parity aktualisieren
2
    cpi parity, 0
3
    brne wechsel
4
    rjmp sonst
5
wechsel:
6
    ldi parity, 0
7
    rjmp ende
8
sonst:
9
    ldi parity, 1

das ist aber mächtig kompliziert für
1
    eor parity, 0b00000001


logische Operation       Verwendung für
---------------------------------------
   ODER                  Bit setzen
   UND                   Bit löschen; Bit zum Abfragen ausmaskieren
   XOR                   Bit toggeln (aus 0 mach 1 und umgekehrt)

von Christian U. (Gast)


Lesenswert?

>entweder fasst dein uint8_t mehr als 8 bit oder dann wird die parity
>wohl kaum nach Spezifikation sein.

ups...
copy&paste lässt grüssen beim umbau hab ich das aus der schleife kopiert 
und vergessen aus tmp data zu machen :p
muss natürlich so aussehen:
1
void PS2_init(void)
2
{
3
  PS2_DDR  |= ((1<<PS2_CLOCK)|(1<<PS2_DATA));
4
  PS2_PORT |= ((1 << PS2_CLOCK)|(1 << PS2_DATA));
5
}
6
7
void PS2_clock(void)
8
{
9
  _delay_us(15);
10
  PS2_PORT &= ~(1 << PS2_CLOCK)
11
  IO_set(PS2_CLOCK,1);
12
  PS2_PORT |= (1 << PS2_CLOCK)
13
  IO_set(PS2_CLOCK,0);
14
}
15
16
void PS2_send(uint8_t data)
17
{
18
  uint8_t tmp = data;
19
  uint8_t i;
20
  
21
  //Startbit
22
  PS2_PORT &= ~(1 << PS2_DATA)
23
  PS2_clock();
24
  //Daten
25
  for (i=0;i<8;i++)
26
    {
27
      if (tmp & 1)
28
        PS2_PORT &= ~(1 << PS2_DATA);
29
      else
30
        PS2_PORT |= (1 << PS2_DATA);
31
      tmp >>= 1; 
32
      PS2_clock();
33
    }
34
  //Parität
35
  if (data & 1)
36
    PS2_PORT &= ~(1 << PS2_DATA);
37
  else
38
    PS2_PORT |= (1 << PS2_DATA);
39
  PS2_clock();
40
  //Stopbit
41
  PS2_PORT |= (1 << PS2_DATA)
42
  PS2_clock();
43
  _delay_ms(1);
44
}

von Roger S. (edge)


Lesenswert?

Christian U. wrote:
> muss natürlich so aussehen:
> [snip]

Nicht wirklich. Das hat nichts mit parity zu tun. Du sendest lediglich 
das LSB nochmals.

Der assembler source von Moritz koennte diesbezueglich wohl eher korrekt 
sein. Aber wer will sich schon durch einen Meter bit-banging in asm 
hangeln.

von Christian U. (z0m3ie)


Lesenswert?

hast recht.
hat wohl eher durch zufall bei den 2 werten für die ich die routine 
geschrieben habe funktioniert.
1
  //Parität
2
  uint8_t parity = 0;
3
  tmp = data;
4
  for (i=0;i<8;i++)
5
    {
6
      parity += tmp&1;
7
      tmp<<=1;
8
    }
9
  if (parity & 1)
10
    PS2_PORT &= ~(1 << PS2_DATA);
11
  else
12
    PS2_PORT |= (1 << PS2_DATA);
13
  PS2_clock();
14
  //Stopbit

von Roger S. (edge)


Lesenswert?

@ Christian Ulrich

vom prinzip her kommts langsam, bloss wird tmp noch in die falsche 
richtung geshiftet und somit falsch berechnet. Ausserdem wird mit der 
addition die gerade paritaet gebildet. PS2 ist aber odd parity.

Zudem komm ich mit deinem Port handling nicht ganz klar, leben deine 
Daten in einer bit invertierten Welt?

von Dirk H. (arm-dran)


Lesenswert?

@Christian Ulrich

nochmal ahjaaaa....

zufällig hab ich die PS2-PC Seite als TaktSlave emuliert und ist in 
vielen
Geräten 100% aktiv.
Ich weiß also wovon ich rede.

Schau Dir lieber nochmal Deinen Code an, bevor Du ihn 10mal korrigierst.

Dirk

von Moritz G. (moritz-)


Lesenswert?

@Karl Heinz: das mit dem eor werd ich sofort übernehmen, Danke!!!

Morgen werd ich den Code testen und verschönern, soweits geht.
Wenn alles klappt, dann kommt auch ne Empfangsfunktion rein, um ne 
exacte kommunikation mit dem PC zu erreichen. Empfangen ist ja 
eigentlich bloss umgekehrt Bits schieben. Wie Christian Ulrich schrieb:

> Aber nachzuschauen ob der DATA port für >
> 100us auf low ist und dann meine Clockroutine 11x aufzurufen und dabei
> nach jedem Aufruf den status von DATA in eien Variable zu schieben
> sollte kein Problem darstellen damit könnte man auch empfangen.

Gruss, Moritz

...doof kann man sein, man muss sich nur zu helfen wissen :-)

von Moritz G. (moritz-)


Lesenswert?

HEy ich habe nochmal ne Frage, weil mei mir das nicht einwandfrei 
funktioniert mit der Tastatur.

Wenn ich den PC mit dem µC am PS2 boote, reicht es da, wenn ich CLOCK 
und DATA auf High lege, (der PC zieht sie ja dann auf Low, wenn er 
beschäftigt ist), ich müsste dann nur überprüfen, ob die Leitungen 
(wieder) high sind, und dann kann ich ihm Daten senden, richtig?

Also ignoriere ich quasi alle seine Anfragen zu ID, Einstellungen, usw.

Otto (Gast) schrieb:
> Für den PC ist die Welt in Ordnung,
> wenn die Leitungen High-Pegel haben.

Oder liege ich da falsch??? Funktionierts hats bis jetzt noch nicht, 
eventuell liegt aber noch ein Code- oder anderes Problem vor.

Gruss,
Moritz

von Otto (Gast)


Lesenswert?

Hallo Moritz,

bei mir war es so - wenn eine Leitung auf "Low"
ist, meckert er beim "booten" über "keyboard error"
oder so.

Es was bei mir auch nicht so einfach, bis es
funktionierte - wenn ich mir recht erinnere,
wurde jede Taste sofort 1x erkannt, dann aber
erst wieder, wenn "ihr" "Release-Code" erkannt
wurde.

Gruß Otto

von Dirk H. (arm-dran)


Lesenswert?

@Moritz

Es gibt zwei Optionen um die Leitungen wahlweise auf 0 zu ziehen.
1.) Um zu verhindern, daß die Tastatur Daten sendet (interner Puffer)

2.) Um der Tastatur mittzuteilen, daß der Master Daten an die Tastatur 
senden
möchte.

Der PC kommuniziert mit der Tastatur. Seine Anfragen zu ignorieren wird
keine korrekte Funktion zur Folge haben.

Dirk

von Moritz G. (moritz-)


Lesenswert?

auf http://www.marjorie.de/ps2/ps2_keyboard.htm findet man einen 
möglichen Ablauf beim booten:

Tastatur: AA  Selbsttest bestanden         ;Keyboard controller init
Host:     ED  Setzen der Status-LEDs
Tastatur: FA  Acknowledge
Host:     00  Alle LEDs aus
Tastatur: FA  Acknowledge
Host:     F2  Lese ID
Tastatur: FA  Acknowledge
Tastatur: AB  Erstes Byte der ID
Host:     ED  Setzen der Status-LEDs       ;BIOS init
Tastatur: FA  Acknowledge
Host:     02  Num Lock LED an
Tastatur: FA  Acknowledge
Host:     F3  Wiederholrate einstellen     ;Windows init
Tastatur: FA  Acknowledge
Host:     20  500 ms / 30.0 Zeichen/sec
Tastatur: FA  Acknowledge
Host:     F4  Enable
Tastatur: FA  Acknowledge
Host:     F3  Wiederholrate einstellen
Tastatur: FA  Acknowledge
Host:     00  250 ms / 30.0 Zeichen/sec
Tastatur: FA  Acknowledge


Meint ihr, dass ich dieses komplizierte Startverfahren durchlaufen 
lassen muss, beim booten, nur dass ich dann am Ende "Pfeil Up" und 
"Pfeil down" senden kann?...
krass

von Dirk H. (arm-dran)


Lesenswert?

Ja, so sieht es wohl aus.

Aber was soll daran kompliziert sein?

Wie gesagt, daß wichtige ist, mit ACK (FA) zu antworten, damit der PC
weiß, daß die Tastatur angeschloßen ist.
Wenn Du zum Beispiel Daten zum setzen der LEDs empfängst, dann 
bestätigst
Du das, musst ja aber deswegen keine einschalten.

Es ist eben wichtig, eine PS2 Tastatur zu emulieren.

Es ist nicht schwer aber man muß es tun. Sonst geht nix.

Dirk

von Otto (Gast)


Lesenswert?

Hallo Moritz,

wie bereits beschrieben, reichte (bei mir):

- beide Leitungen high-Pegel beim "booten"
- anfänglich das "Totstellen" auf die Anfragen des Hosts und
- das Senden der Daten.

Sobald der Host Reaktionen zeigt, habe ich anfangs die
Übertragung abgebrochen.

Später habe ich es dann erweitert.

Gehe mal davon aus, wenn Dein Timing stimmt, das Startbit
und 8 Bit und das Stopbit gesendet werden, kommt auch
etwas bei "Deinem" PC an.

Otto

von Moritz G. (moritz-)


Lesenswert?

Ok, ich probiers jetzt erstmal auf die Otto-Version aus, wenns nicht 
klappt, gibts die Dirk-Version. Bei der Dirk Version muss ich mich dann 
nochmal um das Empfangen kümmern, ist ja nochmal ein bissl Arbeit.
Danke,
Moritz

von MisterMime (Gast)


Lesenswert?

Servus,

wie ich sehe arbeitet ihr gerade mit dem Tastaturprotokoll.

Ich wollte/will noch immer ein Gerät bauen, dass auf einen Tastendruck 
reagiert; Es soll nur "lauschen", mehr nicht. Es funktioniert aber immer 
noch nicht ;).

Könnetet ihr euch mal diesen Thread anschaun? :
Beitrag "AT-Tastatur - PC - µC "einschleifen" -> RS232"

Vielleicht hilft er auch ein bisschen.

Ich bin mir sicher, dass irgendwo ein einziger "wait"-Befehl fehlt, aber 
wo nur :).


Mfg

MisterMime

von Otto (Gast)


Lesenswert?

Hallo MisterMime,

das wird dem Moritz sicher weiterhelfen - nur Dir nicht.

Als ich damit gekämpft habe, habe ich zu "debug-Zwecken"
abwechselnd sowohl das Empfangene als auch das Gesendete
auf einem LCD ausgegeben - so habe ich dann so manche
Fehler erkennen können - speziell die Timing Probleme
könntest Du so überprüfen.

Gruß Otto


von Marc (Gast)


Lesenswert?

Hallo,

habe vorhin diesen Beitrag eröffnet: 
Beitrag "PS/2 Protokoll auf AVR - Tastatur (Maus) emulieren, Fragen zur Schaltung und Programm"

und bin, nachdem ich etliche Male die Suche bemüht habe auf diesen 
interessanten Thread gestoßen.
Vielleicht kann mir ja hier jemand mit meinen grundsätzlichen Fragen 
helfen:

Wie sieht die physikalische Verbindung nun genau aus, wenn ich nur den 
uC an den PS/2 des PCs anschliessen möchte (keine Tastatur oder so 
dran)?

Wie löst man denn am besten die Initialisierung, so dass der PC 
überhaupt bereit ist Daten entgegen zu nehmen? (Ich habe auch gelesen 
was hier steht, nur dummerweise ist der Thread ohne eine endgültige 
Klärung abgerissen)

Um die Leitungen LOW oder HIGH zu setzen, reicht es doch eine 0 oder 
eine 1 an dem I/O auszugeben oder muss ich noch etwas beachten?

Wie bestimme ich das Timing um im richtigen Augenblick die Leitungen LOW 
oder HIGH zu setzen, brauche ich dazu den Timer0 (hat irgendwo mal 
jemand geschrieben) oder lässt sich das anders lösen?

Mit welcher Taktfrequenz sollte der atmega8 dann am besten laufen, 
reichen 4 oder 8 MHz oder sollten es schon 16 MHz sein?

Ein Beispiel Assembler Code, der z.B. einfach ein Zeichen in einer 
Schleife wiederholt an den PC sendet wäre und zum allgemeinen 
Verständnis bestimmt hilfreich.

Es wäre nett, wenn mir das vielleicht jemand erklären könnte oder mir 
vielleicht entsprechende Links zukommen lassen kann, ich bin noch neu 
was diese ganzen Mikrocontroller Geschichten angeht aber lernwillig...

Gruß,
Marc

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.