Forum: Mikrocontroller und Digitale Elektronik PS/2 mit Assembler - Fehler wegen Interrupts


von Malte B. (oberammergau)


Lesenswert?

Liebes Forum,

ich bin gerade für ein Projekt dabei, eine PS/2 Tastatur mit einem 
Atmega 16 auszulesen. Mein bisheriges Ziel war eigentlich nur, die von 
der Tastatur gesendeten Scancodes zu empfangen und über LEDs auszugeben.

Mein Code funktioniert im Prinzip so:
Tastatur CLK an INT2 (INT0 & 1 sind leider schon belegt) löst Interrupt 
bei fallender Flanke aus.
Es wir geprüft ob dies das Startbit ist, falls ja wird es nicht 
gespeichert, sondern einfach ein Zählregister inkrementiert.
In den darauffolgenden 8 Interrupts wird zunächst das Empfangsregister 
rotiert, sodass das LSB für das nächste am Data-Eingang anliegende Bit 
(PortB.3) frei wird. Das Paritätsbit wird wiederum herausgefiltert, und 
wenn das Stopbit empfangen wurde, wird das nun in Temp3 gesicherte Byte 
an PORTD ausgegeben. Dann werden die Variablen resettet um die nächste 
Übertragung abzuwarten.

Wenn ich das Programm nun auf dem µC habe, bekomme ich keine Ausgabe 
über die LEDs (beim normalen Durchlauf). Wenn ich es über einen JTAG 
debugge, wird immer ein Interrupt aktiviert (auch wenn keine Taste 
gedrückt wird) und es werden auch Bytes ausgegeben. Die haben allerdings 
noch keinen kausalen Zusammenhang mit den Scancodes.

Danke für jede Hilfe :)

EDIT: Habe den Code nochmal überarbeitet, selbes Problem:
1
.include "m16def.inc"
2
3
.def temp = r16
4
.def temp2 = r17
5
.def temp3 = r18
6
7
.org 0
8
    rjmp init
9
.org INT2addr
10
        rjmp int2_handler    
11
12
init:  ldi temp, LOW(RAMEND) ;Stack-Init
13
        out SPL, temp
14
        ldi temp, HIGH(RAMEND)
15
        out SPH, temp
16
17
    ldi temp, 0xFF
18
    out ddrd, temp
19
20
    ldi temp, 0b11110011  ;interrupt eingang portb2 + data leitung pordb3
21
        out DDRb, temp
22
23
    ldi temp, (1<<2)|(1<<3)
24
    out PORTB, temp
25
26
    ldi temp, (1<<INT2)
27
    out GICR, temp
28
    
29
    clr temp2
30
    clr temp3
31
32
    sei
33
34
loop:  rjmp loop
35
36
37
;Interrupt
38
int2_handler:
39
40
    cpi temp2, 1
41
    brlo skipbit ;Startbit
42
    
43
    cpi temp2, 0x0A ;Alles empfangen?
44
    brsh ausgabe
45
    
46
    cpi temp2, 0x09 ;Paritätsbit?
47
    brsh skipbit
48
    
49
    clc
50
    ror temp3 ; ausleseregister rotieren für nächsten Eingabe
51
52
    in temp, pinb
53
    bst temp, 3 ;Nächstes Bit ins Ausleseregister
54
    bld temp3, 7
55
56
57
skipbit:inc temp2
58
    reti
59
60
ausgabe:out portd, temp3
61
62
    clr temp3
63
    clr temp2
64
    reti

von Mark L. (Firma: TH Köln) (m2k10) Benutzerseite


Lesenswert?

Malte B. schrieb:
> Es wir geprüft ob dies das Startbit ist

Das siehst du etwas falsch, du prüfst nur deinen Zähler und setzt dabei 
voraus, dass das Startbit dann kommt, wenn dieser auf 1 steht, selbst 
wenn das (falsche) 'Startbit' eine 1 ist. Mit viel Glück könnte das 
funktionieren, aber bei jeglichem Fehler läuft das sofort aus dem Ruder. 
Der int-IRQ ohne Noise-Canceler reagiert auch empfindlich auf Störungen.

Hab grad nicht im Kopf, wie's genau geht, aber du müsstest das Startbit 
als solches identifizieren (bspw. warten bis CLK >50µs high und dann 
erste fallende Flanke, wenn DAT auf low dann Startbit) und dann erst den 
Zähler starten und die nachfolgenden bits einlesen. Oder, falls noch 
frei, könntest du auch einfach den USART nehmen und dir die ganze Arbeit 
sparen(synchr.USART, odd-Parity und CLK und RxD mit pull-up an die 
Tastatur).

Mark

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.