Hab folgendes Problem: Abhängig von einem BYte soll ein entsprechendes Programm ausgeführt werden: Bisher mache ich das so: byte --> r16 cpi r16,0x00 breq prg0jmp cpi r16,0x01 breq prg1jmp ... prg0jmp: rjmp prog0 prg1jmp: rjmp prog1 ... prog0: //code prog1: //code Das muss aber viel viel einfacher gehen mit ijmp oder so etwas. Hat da jemand ne elegante Lösung für mich?
Ja, wenn du die absolute Adresse von deiner Sprungtabelle im Register Z hast ( ldi ZL,low(prg0jmp*2) ; low ldi ZH,high(prg0jmp*2) ; high ), dann geht es bisschen einfacher: add zl, r16 brcc no_carry inc zh no_carry: ijmp
JA der ist zu lang. Und mit deinem Vorschlag kann ich zunächst auch nur 8 Programme ansteuern. ODER ? Dachte an sowas wie (i)jmp label + r16 * (länge vom rjmp) Label: Rjmp prog0 Rjmp prog1 Rjmp prog2 Rjmp prog3 Rjmp prog4 nur ich würde ganz gerne einer multiplikation aus dem weg gehen.
Oder so: menujump: ;Menüpunktaufruf ldi zl,low(menujmp) ;Zeiger auf Sprungtabelle ldi zh,high(menujmp) add zl,mp ;Menüpunkt adc zh,null ;dazu ijmp ;Menüpunkt aufrufen menujmp: ;Menü-Sprungtabelle rjmp mp_00 rjmp mp_01 rjmp mp_02 ... mp_00: ;Hauptmenü, Ebene Edit sbrc flags,v24rx ;PC-Verbindung aktiv? nein... rcall usart_aus ;ja, deaktivieren... mov ztl,ff ;Uhr auf mov zth,ff ;-1 cbr flags,1<<aktiv ;und aus rcall testmax ;Anzahl Schüsse ermitteln rjmp editliste ;Liste aufbauen und Menütexte anzeigen Alles im Zusammenhang hier zu sehen: http://www.hanneslux.de/avr/zuenduhr/ZndUhr01.asm ...
DRei fragen an Aleksej: a) wofür die multiplikation mit zwei? b) reicht es den Wert von Z einfach mit meinem Inhalt von r16 zu erhöhen? oder muss ich die länge eines rjmp-Befehl noch multiplizieren c) meine tabelle sähe dann so aus?: prg0jmp: rjmp prog0 rjmp prog1 rjmp prog2
Die Multiplikation mit 2 ist für byteweisen Zugriff bei LPM erforderlich, bei IJMP aber nicht, da hier der Zugriff wordweise erfolgt. ...
> sorry ihr seit mir zu schnell!
Wir sind auch Mehrere, du nur Einer...
Wir teilen uns quasi die Arbeit...
;-)
...
Baumartig verzweigen: cpi $80 brge... cpi $40 brge... cpi $20 das ist jedenfalls schneller als 255 Vergleiche nacheinander, nach 8 Vergleichen hat man 256 Sprungziele erreicht
Das geht auch einfacher mit IJmp oder ICall. Aufpassen: diese Befehle können manche AVR Controller nicht, also besser vorher im Datenblatt nachschlagen. Im Prinzip funktioniert das so (habs die Syntax nicht ausprobiert): ; Sprungtabelle in Z-Pointer laden LDI ZL, low(Sprungtabelle) LDI ZH, high(Sprungtabelle) ;hier musste nochmals nachschlagen das Prinzip sollte klar sein, der Assembler soll das low byte der Adresse der Sprungtabelle in ZL laden dito für ZH, die Syntax sieht bestimmt ein bischen anders aus. ; Nachdem jeder Eintrag in der Sprungtabelle 2 byte gross ist musst du den Index-Wert in R16 noch mit 2 multiplizieren das enspricht einem linksshift. LSL R16 ;Nun index auf Z draufaddieren (auf überlauf des lowbyte achten!) ; daher vorher ein Register mit 0 laden SUB R0,R0 ; R0 wird mit 0 geladen ADD ZL, R16 ; R16 wird auf ZL addiert und C ggfs. gesetzt ADC ZH, R0 ; ZH = ZH + 0 + C, ggfs carry draufaddieren. zum Registersparen geht das auch ohne R0 mit Abfrage des Carrybits und einem eventuellen INC des ZH. ; Nun der eingentliche Sprung Ijmp ; Hier nun die Sprungtabelle Srungtabelle: rjmp prog0 rjmp prog1 rjmp prog2 .... ciao Remo
HEY HANNES!! Genau das isses! Alles Befürchtugen sind dahin, das funzt! Danke an Euch alle!
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.