PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PS/2 Tastatur auslesen



EagleStar
27.05.2008, 19:25
Hallo zusammen,

Ich habe gerade einen Versuchsaufbau mit einer PS/2 Tastatur gemacht.
Hardware:
Spannungsversorgung extern +5V=
Pin 1 <-> PinD.2 = KB-Data
Pin 5 --> PinD.4 = KB Clock
Das ganze mit einem Atmega8515L mit 8MHz auf dem STK500

Software:

$regfile = "m8515.dat"
$framesize = 32
$swstack = 32
$hwstack = 32
$crystal = 8000000

$baud = 19200

Config Keyboard = Pind.2 , Data = Pind.4 , Keydata = Keydata

Dim Key As Byte

Print "Los gehts"

Do
Key = Getatkbd()
If Key <> 0 Then
Print "Taste " ; Chr(key) ; " " ; Key
End If
Loop
End

Keydata:
'normal keys lower case
Data 0 , 0 , 0 , 0 , 0 , 200 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , &H5E , 0
Data 0 , 0 , 0 , 0 , 0 , 113 , 49 , 0 , 0 , 0 , 122 , 115 , 97 , 119 , 50 , 0
Data 0 , 99 , 120 , 100 , 101 , 52 , 51 , 0 , 0 , 32 , 118 , 102 , 116 , 114 , 53 , 0
Data 0 , 110 , 98 , 104 , 103 , 121 , 54 , 7 , 8 , 44 , 109 , 106 , 117 , 55 , 56 , 0
Data 0 , 44 , 107 , 105 , 111 , 48 , 57 , 0 , 0 , 46 , 45 , 108 , 48 , 112 , 43 , 0
Data 0 , 0 , 0 , 0 , 0 , 92 , 0 , 0 , 0 , 0 , 13 , 0 , 0 , 92 , 0 , 0
Data 0 , 60 , 0 , 0 , 0 , 0 , 8 , 0 , 0 , 49 , 0 , 52 , 55 , 0 , 0 , 0
Data 48 , 44 , 50 , 53 , 54 , 56 , 0 , 0 , 0 , 43 , 51 , 45 , 42 , 57 , 0 , 0

'shifted keys UPPER case
Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
Data 0 , 0 , 0 , 0 , 0 , 81 , 33 , 0 , 0 , 0 , 90 , 83 , 65 , 87 , 34 , 0
Data 0 , 67 , 88 , 68 , 69 , 0 , 35 , 0 , 0 , 32 , 86 , 70 , 84 , 82 , 37 , 0
Data 0 , 78 , 66 , 72 , 71 , 89 , 38 , 0 , 0 , 76 , 77 , 74 , 85 , 47 , 40 , 0
Data 0 , 59 , 75 , 73 , 79 , 61 , 41 , 0 , 0 , 58 , 95 , 76 , 48 , 80 , 63 , 0
Data 0 , 0 , 0 , 0 , 0 , 96 , 0 , 0 , 0 , 0 , 13 , 94 , 0 , 42 , 0 , 0
Data 0 , 62 , 0 , 0 , 0 , 8 , 0 , 0 , 49 , 0 , 52 , 55 , 0 , 0 , 0 , 0
Data 48 , 44 , 50 , 53 , 54 , 56 , 0 , 0 , 0 , 43 , 51 , 45 , 42 , 57 , 0 , 0

Jetzt hab ich das Problem, dass wenn ich auf der Tastatur eine Taste drücke wird mir irgend eine Taste angezeigt und auch beim mehrmaligen drücken derselben Taste bekomm ich immer wieder andere Zeichen ausgespuckt.

Kann mir jemand einen Tipp geben woran das liegen könnte?

MfG EagleStar

guenter1604
01.06.2008, 23:03
Schau mal da vorbei...

http://www.gerold-online.de/cms/index.php?id=136

Ich hab das mit einem ext. Interrupt realisiert, der die Clockleitung prüft.


P.S. Trochtelfingen ? Das ist ja gleich um die Ecke...

EagleStar
03.06.2008, 12:29
Danke für den Link.
Ich denke da muss ich mich erstmal durchfuchsen!
Aber ein guter Tipp der mir weiterhilft. THX

MfG EagleStar

PS: Um die Ecke von?

guenter1604
03.06.2008, 13:49
Hallo,


P.S. Röhlingen ;-)

Jaecko
03.06.2008, 14:24
Die Idee mit der Data-Leitung auf nem INT is ja genial; um einiges besser als das mit dem ERR-Bit.

guenter1604
03.06.2008, 22:56
Hallo Jaecko,

kann man folgende pauschale Aussage treffen:

Alles was sich ständig ändert in die Hauptschleife packen. Was jedoch nur einmal in 1000 Jahren passiert (Tastendruck Fernbedienung oder Tastatur) möglichst auf einen Interrupt auslagern. Ziel ist die Hauptschleife möglichst kurz zu halten? :-s

Jaecko
03.06.2008, 23:12
Hm jein... eher nicht.
Normalerweise ist es so: Alles in die Main-Loop und in die Interrupts so kurz wie nur irgendwie möglich.
Dauert die ISR nämlich so lange, dass in deren Abarbeitung der Interrupt bereits ein weiteres Mal aufgerufen wird, dann kanns Probleme geben.
Also eine Timer-ISR, die im Sekundentakt aufgerufen wird und dort die Anweisung "WAIT 2" ausführt wird etwas Stress machen.

Will man auf ein Ereignis reagieren, kann man entweder den ganzen Code direkt in der ISR abarbeiten, oder man setzt nur ein Flag, das dann in der Main-Loop bei jedem Durchlauf geprüft und der Code dann entsprechend abgearbeitet wird.
(If FlagXYZ = 1 Then...)

Wie man das macht, kommt halt drauf an, wie "wichtig" das Ereignis ist. Muss z.B. sofort drauf reagiert werden (Not-Aus, ankommende Daten), ist es sicher sinnvoll, den Code direkt in der ISR zu bearbeiten.

Will man aber z.B. nur den Status eines Geräts erfassen (z.B. SD-Kartenslot, Signal "Karte steckt"), reicht es, in der ISR ein Flag zu setzen.
Wobei ein Interrupt hier aber schon fast wieder übertrieben scheint, da normales "Polling" auch reicht.

Interrupts sind auch sinnvoll, um kurze Pinänderungen "aufzuspüren";
Würde man einen Pin nur in der Main-Loop pollen, könnte der sich ändern, ohne dass das Programm was mitbekommt.
Mit dem Interrupt wird die Änderung registriert => Flag setzen und schon hat man die Änderung.

So wie ich das Programm mit der Tastatur verstanden hab, muss die Tastatur unmittelbar nach Auftreten eines Clock-Pulses ausgelesen werden, da die Daten sonst verloren gehen; also warten, bis in der Main-Loop irgendwann mal das Flag überprüft wird, geht nicht.
Das Auswerten, also WELCHE Taste da nun gekommen ist, könnte man dann durchaus in die Main-Loop auslagern.

guenter1604
03.06.2008, 23:45
verstehe, es kommt auf die Prioritäten an. In meinem Beispiel war die oberste Priorität die Abarbeitung der seriellen Schnittstelle, denn hier passiert der meiste Verkehr. Damit diese möglichst schnell Befehle zum nächsten Modul weiterleitet, musste die Hauptschleife so kurz wie möglich gehalten werden. Tastatur muss sofort ausgewertet werden, da sonst die Eingabe zu zäh wird und Buchstaben verschluckt werden. Die Fernbedienung setzt nur ein Flag im Interrupt, damit der Prozessor nur minimal durch den Interrupt in der Ausführung gebremst wird.

EagleStar
14.06.2008, 11:30
Hi zusammen,

der Code sieht an und für sich ganz gut aus. Ich habe nur das Problem, dass ich den Code mit der DEMO nicht compiliert bekomme. Kann mir vielleicht jemand die HEX-Dat schicken für einen Atmega8515 mit 8MHz schicken?

Hatte Probleme den Code so zu verkleinern, dass ich die 2kB nicht überschreite. Jedoch trotz entfernung RC5 etc hab ich das nicht erreicht.

MfG EagleStar

guenter1604
14.06.2008, 12:04
Hallo EagleStar,

den Code hab ich mal auf das nötigste zusammengestutzt.

Das müsste jetzt auch mit der Testversion klappen. Den Code hab ich ab nicht getestet, aber das kriegst du sicher hin wenn da noch ein Fehler drin wäre ;-)



'---------------------------------------------------------------------------
' PS2-Tastatur
'
' Günter Gerold
'---------------------------------------------------------------------------

$regfile = "m8def.dat"
$crystal = 8000000
$baud = 38400

$hwstack = 40
$swstack = 16
$framesize = 32

Declare Sub Writeserinp
Declare Sub Lcdanzeige

Config Serialin = Buffered , Size = 63
Config Serialout = Buffered , Size = 63
Config Lcdpin = Pin , Db4 = Portc.2 , Db5 = Portc.3 , Db6 = Portc.4 , Db7 = Portc.5 , E = Portb.1 , Rs = Portb.0
Config Lcdbus = 4
Config Lcd = 16 * 2
Config Keyboard = Pind.2 , Data = Pind.6 , Keydata = Keydata
Config Watchdog = 512 'Mit dem Watchdogtimer ist das an- und abstecken der Tastatur im Betrieb möglich

On Int0 Isr0
Enable Int0
Config Int0 = Falling

Dim Lcd_dirty As Bit
Dim Serinpstr As String * 63
Dim Strsize As Byte
Dim Strlang As Byte
Dim Fbstring As String * 33
Dim Lcdstring As String * 33
Dim Lcdstringptr(33) As Byte At Lcdstring Overlay
Dim Lcdstringoben As String * 16
Dim Lcdstringunten As String * 16
Dim Taste As Word
Dim Timerlearn As Bit
Dim Lcd_command As Bit

Dim Ib As Byte

Deflcdchar 4 , 14 , 17 , 17 , 22 , 17 , 25 , 22 , 16 ' ß
Deflcdchar 1 , 17 , 14 , 17 , 17 , 31 , 17 , 17 , 32 ' Ä
Deflcdchar 2 , 17 , 14 , 17 , 17 , 17 , 17 , 14 , 32 ' Ö
Deflcdchar 3 , 17 , 32 , 17 , 17 , 17 , 17 , 14 , 32 ' Ü

Enable Interrupts
Echo Off
Cursor Off
Start Watchdog
Cls

Do
If Lcd_dirty = 1 Then
Lcd_dirty = 0
Call Lcdanzeige
End If
Reset Watchdog
Loop

'---------------------------------------------------------------------------
' Writeserinp
' Leitet den empfangenen String zum nächsten Modul weiter
'---------------------------------------------------------------------------

Sub Writeserinp
Print Serinpstr ' Befehl Weiterreichen
End Sub

'---------------------------------------------------------------------------
' LCD Anzeige
'
' Routine zum konvertieren des FBstrings für LCD.
' die Sonderzeichen haben andere Asciicodes...
' Zeilenumbruch des Displays
'---------------------------------------------------------------------------
Sub Lcdanzeige

Lcdstring = Fbstring
For Ib = 1 To Len(lcdstring)
Select Case Lcdstringptr(ib)
Case 129:
Lcdstringptr(ib) = 245
Case 132:
Lcdstringptr(ib) = 225
Case 148:
Lcdstringptr(ib) = 239
Case 225:
Lcdstringptr(ib) = 4
Case 142:
Lcdstringptr(ib) = 1
Case 153:
Lcdstringptr(ib) = 2
Case 154:
Lcdstringptr(ib) = 3
End Select
Next Ib 'nächstes zeichen
Locate 1 , 1
Lcdstringoben = Left(lcdstring , 16)
Lcd Lcdstringoben ; " "
Lowerline
Strsize = Len(lcdstring)
Lcdstringunten = Mid(lcdstring , 17 , 32)
Lcd Lcdstringunten ; " "
If Lcd_command = 1 Then
Stop Watchdog
Waitms 500
Start Watchdog
Fbstring = ""
Lcd_command = 0
Lcd_dirty = 1
End If
End Sub


'---------------------------------------------------------------------------
' Isr0
' Interruptroutine für die Tastatur
' der externe Interrupt 0 überwacht die Dataleitung der Tastatur
'---------------------------------------------------------------------------
Isr0: 'interrupt routine
Taste = Getatkbd() 'Get data from AT keyboard
Select Case Taste
Case 13:
Serinpstr = Fbstring
Fbstring = ""
Call Writeserinp
Case 8:
If Len(fbstring) = 1 Then
Fbstring = ""
Else
Strlang = Len(fbstring) - 1
Fbstring = Left(fbstring , Strlang)
End If
Case 171: 'F-Tasten auslesen
Readeeprom Fbstring , 1
Lcdstring = Fbstring
Case 172:
Readeeprom Fbstring , 31
Lcdstring = Fbstring
Case 173:
Readeeprom Fbstring , 61
Lcdstring = Fbstring
Case 174:
Readeeprom Fbstring , 91
Lcdstring = Fbstring
Case 175:
Readeeprom Fbstring , 121
Lcdstring = Fbstring
Case 176:
Readeeprom Fbstring , 151
Lcdstring = Fbstring
Case 177:
Readeeprom Fbstring , 181
Lcdstring = Fbstring
Case 178:
Readeeprom Fbstring , 211
Lcdstring = Fbstring
Case 179:
Readeeprom Fbstring , 241
Lcdstring = Fbstring
Case 181: 'Shift und F-Taste: Befehl unter F-Taste speichern
Writeeeprom Fbstring , 1
Timerlearn = 1
Case 182:
Writeeeprom Fbstring , 31
Timerlearn = 1
Case 183:
Writeeeprom Fbstring , 61
Timerlearn = 1
Case 184:
Writeeeprom Fbstring , 91
Timerlearn = 1
Case 185:
Writeeeprom Fbstring , 121
Timerlearn = 1
Case 186:
Writeeeprom Fbstring , 151
Timerlearn = 1
Case 187:
Writeeeprom Fbstring , 181
Timerlearn = 1
Case 188:
Writeeeprom Fbstring , 211
Timerlearn = 1
Case 189:
Writeeeprom Fbstring , 241
Timerlearn = 1
Case 190: 'Rollen: Befehl ständig senden


Case 191: 'Shift und Rollen: Das Timerarray wird programmiert

Case Else:
If Taste <> 0 Then
Fbstring = Fbstring + Chr(taste)
End If
End Select
'End If
Set Gifr.intf0
Taste = 0
Lcd_dirty = 1
Return

'---------------------------------------------------------------------------
' Keydata
' Codetabelle für die Tastatur
' da Tastaturen keinen Ascii-Code ausgeben wird in dieser Tabelle
' jeder Taste ein Ascii-Code zugewiesen
'---------------------------------------------------------------------------
Keydata:
'Kleinbuchstaben
Data 0 , 179 , 0 , 175 , 173 , 171 , 172 , 0 , 0 , 180 , 178 , 176 , 174 , 0 , 0 , 0
Data 0 , 0 , 0 , 0 , 0 , 113 , 49 , 4 , 4 , 4 , 121 , 115 , 97 , 119 , 50 , 0
Data 0 , 99 , 120 , 100 , 101 , 52 , 51 , 4 , 4 , 32 , 118 , 102 , 116 , 114 , 53 , 0
Data 0 , 110 , 98 , 104 , 103 , 122 , 54 , 7 , 8 , 44 , 109 , 106 , 117 , 55 , 56 , 0
Data 0 , 44 , 107 , 105 , 111 , 48 , 57 , 4 , 4 , 46 , 45 , 108 , 148 , 112 , 225 , 0
Data 0 , 0 , 132 , 228 , 129 , 92 , 4 , 4 , 4 , 4 , 13 , 4 , 4 , 35 , 0 , 0
Data 0 , 60 , 0 , 0 , 0 , 0 , 8 , 0 , 0 , 49 , 0 , 52 , 55 , 0 , 0 , 0
Data 48 , 44 , 177 , 53 , 54 , 56 , 0 , 0 , 0 , 43 , 51 , 45 , 42 , 57 , 190 , 0

'Grossbuchstaben
Data 0 , 189 , 0 , 185 , 183 , 181 , 182 , 0 , 0 , 0 , 188 , 186 , 184 , 0 , 0 , 0
Data 0 , 0 , 0 , 0 , 0 , 81 , 33 , 0 , 0 , 0 , 89 , 83 , 65 , 87 , 34 , 0
Data 0 , 67 , 88 , 68 , 69 , 0 , 35 , 0 , 0 , 32 , 86 , 70 , 84 , 82 , 37 , 0
Data 0 , 78 , 66 , 72 , 71 , 90 , 38 , 0 , 0 , 76 , 77 , 74 , 85 , 47 , 40 , 0
Data 0 , 59 , 75 , 73 , 79 , 61 , 41 , 0 , 0 , 58 , 95 , 76 , 153 , 80 , 63 , 0
Data 0 , 0 , 142 , 0 , 154 , 96 , 0 , 0 , 0 , 0 , 13 , 94 , 0 , 42 , 0 , 0
Data 0 , 62 , 0 , 0 , 0 , 8 , 0 , 0 , 49 , 0 , 52 , 55 , 0 , 0 , 0 , 0
Data 48 , 44 , 187 , 53 , 54 , 56 , 0 , 0 , 0 , 43 , 51 , 45 , 42 , 57 , 191 , 0

guenter1604
14.06.2008, 13:19
Hallo,

der 8515 hat nur halb soviel SRAM wie der ATMega 8. Deshalb wird das kompl. Programm nicht laufen. Da wäre eine Variablendiät nötig ;-)

a6000000
29.12.2008, 21:03
delete delete delete

a6000000
29.12.2008, 21:05
vielleicht auch nuetzlich:
www.beyondlogic.org//keyboard//keybrd.htm
interfacing a keyboard
ziemlich umfassend