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:
Die Anwendung im Programm sieht so aus: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
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.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 ...
Klappt's so?
mare_crisium






Zitieren

Lesezeichen