Hallo zusammen,
ich versuche seit kurzem in Assembler eine 7-Segmente Anzeige
anzusteuern. Das Programm soll auch bei einem Tastendruck die angezeigte
Zahl um 1 erhöhen(Probeweise nur bis 2, bei der Zahl 3 wird der zähler
wider auf 0 gesetzt). Jedoch wenn ich das Programm auf meinen ATmega32
lade und den Taster drücke leuchten kurz alle LEDs auf und erlöschen
sofort wieder.
Hier der Code:
1
;Ansteuern der Segmente und des Tasters
2
;PB1-PB7 sind für die Segmente (Ausgang) und PB0 ist für den Taster ;(Eingang) bestimmt.
3
4
.INCLUDE "m32def.inc" ;Deklaration für ATmega32
5
.EQU takt = 16000000 ;Takt 16 MHz
6
.DEF akku = r16 ;Arbeitsspeicher
7
.DEF zaehler = r18 ;Zähler für Tastendruck
8
.CSEG ;Programm-Flash
9
10
11
start: ldi r16,0xFE
12
out DDRB,r16 ;PB0 auf Eingang und PB1-PB7 auf Ausgang
Dir ist hoffentlich klar, dass dein Hochzählen nicht erfolgt 'Wenn eine
Taste gedrückt wird', sondern 'Solange eine Taste gedrückt ist'. Als
Mensch wirst du es kaum schaffen, eine Taste kürzer als ein paar
Millieskunden gedrückt zu halten. In dieser Zeit zählt dein Prozessor
rasend schnell immer wieder und immer wieder durch.
Sieh dir mal an, welche 7-Segment Muster du in welches Register lädts,
und welches Register du tatsächlich dann am Port ausgibst.
Sowas
1
cpi r18,1 ;Vergleichen
2
breq zahl_1 ; <------------
3
brne kontrolle_2 ; <------------
4
5
kontrolle_2: cpi r18,2
ist ziemlich kontraproduktiv. Entweder 2 Zahlen sind gleich, oder sie
sind es nicht. Wenn sie aber gleich sind, können sie nicht ungleich
sein. D.h. der brne ist da ziemlich sinnfrei. Wenn der Prozessor zum
brne kommt, dann steht bereits fest, dass r18 nicht gleich 1 sein kann.
Sonst wäre der Programmlauf nicht an diese Stelle gekommen!
d.h deine 'Hauptschleife' kannst du kürzer auch so schreiben
Grundsätzlich ist es nicht schlecht, ausführlich zu programmieren. Aber
gerade in Assembler kann mans auch übertreiben. Und dann wirds nicht
übersichtlicher sondern man legt sich selber Fallen, weil man vor lauter
Anweisungen nicht mehr sieht, welche davon sinnlos sind, und welche
nicht.
Dir ist hoffentlich auch klar, dass du hier
ldi r19,0xFE
out PORTB,r19
dadurch, dass PB0 gleich 0 ist, denn Pullup für den Taster abschaltest
(Ditto bei den anderen Ausgaben)
Hi,
einige Bemerkungen zur Systematik deines Programmes.
-) Verlagere das Auswerten der Taste in eine eigene Unterroutine. In
dieser werde die taste etwa 10 ms abgefragt. Wenn 75 % der
Abfrageresultate ergeben, daß der Tater 'zu' ist, wird ein TRUE
zurückgegeben, sonst ein false.
-) Erst wenn ein TRUE zurückkommt, wird der Zähler incrementiert.
-) Für die Anzeigendecoduierung verwende eine Tabelle, auf die mit einem
konstantem Pointer gezeigt wird (in c etwa const * unsigned char ). Das
Auslesen des Wertes ergibt die Bits in der Anzeige. Auch das gehört in
eine eigene Routine.
-) Überlege, was in einen Kommentar hineingehört und was nicht. Deine
Kommentare 'Arbeitsspeicher', die 16 MHZ usw. können entfallen. Das
Initialisierungsjedöns gehört in ein eigenes UP.
-)dein Programm kann dann im Hauptteil aussehen wie folgt (das ist jetzt
VHIT, vom Hirn ins terminal, also ohne Test)
start:
call init;; initialisierung
loop: taste_auswerten; result on TOS
mov R01, TOS ;
jnz loop; warten bis Taste gedrückt
;; entry hier nur wenn tastendruck
inc tastcount;
ld R01 Tastcount + vector; vector ist der og.
Tabellenpointer
mov 7SEGPORT, R01;
jmp loop;
So. Ich hoffe, das hiolft erstmal weiter,
Gruss#
Robert
Ich würde das Haus nicht mit dem Dach anfangen zu bauen, sondern mit dem
Fundament.
Wenn also etwas auf Tastendruck passieren soll, programmiert man erstmal
ne funktionierende Tastenroutine.
Z.B. ne LED mit Taste ein- und ausschalten.
Wenn das funktioniert, d.h. die LED wechselt zuverlässig und prellfrei
bei jedem Tastendruck, gehts einen Schritt weiter.
Z.B. 2 Tasten und 2 LEDs unabhängig und gleichzeitig.
Dann weiß man, daß die Tastenroutine nicht blockierend ist, d.h. einen
zu entwickelnden Programmablauf nicht behindert.
Usw.
Immer alle Probleme in kleine Häppchen aufteilen und diese lösen (teile
und herrsche).
Peter