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!
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.
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..
>>
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
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.
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!
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.