Anfängerfrage AVR Assembler

C

Christian Sander

Guest
Liebe Newsgroup,

ich habe in einem Register folgendes definiert:

.def temp=r25 ;Register zur allgemeinen Verwendung

.equ rs_recv=0
.equ Ser_Busy=1
.equ TX_Ready=2
.equ RX_Ready=3
.equ int_Rx_Ready=4

Ziel war es den einzelnen Speicherzellen des Registers Labels zuzuordnen die
ich
dann später im Programm direkt ansprechen kann. Ungefähr so wie bei 8051 der
bitadressierbare Bereich.

Leider klappt es nicht so wie ich es mir vorgestellt habe. Wo ist mein
Denkfehler?

Grüße aus München,

Christian
 
Christian Sander wrote:

.equ rs_recv=0
.equ Ser_Busy=1
.equ TX_Ready=2
.equ RX_Ready=3
.equ int_Rx_Ready=4
Ich gehe mal davon aus, dass jedes EQU ein Bit im Register darstellen soll.


Ziel war es den einzelnen Speicherzellen des Registers Labels zuzuordnen
die ich
dann später im Programm direkt ansprechen kann. Ungefähr so wie bei 8051
der bitadressierbare Bereich.
Leider kenne ich den 8051 nicht.


Leider klappt es nicht so wie ich es mir vorgestellt habe. Wo ist mein
Denkfehler?
Was klappt denn nicht? Es gibt Befehle, um ein einzelnes I/O-Bit zu
setzen/löschen. Etwa in der Art:

sbi portb, rs_recv ;Bit setzen
cli portb, rs_recv ;Bit löschen


Aber ein Bit im Register zu setzen, da gibt es (zumindest beim 2313) keinen
direkten Befehl, dann eben über einen Umweg.

Wir setzen die equs auf eine Konstante, die der ehemaligen Konstante als
Potenz 2^x entspricht:

.equ rs_recv=1
.equ Ser_Busy=2
.equ TX_Ready=4
.equ RX_Ready=8
.equ int_Rx_Ready=16

Jetzt kann man mit SBR und CBR Bits setzen und löschen:

SBR temp, rs_recv
CBR temp, rs_recv

Bei diesen Befehlen hat der zweite Parameter die Funktion einer Maske, d.h.
alle Bits die in der Konstante gesetzt sind, werden im Register
gelöscht/gesetzt. Also löscht

CBR temp, 255

das ganze Register, entspricht also

CLR temp

und

SBR temp, 255

wäre gleichbedeutend mit

LDI temp, 255


Viele Grüße,
Michael
 
Am Thu, 29 Jul 2004 11:06:00 +0200 hat Christian Sander
<chris@sander-muenchen.de> geschrieben:

Liebe Newsgroup,

ich habe in einem Register folgendes definiert:

.def temp=r25 ;Register zur allgemeinen Verwendung

.equ rs_recv=0
.equ Ser_Busy=1
.equ TX_Ready=2
.equ RX_Ready=3
.equ int_Rx_Ready=4

Ziel war es den einzelnen Speicherzellen des Registers Labels zuzuordnen
die
ich
dann später im Programm direkt ansprechen kann. Ungefähr so wie bei 8051
der
bitadressierbare Bereich.

Leider klappt es nicht so wie ich es mir vorgestellt habe. Wo ist mein
Denkfehler?
Hast du das entsprechende include file eingebunden?
Beim Atmega8 z.B. .include "m8def.inc"

Grüße aus München,

Christian
Gruß Chris

--
Wann hält Ulm an diesem Zug?
(A. Einstein)
 
OK, ich habe jetzt neu definiert.

.def a_flag=r25 ;Register zur allgemeinen Verwendung
;Flag von A Flag
.equ Ser_Busy=1
.equ TX_Ready=2
.equ RX_Ready=4
.equ int_Rx_Ready=8

Über den Studio Debugger schaue ich mir das Register 25 an.
Da steht vor meinem Befehl 0x04 darin.

Trotzdem springt er mir in folgender Routine nach RECEIVE_CONTROL_END.

Wer weis RAT?

RECEIVE_CONTROL: sbrs a_flag,int_Rx_Ready
rjmp RECEIVE_CONTROL_END

cbi PORTA, LED1 ;LED
anschalten
RECEIVE_CONTROL_END:ret
Ich gehe mal davon aus, dass jedes EQU ein Bit im Register darstellen
soll.


Ziel war es den einzelnen Speicherzellen des Registers Labels zuzuordnen
die ich
dann später im Programm direkt ansprechen kann. Ungefähr so wie bei 8051
der bitadressierbare Bereich.

Leider kenne ich den 8051 nicht.


Leider klappt es nicht so wie ich es mir vorgestellt habe. Wo ist mein
Denkfehler?

Was klappt denn nicht? Es gibt Befehle, um ein einzelnes I/O-Bit zu
setzen/löschen. Etwa in der Art:

sbi portb, rs_recv ;Bit setzen
cli portb, rs_recv ;Bit löschen


Aber ein Bit im Register zu setzen, da gibt es (zumindest beim 2313)
keinen
direkten Befehl, dann eben über einen Umweg.

Wir setzen die equs auf eine Konstante, die der ehemaligen Konstante als
Potenz 2^x entspricht:

.equ rs_recv=1
.equ Ser_Busy=2
.equ TX_Ready=4
.equ RX_Ready=8
.equ int_Rx_Ready=16

Jetzt kann man mit SBR und CBR Bits setzen und löschen:

SBR temp, rs_recv
CBR temp, rs_recv

Bei diesen Befehlen hat der zweite Parameter die Funktion einer Maske,
d.h.
alle Bits die in der Konstante gesetzt sind, werden im Register
gelöscht/gesetzt. Also löscht

CBR temp, 255

das ganze Register, entspricht also

CLR temp

und

SBR temp, 255

wäre gleichbedeutend mit

LDI temp, 255


Viele Grüße,
Michael
 
RECEIVE_CONTROL: sbrs a_flag,int_Rx_Ready
Hi,

ja das dachte ich mir. Das ist das Problem an meiner Idee: Die EQUs
enthalten potenzierte Werte und keine Bit-Nummern, aber SBRS & Co.
verlangen Bit-Nummern. Das solltest Du zwei EQUs pro Bit machen, einen mit
der Nummer und einen Potenzierten.


 .equ int_Rx_Ready=8
Mit einem

.equ int_Rx_Ready=4

würde es funktioniern, denke ich.

PS: Wir hatten die neuen EQU-Werte so definiert:

    .equ rs_recv=1
    .equ Ser_Busy=2
    .equ TX_Ready=4
    .equ RX_Ready=8
    .equ int_Rx_Ready=16

also kein

int_Rx_Ready=8


Viele Grüße,
Michael
 
man kann keine .equ mit 2 werten angeben, da er logischerweise einen Fehler
beim Compilieren herausgibt.
Auch .equ Werte mit =16 funktionieren nicht.

Gibt es da keine allgemeine Lösung? Ist das wirklich so speziell???

Grüße,

Christian


Hi,

ja das dachte ich mir. Das ist das Problem an meiner Idee: Die EQUs
enthalten potenzierte Werte und keine Bit-Nummern, aber SBRS & Co.
verlangen Bit-Nummern. Das solltest Du zwei EQUs pro Bit machen, einen mit
der Nummer und einen Potenzierten.


.equ int_Rx_Ready=8

Mit einem

.equ int_Rx_Ready=4

würde es funktioniern, denke ich.

PS: Wir hatten die neuen EQU-Werte so definiert:

.equ rs_recv=1
.equ Ser_Busy=2
.equ TX_Ready=4
.equ RX_Ready=8
.equ int_Rx_Ready=16

also kein

int_Rx_Ready=8


Viele Grüße,
Michael
 
man kann keine .equ mit 2 werten angeben, da er logischerweise einen
Fehler beim Compilieren herausgibt.
Natürlich geht das nicht. Ich meinte ja auch nicht denselben Namen!


Auch .equ Werte mit =16 funktionieren nicht.
Das wäre mir neu.


Gibt es da keine allgemeine Lösung? Ist das wirklich so speziell???
Ich kenne keine andere, außerdem ist sie nicht sehr umständlich, bis auf die
Tatsache, das man eigene EQUs braucht...


Gruß
Michael
 
Michael wrote:

ja das dachte ich mir. Das ist das Problem an meiner Idee: Die EQUs
enthalten potenzierte Werte und keine Bit-Nummern, aber SBRS & Co.
verlangen Bit-Nummern. Das solltest Du zwei EQUs pro Bit machen, einen mit
der Nummer und einen Potenzierten.
Das ist eine Moeglichkeit - ich mach das aber immer so:


.def Status = R22 ; Flag-Register

; Flag-Definitionen für Status
.equ STAT_RATE = 0
.equ STAT_RX = 1
.equ STAT_TIMER = 2
.equ STAT_BATTVOLL = 3
.equ STAT_TASTE = 4
.equ STAT_COMP = 5
.equ STAT_CHARGE = 6

Mit diesen Definitionen funktioniert der sbrs-Befehl ohne weiteres.
Beim Setzen oder Loeschen von Bits im Register muss man im Hinterkopf
haben, dass der Befehl sbr das gleiche macht (und logischerweise den
gleichen Opcode liefert) wie der Befehl ori. Hierbei kann man natuerlich
gleichzeitig mehrere Bits setzen. Das sieht dann so aus:

sbr Status, (1<<STAT_RATE | 1<<STAT_TASTE | 1<< STAT_BATTVOLL)

Ich geb es ja zu: besonders schoen ist es nicht, aber es funktioniert.
 
Christian Sander wrote:

Liebe Newsgroup,

ich habe in einem Register folgendes definiert:

.def temp=r25 ;Register zur allgemeinen Verwendung

.equ rs_recv=0
.equ Ser_Busy=1
.equ TX_Ready=2
.equ RX_Ready=3
.equ int_Rx_Ready=4

Ziel war es den einzelnen Speicherzellen des Registers Labels zuzuordnen
die ich
dann später im Programm direkt ansprechen kann. Ungefähr so wie bei 8051
der bitadressierbare Bereich.

Leider klappt es nicht so wie ich es mir vorgestellt habe. Wo ist mein
Denkfehler?

Grüße aus München,

Christian
Es gibt auch noch die Möglichkeit über das Transfer-Flag zu gehen, das würde
so aussehen:

;Deine EQUs kannst Du beibehalten.


Bit_setzen:

SET
;Setzt das Transfer-Flag auf '1'
BLD temp, TX_Ready
;Setzt das Bit TX_Ready im Register temp auf den Wert vom Transfer-Flag

CLT
;Setzt das Transfer-Flag auf '0'
BLD temp, TX_Ready
;Setzt das Bit TX_Ready im Register temp auf den Wert vom Transfer-Flag

zum Bitlesen aus einem Register kannst Du irgendeine
Skip-If-Bit-Is-Set/Cleared-Funktion benutzen.


Viele Grüße,
Michael
 
Vielen Dank Euch allen für die Hilfe. Jetzt funktionierts.

Damit hat es jetzt funktioniert, und noch besser, ich habe es verstanden.
Jetzt wo es funktioniert werde
ich auch die anderen Lösungsvorschläge ausprobieren.

Grüße,

Chris




Christian Sander wrote:

Liebe Newsgroup,

ich habe in einem Register folgendes definiert:

.def temp=r25 ;Register zur allgemeinen Verwendung

.equ rs_recv=0
.equ Ser_Busy=1
.equ TX_Ready=2
.equ RX_Ready=3
.equ int_Rx_Ready=4

Ziel war es den einzelnen Speicherzellen des Registers Labels zuzuordnen
die ich
dann später im Programm direkt ansprechen kann. Ungefähr so wie bei 8051
der bitadressierbare Bereich.

Leider klappt es nicht so wie ich es mir vorgestellt habe. Wo ist mein
Denkfehler?

Grüße aus München,

Christian

Es gibt auch noch die Möglichkeit über das Transfer-Flag zu gehen, das
würde
so aussehen:

;Deine EQUs kannst Du beibehalten.


Bit_setzen:

SET
;Setzt das Transfer-Flag auf '1'
BLD temp, TX_Ready
;Setzt das Bit TX_Ready im Register temp auf den Wert vom
Transfer-Flag

CLT
;Setzt das Transfer-Flag auf '0'
BLD temp, TX_Ready
;Setzt das Bit TX_Ready im Register temp auf den Wert vom
Transfer-Flag

zum Bitlesen aus einem Register kannst Du irgendeine
Skip-If-Bit-Is-Set/Cleared-Funktion benutzen.


Viele Grüße,
Michael
 
Christian Sander schrieb:
.def a_flag=r25 ;Register zur allgemeinen Verwendung
;Flag von A Flag
.equ Ser_Busy=1
.equ TX_Ready=2
.equ RX_Ready=4
.equ int_Rx_Ready=8

Über den Studio Debugger schaue ich mir das Register 25 an.
Da steht vor meinem Befehl 0x04 darin.

Trotzdem springt er mir in folgender Routine nach RECEIVE_CONTROL_END.

Wer weis RAT?

RECEIVE_CONTROL: sbrs a_flag,int_Rx_Ready
rjmp RECEIVE_CONTROL_END

cbi PORTA, LED1 ;LED anschalten
RECEIVE_CONTROL_END:ret
Ja, ist bei diesen Werten korrekt.

Bit 8 (int_Rx_Ready) ist in Register r15=0x04 (a_flag) nicht gesetzt,
daher ist sbrs -> no skip. Es wird rjmp ausgefuehrt.
Hmm, eigentlich sollte es eine Compiler-Warnung bei Bit 8 geben.

Du solltest die Bitnummnern verwenden.

Sonst empfehle ich (aehnlich wie Mathias Weierganz) die Befehle
CBR (intern wie ANDI) und SBR (intern wie ORI) und Bitmasken (1<<bit#).
Abfragen mit SBRS/SBRC.

Bei IO-Register gibt es andere Befehle (CBI,SBI, ...), wichtig ist
diese nicht zu mischen. Der Compiler bemerkt nicht ob du auf r25
oder IO-Register 25 zugreifen willst.

BTW: Bitte verbessere dein Quoting. Durch bessere Lesbarkeit
wird auch die Chance auf Antworten hoeher.
http://www.afaik.de/usenet/faq/zitieren/

servus thomas
Ť
--
Die 4. Österreichische Fan-Convention zum Thema Japanische Popkultur
** AniNite 2004 ** 20.-22.August 2004 ** http://www.aninite.at/ **
Anime & Manga * J-Pop Bar * Cosplay * Videogames * Go * DDR * AMV *
Manga Workshop * Quiz * Trading Cards * Vortraege * Origami * Kyudo *
 

Welcome to EDABoard.com

Sponsor

Back
Top