Forum: Mikrocontroller und Digitale Elektronik Sprungtabelle funktioniert nicht


von Klaus (Gast)


Lesenswert?

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

von Hc Z. (mizch)


Lesenswert?

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.

von spess53 (Gast)


Lesenswert?

Hi

Ich sehe keine Tastenentprellung.

MfG Spess

von Michael U. (amiga)


Lesenswert?

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

von Klaus (Gast)


Lesenswert?

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!

von Klaus (Gast)


Lesenswert?

@ 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
Noch kein Account? Hier anmelden.