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
1 | loop: |
2 | SBIC PinD,2 ; Taste 1 gedrückt? |
3 | rjmp increment ; nein, count inkrementieren |
4 | [..] ; 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!
@ Michael dein Ansatz hat funktioniert. Nochmal vielen Dank! Muss mir nur nochmal den Unterschied verinnerlichen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.