Mitch,
an der Stelle musste ich auch lange knobeln ! Du musst den Zeiger verdoppeln, weil die Anweisungen bei den ATmegas immer zwei Bytes (14 Bit) belegen. Ich arbeite viel mit Adressentabellen und habe mir dafür eine extra Assembler-Prozedur geschrieben:
Code:
/*------------------------------------
PROCEDURE TBL_CALL
Die Prozedur TBL_CALL liest aus einer Adressentabelle, die
im Programmspeicher abgelegt ist, ein 2-Byte-Adresse aus.
Sie wird als Programmadresse angesprungen. Das aufrufende
Programm ist selbst dafür verantworlich, dass der maximale
Index nicht überschritten wird. Das aufrufende Programm
wird in der Zeile nach der Anweisung "rcall TBL_CALL "
fortgesetzt.
Eingangsvariablen
zh:zl: enhält den Zeiger auf die RAM-Adresse,
an der die Sprungtabelle beginnt
r16: enthält den Index der Adresse, die
angesprungen werden soll
Ausgangsvariablen
keine
geänderte Register
zh,zl
geänderte Ports
keine
*/
TBL_CALL:
push r17
in r17,SREG
push r17
clr r17
add zl,r16
adc zh,r17
add zl,zl
adc zh,zh
lpm r17,z+
lpm zh,z
mov zl,r17
pop r17
out SREG,r17
pop r17
ijmp
ret
Die Anwendung im Programm sieht so aus:
Code:
...
PROGRM_TABELLE:
.dw TU_DIES
.dw TU_DAS
.dw TU_JENES
...
...
ldi zl,low(PROGRM_TABELLE) ; Zeiger auf Tabelle nach zh:zl
ldi zh,high(PROGRM_TABELLE)
ldi r16,0x02 ; Programmteil "TU_JENES" auswählen
rcall TBL_CALL
nop
...
TU_JENES:
nop
ret
...
Das Auslesen der Unterprogramm-Startadresse aus dem Flash geht mit der Anweisung "lpm". Da ich das ausgewählte Unterprogramm in TBL_CALL mit "ijmp" anspringe, bleibt die Rückkehradresse, die noch vom Aufruf von "rcall TBL_CALL" auf dem Systemstack liegt, unverändert. D.h. nach Abarbeiten von "TBL_CALL" und des Unterprogramms ("TU_JENES"), kehrt der Programmablauf zu der nächsten, auf "rcall TBL_CALL" folgenden Anweisung (nop) zurück.
Klappt's so?
mare_crisium
Lesezeichen