blamaster,
so wie's PicNick in Basic geschrieben hat, hatte ich's auch gemeint. In Assembler sieht's ganz ähnlich aus. Nach ein bisschen Herumprobieren kam mir eine echte Sprungtabelle als die einfachste Methode (in Assembler) vor. Dann braucht man aber doppelt soviel Platz für die Tabelle, als wenn man Port- und Pin-Nummer in einem Byte kodiert ablegt. Es ist aber einfacher, über die Sprungtabelle direkt eine Auswertungsprozedur anzuspringen, als das gelesene Tabellenbyte zu dekodieren. Das kommt daher, dass man beim Atmel die Ports nur direkt (immediate) adressieren kann.
Zur Information hänge ich das Beispiel unten an.
mare_crisium
Code:
;*-----------------------------------
; BEISPIEL Tabelle_V01.asm
; Entwicklungsversion
;*-----------------------------------
;* Einbinden
;*
.device ATmega8
.include "m8def.inc"
;*-----------------------------------
;* Definitionen
;*
.equ PORTA = 0x1B
;*------------------------------------
;* PROCEDURE TBL_CALL
;*
;* Die Prozedure TBL_JMP liest aus einer Sprung-
;* tabelle, die im Programmspeicher abgelegt
;* ist, ein 2-Byte-Adresse aus. Sie wird als
;* Programmadresse angesprungen.
;
; 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
/*------------------------------------
SPRUNGTABELLE
*/
// 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7
SPRUNG_TBL:
.dw SET_PORTA0, RES_PORTA0 ; ... usw.
//...
.dw SET_PORTC7, RES_PORTC7
/*------------------------------------
PROCEDURE EVAL_RS485
Die Prozedure EVAL_RS485 wertet ein Datenbyte aus,
das über die RS485 empfangen wurde. Das Datenbyte dient
als Zeiger in die Sprungtabelle SPRUNG_TBL. Die Einträge
enthalten die Adresse je einer Prozedur, die an einem
bestimmten Port einen bestimmten Pin setzt oder zurücksetzt.
Eingangsvariablen
r16: enthält den das Datenbyte, das
ausgewertet werden soll
Ausgangsvariablen
r16: enthält das ungeänderte Datenbyte
geänderte Register
keine
geänderte Ports
PORTA,PORTB,PORTC, je nach Datenbyte
*/
EVAL_RS485:
push r16
push zl
in zl,SREG
push zl
push zh
ldi zl,low(SPRUNG_TBL); zh:zl := Adresse der Tabelle
ldi zh,high(SPRUNG_TBL)
rcall TBL_CALL ; ausgewählte Prozedure anspringen
pop zh
pop zl
out SREG,zl
pop r16
ret ;
/*------------------------------------
PROZEDUREN SET_PORTA0/RES_PORTA0 bis SET_PORTC7/RES_PORTC7
Hier kommen die Prozeduren, die die ausgewählten Ports und
Pins ansprechen.
Eingangsvariablen
keine
Ausgangsvariablen
keine
geänderte Register
keine
geänderte Ports
PORTA,PORTB,PORTC, je nach Datenbyte
*/
SET_PORTA0:
sbi PORTA,0
ret
RES_PORTA0:
cbi PORTA,0
ret
// und so weiter
SET_PORTC7:
sbi PORTC,7
ret
RES_PORTC7:
cbi PORTC,7
ret
//------------------------
Lesezeichen