Anfängerfrage AVR Assembler

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

Reply to
Christian Sander
Loading thread data ...

Ich gehe mal davon aus, dass jedes EQU ein Bit im Register darstellen soll.

Leider kenne ich den 8051 nicht.

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

Reply to
Michael

Am Thu, 29 Jul 2004 11:06:00 +0200 hat Christian Sander geschrieben:

Hast du das entsprechende include file eingebunden? Beim Atmega8 z.B. .include "m8def.inc"

Gruß Chris

--
Wann hält Ulm an diesem Zug?
(A. Einstein)
Reply to
Christof Voelkle

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

soll.

keinen

d.h.

Reply to
Christian Sander

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.

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

Reply to
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

Reply to
Christian Sander

Natürlich geht das nicht. Ich meinte ja auch nicht denselben Namen!

Das wäre mir neu.

Ich kenne keine andere, außerdem ist sie nicht sehr umständlich, bis auf die Tatsache, das man eigene EQUs braucht...

Gruß Michael

Reply to
Michael

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

Reply to
Mathias Weierganz

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

Reply to
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

würde

Transfer-Flag

Transfer-Flag

Reply to
Christian Sander

Christian Sander schrieb:

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

Reply to
Thomas Mozgan

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.