Hallo, seit ein paar Tagen versuch ich vergebens eine SRam Sprungtabelle
zu programmieren. Ich hoffe einer von euch erkennt den Fehler.
Programmiert wird ein Atmega32 mit AVR Studio im Assembler. Grundlage
„meines“ Programms ist das Tutorial Mehrfachverzweigungen. Hab mich für
die Version B entschieden, da der interne SRam des Atmega32 weniger als
8KB Ram hat. Im user manual steht 2KB und deshalb geht Version C nicht.
Steht zumindest so im Tutorial.
Mein Vorhaben ist mit zwei Tastern ein Register count zu inkrementieren.
Für die Registerwerte 0x01->0x05 sollen in der Sprungtabelle hinterlegte
Werte ausgegeben werden. Allerdings nicht wie in älteren Forumsbeiträgen
nur 8bits sonder 2x8bits (8bits für portb und 8bit für porta). Das
merkwürdige ist, im Debugmodus funktioniert das Programm, nur auf dem
Mc. Nicht.
Hier mal der der Code:
.include "m32def.inc"
.def count= r21
.def temp= r20
.def temp2= r22
.equ minimum = 1
.equ maximum = 5
;---------------------------------
init:
ldi temp, LOW(RAMEND)
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp
ldi temp,0x60 ;ein-ausgabe richtung port d
out DDRD,temp
ldi temp,0xff ;ein-ausgabe richtung port B
out DDRB,temp
ldi temp,0xff ;ein-ausgabe richtung port A
out DDRA,temp
rjmp loop
loop:
SBIC PinD,2
rjmp increment
mov temp, count
subi temp,minimum ; Nullpunkt verschieben
cpi temp,(maximum-minimum+1) ; Index auf Maximum prüfen
brsh kein_Treffer ; Index zu gross -> Fehler
ldi ZL,low(Sprungtabelle) ; Tabellenzeiger laden, 16 Bit
ldi ZH,high(Sprungtabelle)
add ZL,temp ; Index addieren, 16 Bit
ldi temp,0
adc ZH,temp
ijmp ; indirekter Sprung in
Sprungtabelle
kein_treffer:
ldi temp, 0x00
ldi temp2,0x00
rjmp ende_vergleich
increment:
inc count
up:
SBIc PinD,3 ;warten bist zweite Taste gedrückt wird
rjmp loop
rjmp up
Sprungtabelle:
rjmp zweig_0
rjmp zweig_1
rjmp zweig_2
rjmp zweig_3
rjmp zweig_4
zweig_0:
ldi temp, 0b00000011
ldi temp2,0b11000000
rjmp ende_vergleich
zweig_1:
ldi temp, 0b00001111
ldi temp2,0b11110000
rjmp ende_vergleich
zweig_2:
ldi temp, 0b00111111
ldi temp2,0b11111100
rjmp ende_vergleich
zweig_3:
ldi temp, 0b11111111
ldi temp2,0b00000000
rjmp ende_vergleich
zweig_4:
clr count
rjmp ende_vergleich
ende_vergleich:
out porta, temp2
out portb, temp
rjmp loop
[..] ; bedingte Verzweigung nach dem Inhalt von count
5
6
increment:
7
inc count
8
up:
9
SBIc PinD,3 ; Taste 2 gedrückt?
10
rjmp loop ; Nein, zurück zur Abfrage von Taste 1
11
rjmp up
Die Kommentare habe ich mir aus dem (Spaghetti-)Code zusammengereimt.
Wenn ich mit ihnen recht habe, zählst Du count immer weiter, bis
zumindest eine Taste gedrückt ist. count wird daher höchstens zufällig
in den gültigen Bereich von 1..5 kommen.
Zudem fehlt eine Entprellung. Selbst wenn Du den Code so hinbekommst,
dass je Tastenflanke der nächste Eintrag angesprungen wird, wirst Du pro
Tastendruck so viele Flanken bekommen, dass alle Einträge reihum
vielmals angelaufen werden und der letzte, bei dem es stehen bleibt,
rein zufällig ist.
Hallo,
Klaus schrieb:
> Hallo, seit ein paar Tagen versuch ich vergebens eine SRam Sprungtabelle> zu programmieren. Ich hoffe einer von euch erkennt den Fehler.
Du willst eine Sprungtabelle im Flash nutzen, nicht im SRAM.
Der SRAM wäre der .data Bereich und da müßtest Du die Tabelle nacht dem
Programmstart erstmal reinschreiben, weil der SRAM nach dem Ausschalten
seine Daten vergisst...
> Programmiert wird ein Atmega32 mit AVR Studio im Assembler. Grundlage> „meines“ Programms ist das Tutorial Mehrfachverzweigungen. Hab mich für> die Version B entschieden, da der interne SRam des Atmega32 weniger als> 8KB Ram hat. Im user manual steht 2KB und deshalb geht Version C nicht.> Steht zumindest so im Tutorial.
Das suche ich mir jetzt nicht raus.
> Mein Vorhaben ist mit zwei Tastern ein Register count zu inkrementieren.> Für die Registerwerte 0x01->0x05 sollen in der Sprungtabelle hinterlegte> Werte ausgegeben werden. Allerdings nicht wie in älteren Forumsbeiträgen> nur 8bits sonder 2x8bits (8bits für portb und 8bit für porta). Das> merkwürdige ist, im Debugmodus funktioniert das Programm, nur auf dem> Mc. Nicht.
Wundert mich eigentlich...
> Hier mal der der Code:>> .include "m32def.inc">> .def count= r21> .def temp= r20> .def temp2= r22> .equ minimum = 1> .equ maximum = 5>> ;--------------------------------->> init:>> ldi temp, LOW(RAMEND)> out SPL, temp> ldi temp, HIGH(RAMEND)> out SPH, temp>> ldi temp,0x60 ;ein-ausgabe richtung port d> out DDRD,temp>> ldi temp,0xff ;ein-ausgabe richtung port B> out DDRB,temp>> ldi temp,0xff ;ein-ausgabe richtung port A> out DDRA,temp>> rjmp loop>>>>> loop:>> SBIC PinD,2> rjmp increment> mov temp, count> subi temp,minimum ; Nullpunkt verschieben> cpi temp,(maximum-minimum+1) ; Index auf Maximum prüfen> brsh kein_Treffer ; Index zu gross -> Fehler> ldi ZL,low(Sprungtabelle) ; Tabellenzeiger laden, 16 Bit> ldi ZH,high(Sprungtabelle)
Die Tabelle liegt im Flash, der ist Word-Organisiert (16Bit breit), die
Befehle erwarten aber eine Byte-Adresse, also *2
> ldi ZL,low(2*Sprungtabelle) ; Tabellenzeiger laden, 16 Bit> ldi ZH,high(2*Sprungtabelle)
Ein Eintrag Deiner Tabelle ist aber länger als 1 Byte:
> rjmp zweig_0
Du muß also Dein temp erstmal auf die passende Länge bringen, hier also
lsl temp ; temp * 2 wegen Länge eines
Eintrags
> add ZL,temp ; Index addieren, 16 Bit> ldi temp,0> adc ZH,temp> ijmp ; indirekter Sprung in> Sprungtabelle>> kein_treffer:>> ldi temp, 0x00> ldi temp2,0x00>> rjmp ende_vergleich>> increment:>> inc count> up:> SBIc PinD,3 ;warten bist zweite Taste gedrückt wird> rjmp loop> rjmp up>>> Sprungtabelle:> rjmp zweig_0> rjmp zweig_1> rjmp zweig_2> rjmp zweig_3> rjmp zweig_4>> zweig_0:>> ldi temp, 0b00000011> ldi temp2,0b11000000>> rjmp ende_vergleich>> zweig_1:>> ldi temp, 0b00001111> ldi temp2,0b11110000>> rjmp ende_vergleich>> zweig_2:>> ldi temp, 0b00111111> ldi temp2,0b11111100>> rjmp ende_vergleich>> zweig_3:>> ldi temp, 0b11111111> ldi temp2,0b00000000>> rjmp ende_vergleich>> zweig_4:>> clr count>> rjmp ende_vergleich>> ende_vergleich:>> out porta, temp2> out portb, temp>> rjmp loop
Das Ganze ist aber ziemlich umständlich und unnötig...
...... Dein Anfang von oben, der invrement-Teil auch....
cpi temp,(maximum-minimum+1) ; Index auf Maximum prüfen
brlo okay ; Index zu gross -> Fehler
ldi temp, 0x00 ; kein Treffer
ldi temp2,0x00
rjmp ende_vergleich
okay:
cpi temp, 4 ; Sonderfall?
brne nimm_tabelle ; nein
clr count
rjmp ende_vergleich
nimm_tabelle:
ldi ZL,low(2*tabelle_der_werte) ; Tabellenzeiger laden, 16 Bit
ldi ZH,high(2*tabelle_der_werte)
lsl temp ; * 2 wegen Länge eines Eintrags
add ZL,temp
clr temp
adc ZH,temp ;Z zeigt jetzt auf passenden
Eintrag
lpm temp,Z+ ; ersten Eintrag holen
lpm temp2,Z ; zweiten Eintrag holen
ende_vergleich:
out porta, temp2
out portb, temp
rjmp loop
tabelle_der werte:
.db 0b00000011, 0b11000000 ; Werte für 0
.db 0b00001111, 0b11111100
.db 0b11111111, 0b00000000
PS: hoffentlich ist kein Fehler drin.....
Gruß aus Berlin
Michael
Vielen Dank für eure Tipps. Nochmal zu meinem Programm:
Für die Entprellung ist der zweite Taster da. PinD, 2 inkrementiert das
register und erst wenn PinD, 3 gedrückt wurde folgt Rücksprung nach
loop.
@Michael wird ich auf alle Fälle ausprobieren!