www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 240fache Verzweigung


Autor: Maxim S. (maxim) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie kann ich am besten eine 240fache Verzweigung realisieren?

Abhängig von einem Wert zwischen 10 und 250 soll jeweils an eine andere 
Stelle gesprungen werden.

Ich habe das jetzt mit CJNE gelöst. Der uC Prüft also im schlimmsten 
Fall 239 Mal, ob der Wert mit einer Konstante übereinstimmt und springt 
gegebenenfalls.

Das geht doch sicher effizienter, oder?

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OMG! Wer tipt sowas alles ein o.O
Nimm ne Sprungtabelle...
ldi ZL, LOW(jumptable*2)  ; Tabellenindex laden
ldi ZH, HIGH(jumptable*2) ; Tabellenindex laden
( subi wert, 10 )       ;"Startindex" anpassen
add ZL, wert            ;Wert aufadieren
sbc ZH, -1              ;Carry auf High
ijmp
back:

label1:
  code
  rjmp back
label2:
  code
  rjmp back
.
.
.
label250:
  code
  rjmp back


jumptable:
rjmp label1
rjmp label2
rjmap label3
.
.
.
rjmp label250

ist sehr viel schneller und braucht wahrscheinlich noch weniger code.
Wenn dein wert nicht bei 0 anfängt mußt du vorher noch 10 abziehen (hab 
ich mal in klammern angedeutet.)

Vorteil ist das du immer konstante Zeit brauchst für den Vergleich.
Nachteil: Der Prozessor muß inderekten Sprung unterstützen.

Autor: zonendoedel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin moin,

schmunzel...
wusste gar nicht das eine Sptungtabelle so aussieht.

>jumptable:
>rjmp label1
>rjmp label2
>rjmap label3
>.


Mal ein Beispiel mit dem MSP430:
In: R4

  clr  R5
ParCmd  cmp.b  #0,CmdTbl(R5)
  jz  NoCmd
  cmp.b  CmdTbl(R5),R4
  jz  FndCmd
  inc  R5
  jmp  ParCmd
FndCmd  rla  R5
  mov  CmdAdr(ACC),PC
NoCmd  bla
  bla

CmdTbl
  DB  08h,0dh,1bh,'A','C','+','-','0',0
  EVEN
CmdAdr
  DW  CmdBS,CmdCR,CmdESC,LtrA,LtrC,CmdPl,CmdMi,Cmd0
  EVEN

CmdBS
  bla
  bla

CmdCR
  bla
  bla

und so weiter...


Und wech...

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zonendoedel wrote:
> Moin moin,
>
> schmunzel...
> wusste gar nicht das eine Sptungtabelle so aussieht.
>
>>jumptable:
>>rjmp label1
>>rjmp label2
>>rjmap label3
>>.
Tjoar hm... wieso nicht?
Ich mein ich habs jezt so ausm Gedächtnis hinprogrammiert und ist halt 
AVR ASM aber im Prinzip funktioniert das schon so...
Man kann natürlich auch eine Tabelle der Label anlegen, von der man die 
Adresse lädt, und dann mit IJMP... jeder wie er es mag.
Stand ja nicht dabei was nun genau er will welche Architektur, welcher 
proz...

Auf diese weise kann man aber auch in grenzen nen Fallthroug realisieren

rcall XYZ
rcall fallthrough
rjmp blabla

Autor: zonendoedel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmmm..

s/ACC/R5/

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab eben mal geschaut Wikipedia sagt z.B.:

"Dazu sind die Aufrufe (oder manchmal auch nur die nackten 
Funktionsadressen) mit konstanter Länge hintereinander wie in einer 
Tabelle im Speicher angeordnet. Sie bestehen typischerweise aus 
einfachen Sprungbefehlen an die Stelle im ROM oder innerhalb der 
Funktionsbibliothek"

Und die Interuptvektoren im AVR sind auch ne "Sprungtabelle"... also seh 
ich jezt grad nicht warum mein Ansatz so verkehrt ist?

Autor: zonendoedel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin moin @Läubi,

jojo, wie zu guten alten CP/M-C64-Zeiten.

Die Tabellenlösung ist halt ausgesprochen flexibel.
Die Interruptvektortabellen aktueller CPUs/MCUs arbeiten ja ähnlich.
Nur steinalte Design arbeiten da z.B. mit JMPs (8051...)

Aber jeder wie er mag...

Autor: Allu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Läubi,

an deiner Lösung ist nichts falsch. Die Auswertung mit einem berechneten 
Sprungziel finde ich für diese Aufgabenstellung optimal.

Man kann auch die Rückkehradresse auf dem Stack ablegen, die 
Zieladressen ohne Jmp untereinanderschreiben, Tabellenadresse berechnen 
und den Inhalt ebenfalls auf dem Stack ablegen. Jetzt das Zielprogramm 
mit einem ret anspringen und mit einem ret abschliessen. Dann stimmt der 
Stack wieder und das Programm wird an der vorgegebenen Rückkehradresse 
fortgesetzt.

Grüße Allu

Autor: Joe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wahrscheinlich geht dieser Thread hier weiter ;-))

Beitrag "Indirekte Sprünge mit 8051"

er meint eine 8051 Typ und da kann man es z.B. so machen.

CMD:          mov a,command      ;
    rl a        ;ajmp = 2 Bytes
    mov dptr,#commands    ;pointer @ cmd
    jmp @a+dptr      ;execute commands
commands:  ajmp command_1      ;
    ajmp command_2      ;
    ajmp command_3            ;
    ajmp command_4            ;
.....
.....


Allerdings muß das Sprungziel innerhalb eines 2k Blocks liegen.

Autor: Joe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich liebe Tabs ;-))

Autor: Maxim S. (maxim) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke euch für die vielen Tipps!

Habe leider vergessen zu erwähnen, dass ich einen 8252 und Assembler 
nutze, aber das Prinzip ist ja das selbe.

Statt einer Sprungtabelle oder einer 240fachen Verzweigung könnte ich in 
meinem Programm den Wert auch durch "Timer = 1 / (3 * 10^-6 * R0)" 
berechnen, aber eine Sprungtabelle mit vorberechneten Werten ist in 
diesem Fall einfacher, oder?

Autor: Joe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, so ist es.

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch einfacher ist ein Array, also das Lesen von einer berechneten 
Adresse. Die Sprungtabelle ist unnötiger Aufwand.

Autor: Maxim S. (maxim) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber der Timer ist 16-bittig, kann ich ein 16-bittiges Array anlegen? Da 
muss ich halt immer zwei Bytes abspeichern und dann beim Sprung mit RL 
die Adresse anpassen?

Autor: Maxim S. (maxim) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
VALUE001:  DB  513d

VALUE002:  DB  514d

VALUE003:  DB  516d

ist ja dasselbe wie:

VALUE001H:  DB  1d
VALUE001L:  DB  1d

VALUE002H:  DB  1d
VALUE002L:  DB  2d

VALUE003H:  DB  1d
VALUE003L:  DB  4d

oder?

Autor: Joe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So Andreas, wir warten ;-))

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau so. Die vielen Labels kannst du dir sparen, schreib einfach deine 
240 Werte hintereinander in den Speicher, dann kannst du dir die Adresse 
so ausrechnen:

adresse = (x - 10) * 2 + startadresse

Autor: Maxim S. (maxim) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Schwarz wrote:
> Genau so. Die vielen Labels kannst du dir sparen, schreib einfach deine
> 240 Werte hintereinander in den Speicher, dann kannst du dir die Adresse
> so ausrechnen:
>
> adresse = (x - 10) * 2 + startadresse

So wollte ich das auch machen. :-)

Habe ein kleines Testprogramm geschrieben. Leider funktioniert es nicht 
richtig. Habe den Debugger verwendet, aber bis jetzt nicht 
herausgefunden, wo der Fehler liegt.

INCLUDE  C:\RIDE\INC\51\ATMEL\REG8252.INC

MOV  P2, #0h
MOV  R0, #0h

LOOP:  JB  P3.3, WAIT_FOR_Z
  SJMP  GO_ON 
    
WAIT_FOR_Z:  JNB  P3.3, BUTTON_OK
    SJMP  WAIT_FOR_Z
        
BUTTON_OK:  INC  R0          ;Falls Taster betätigt, erhöhe R0 um 1

GO_ON:  MOV  DPTR, #TABELLE    ;Lade Adresse des Arrays in den Datenzeiger
    MOV  A, R0          
    RL    A                 ;Verschiebe Wert um eine Stelle nach links (gleich der Multiplikation mit 2)
    ADD  A, #1d        ;Addiere 1, um an das Low-Byte zu kommen
    MOVC  A, @A+DPTR      ;Kopiere Inhalt aus dem Array in den Akkumulator
    MOV  P2, A  
      
RET_GO_ON:  SJMP  LOOP

TABELLE:
      
VALUE001:  DB  513d  ;Low-Byte = 1

VALUE002:  DB  514d  ;Low-Byte = 2

VALUE003:  DB  516d  ;Low-Byte = 4

VALUE004:  DB  520d  ;Low-Byte = 8
       
VALUE005:  DB  528d  ;Low-Byte = 16
                    
END

Am Port P2 sind 8 LEDs angeschlossen. Mit diesem Programm sollte bei 
einem Tastendruck (Taster am P3.3) immer eine LED weitergeschaltet 
werden. Stattdessen leuchtet am Anfang die zweite, dann die vierte und 
bei einem weiteren Tastendruck die erste LED. Danach erscheinen alle 
möglichen Kombinationen, da der Datenzeiger scheinbar irgendwo auf den 
Code zeigt, weil das Array zu ende ist.

Ich werde jetzt noch weiter mit dem Debugger rumspielen, aber vielleicht 
sieht jemand den Fehler auf Anhieb?

update: Irgendwie werden die dezimalen Werte nur in einem Byte 
gespeichert. Der Assembler beachtet den High-Byte gar nicht. Das erklärt 
das Verhalten des uC. Ich benutze die kostenlose Version von RIDE 
6.10.15. Liegt es an dem Programm oder muss ich die Schreibweise 
irgendwie verändern, dass er z.B. die Zahl 513 automatisch in zwei Bytes 
ablegt?

Autor: Maxim S. (maxim) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier ein Screenshot vom Debugger.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für 16Bit mußt Du natürlich DW nehmen und nicht DB.

Und auch 2* MOVC um beide Bytes auszulesen (INC DPTR dazwischen).


Peter

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also z.B. so hier:
  mov     dptr, #table
  mov     a, index
  add     a, acc
  jnc     _m1
  inc     dph        ;übertrag
_m1:
  mov     r7, a
  movc    a, @a+dptr
  inc     dptr
  xch     a, r7
  movc    a, @a+dptr
  ret                ;r7 = high, a = low byte

table:
       dw 1000
       dw 2000
usw.


Peter

Autor: Maxim S. (maxim) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
JA, jetzt geht's. DANKE! :D

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.