Forum: Mikrocontroller und Digitale Elektronik AVR - Port einlesen/ausgeben


von Neuling (Gast)


Lesenswert?

Hi,

ich bin gerade dabei, mich ein bisschen in die AVR Architektur 
einzuarbeiten und möchte dazu mal mit einem einfachen Assembler Programm 
starten.
Folgendes hätte ich mir überlegt: Am Port PA hängen 4 LEDs (PA4 - PA7) 
und 4 Taster (PA0 - PA3). Wenn nun Taster 1 oder Taster 2 gedrückt wird, 
dann soll die an PA7 angeschlossene LED leuchten.

Mein Programm sieht folgendermaßen aus:
1
     
2
    .equ temp, 0x10 ;Register r16
3
     
4
    .section .text ;in den Flash Speicher
5
     
6
     
7
    jmp main
8
     
9
    upro:
10
    in temp, PINA ;lese von A
11
    andi temp, ((1<<0) | (1<<1)) ;maskiere A mit 0x03
12
    breq led_aus ;wenn Zero-Flag gesetzt (also UND Verknuepfung 0 ist)
13
    sbi PORTA, 7 ;aktiviere LED7
14
    jmp return
15
    led_aus: cbi PORTA, 7 ;deaktivere LED7
16
     
17
    return: ret
18
     
19
    main:
20
    ;###########Stack Pointer initialisieren#########
21
    ldi r16, lo8(RAMEND)
22
    out SPL, r16
23
    
24
    ldi temp, hi8(RAMEND)
25
    out SPH, temp
26
    ;################################################ 
27
 
28
    ;PA0 - PA3 als Input (=Taster) und PA4 - PA7 als Output (=LEDs)
29
    ldi temp, 0b11110000
30
    out DDRA, temp
31
     
32
    ;Pullup für PA0 - PA3 aktivieren
33
    ldi temp, 0b00001111
34
    out PORTA, temp
35
     
36
    loop:
37
    rcall upro
38
    jmp loop

Doch leider funktioniert mein Programm nicht. Egal ob ich Taster 1 oder 
Taster 2 drücke (oder nicht drücke), der Zustand der LED ändert sich 
nicht.
Ich würde mich freuen, wenn sich hier jemand die Mühe machen würde, 
einen Blick auf den Sourcecode zu werfen, um mich auf meine(n) Fehler 
aufmerksam zu machen.

Ich danke euch!

von holger (Gast)


Lesenswert?

>einzuarbeiten und möchte dazu mal mit einem einfachen Assembler Programm
>starten.

Dann mach die LED einfach nur an und vergiss die Taster.

von Andreax (Gast)


Lesenswert?

Vielleicht hast du eine Powerled benutzt. Das geht nicht. Der Avr kann 
nur 20 mA Strom liefern sonst geht was kaputt.

von Neuling (Gast)


Lesenswert?

holger schrieb:
> Dann mach die LED einfach nur an und vergiss die Taster.

Damit hab ich gestartet. Als nächstes hab ich ein Lauflicht probiert. 
Das hat auch funktioniert. Nur hier haperts etwas mit der Umsetzung.

@Andreax: Das kann ich ausschließen. Wenn ich den kompletten Port als 
Ausgang konfiguriere und 0xFF rausschreibe, dann leuchten alle LEDs.

von MWS (Gast)


Lesenswert?

Die Led leuchtet solange bis Du Taste 1 & 2 gleichzeitig drückst.

von Neuling (Gast)


Lesenswert?

MWS schrieb:
> Die Led leuchtet solange bis Du Taste 1 & 2 gleichzeitig drückst.

Ach, stimmt an den Kopf klatsch. Ich glaub ich steh gerade etwas auf 
dem Schlauch: Aber wie kann man das denn eine Oder-Verknüpfung der 
Schalter realisieren? Also das die LED, wenn PA0, PA1 oder beide 
gedrueckt sind, leuchtet. In C wäre das ja ein Einzeiler, aber wie mach 
ich das in Assembler am elegantesten? Alle Lösungen, die mir einfallen, 
sind nicht gerade sehr elegant. Ich glaub ich denk einfach viel zu 
kompliziert..

von MWS (Gast)


Lesenswert?

Nach dem Maskieren ein CPI, hier mit 3. Bei ungleich 3 wurde eine Taste 
gedrückt, somit kann alles andere bleiben wie's ist.

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

Neuling schrieb:
> ...
> Wenn nun Taster 1 oder Taster 2 gedrückt wird,
> dann soll die an PA7 angeschlossene LED leuchten.
>
>
1
>     in temp, PINA ;lese von A
2
>     andi temp, ((1<<0) | (1<<1)) ;maskiere A mit 0x03
3
>     breq led_aus ;wenn Zero-Flag gesetzt (also UND Verknuepfung 0 ist)
4
>     sbi PORTA, 7 ;aktiviere LED7
5
>     jmp return
6
>     led_aus: cbi PORTA, 7 ;deaktivere LED7
7
> 
8
>     return: ret
9
>
>
>
Nun, ein unbetätigter Taster erzeugt wegen dem Einschalten der 
internen Pullup Widerstände ein 1-Signal. Also High an dem jeweiligen 
Pin.

Wenn Du also nach dem Einlesen des Ports A ( in temp,PINA ) alle 
eingelesenen Bits invertierst ( com temp ) erhälst Du für jeden nicht 
betätigten Taster ein 0-Signal. Also Low.
Jetzt passt auch die Maskierung ( andi temp, 1<<0 | 1<<1 ), da ein 
betätigter Taster ein 0-Signal ergibt, aber durch die Invertierung 
durch den com-Befehl zu einer 1 gemacht wird.

Das war jetzt nur theoretisch durchdacht.
Spiel das ganze mal im Simulator durch oder lass das durch den
com-Befehl ergänzte Programm einfach mal laufen.

Bernd_Stein

von MWS (Gast)


Lesenswert?

Bernd Stein schrieb:

> Jetzt passt auch die Maskierung ( andi temp, 1<<0 | 1<<1 ), da ein
> betätigter Taster ein 0-Signal ergibt, aber durch die Invertierung
> durch den com-Befehl zu einer 1 gemacht wird.

Die Maskierung passt unabhängig davon ob da nun etwas invertiert wird 
oder nicht und hat nichts mit dem Problem zu tun, da sie in jedem Fall 
notwendig ist um die Tastenpins herauszufiltern.

von Neuling (Gast)


Lesenswert?

MWS schrieb:
> Nach dem Maskieren ein CPI, hier mit 3. Bei ungleich 3 wurde eine Taste
> gedrückt, somit kann alles andere bleiben wie's ist.

Danke, das hat hervorragend funktioniert!

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Angehängte Dateien:

Lesenswert?

Wozu dient das Konstrukt das mit WPx ( WRITE PINx REGISTER ) erzeugt 
wird ?


Bernd_Stein

von guess (Gast)


Lesenswert?

Bernd S. schrieb:
> Wozu dient das Konstrukt das mit WPx ( WRITE PINx REGISTER ) erzeugt
> wird ?

Zum toggeln des I/O wenn das PIN Register mit 1 beschrieben wird.

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Lesenswert?

guess schrieb:
> Zum toggeln des I/O wenn das PIN Register mit 1 beschrieben wird.
>
Danke, jetzt sehe ich es auch ganz klar und deutlich.


Bernd_Stein

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.