Forum: Mikrocontroller und Digitale Elektronik assembler avr


von T.S. (Gast)


Lesenswert?

hallo zusammen
ich will in assembler 2register miteinander vergleichen mit folgendem
code:

ldi  r30,r15 == r14
wenn es true ist sollte es ins register 30 eine 1 schreiben sonst eine
0
weshalb funktioniert es nicht?
mfg

von Tom (Gast)


Lesenswert?

Hmm, ich glaube du solltest dir mal die Assembler-Basics anschauen. Das
sieht mir doch sehr nach C aus, nur mit anderer Syntax. In Assembler
kann immer nur eine Operation pro Befehl ausgeführt werden, das oben
ist viel zu komplex.

Probiers mal mit:
cp r14, r15
breq gleich
ungleich:
ldi r30, 0
rjmp weiter
gleich:
ldi r30, 1
weiter:
...

Zwar nicht sonderlich sinnvoll, aber das macht dann was du
beabsichtigst.

Tom

von dj4ee (Gast)


Lesenswert?

hmm, kann der Assembler solche Ausdrücke eigentlich ?

Probiers mal mit
ldi r30,(r15 == r14) kann mir aber kaum vorstellen, daß der Assembler
versteht, was Du meinst..

ich hätte das allerdings so gelöst:

...
clr r30
cp r15,r14
sbrc STATUS,Z
ldi r30,1
...

Greetz,
MK

von Peter Dannegger (Gast)


Lesenswert?

1
  ldi   r30, 1
2
  cpse  r14, r15
3
  ldi   r30, 0


Peter

von T.S. (Gast)


Lesenswert?

danke für eure hilfe, ich hab diesen befehl aus dem buch
"Mikrocomputertechnik mit controllern der atmel AVR-RISC-Familie" von
g.schmitt, erzählt dieser typ scheiss in seinem buch?
ich arbeite mit dem atmega8

von thkais (Gast)


Lesenswert?

Könnte ein Makro sein, standard-Code ist das nicht.

von T.S. (Gast)


Lesenswert?

so ich muss den ganzen code veröffentlichen, ist mir peinlich das ich es
nicht selber lösen kann aber ich komm nicht mehr weiter. dies sollte ei
einfaches Blinklicht werden, sollte:

.INCLUDE "m8def.inc"
.CSEG
.DEF  STATUS = r18
ldi    r16,0xFF
out   DDRD,r16
ldi  Y,0xFE
out   DDRB,r17

schlei:

      ldi    Y,0
      ldi    Y,0x0F
      out    PORTD,r18

  wart1_0:
      adiw   Y,1
      clr   r30
      cpi   Y,255
      sbrc   STATUS,Z
      cpi   r30,1
  breq wart1_1
  breq wart1_0

  wart1_1:
      ldi    Y,0
      ldi    r18,0xF0
      out    PORTD,r18

  wart2_0:
      adiw   Y,1
      clr   r30
      cpi   Y,255
      sbrc   STATUS,Z
      cpi   r30,1
  breq wart2_1
  breq wart2_0

  wart2_1:

rjmp     schlei
.EXIT

die fehler meldungen sind am dateianhang.

von haves (Gast)


Lesenswert?

welcher Anhang?!

von T.S. (Gast)


Angehängte Dateien:

Lesenswert?

sorry,habe noch einiges verändert geht leider immer noch nicht:


.INCLUDE "m8def.inc"
.CSEG
ldi    r16,0xFF
out   DDRD,r16
ldi    r17,0xFE
out   DDRB,r17

schlei:
  wart2_1:
      ldi    Y,0
      ldi    r18,0x0F
      out    PORTD,r18
  wart1_0:                    ;sollte ein delay sein
      adiw           Y,1
      cpi           Y,255
  breq wart1_1
    breq wart1_0

  wart_1:
      ldi    Y,0
      ldi    r18,0xF0
      out    PORTD,r18

  wart2_0:
      adiw           Y,1
      cpi          Y,255
  breq wart2_1
  breq wart2_0


rjmp     schlei
.EXIT

von eSBeO (Gast)


Lesenswert?

Zunächst findet er die Datei "m8def.inc" nicht => prüfen ob sich die
Datei am angegebenen Ort befindet.

Wer oder was sind "Y" und "Z"? => zb.: .def Y=r17 und .def Z=r18

eSBeO

von haves (Gast)


Lesenswert?

Hi,

  wart2_1:
      ldi    Y,0  <-- Y?

Ich denke dein Kompiler weiß nicht was Y ist bzw. welches Register das
sein sollen. Muss denfiniert werden.

Füg mal die Zeile
.def Y = r19

Am Anfang nach .CSEG ein.

MfG
haves

von eSBeO (Gast)


Lesenswert?

Weiterhin:

"adiw" akzeptiert nur die Register 24, 26, 28 und 30.

"sbrc Rc, b": Prüft Bit b des Registers Rr und überspringt die
nachfolgende Anweisung, wenn das Bit gelöscht ist.
Und hier sind: 0<=r<=31, 0<=b<=7

eSBeO

von Läubi (Gast)


Lesenswert?

X, Y, Z sidn doch die (vordefinierten) 16bit register, aber ohne die
Definitionsdatei steht der Compiler natürlich wie der Ochse vorm Berg.

von eSBeO (Gast)


Lesenswert?

@Läubi
Das tut er auch mit eingebundener Definitionsdatei, denn dort sind XL,
XH, YL, YH, ZL und ZH definiert.

@T.S.
Y durch YL und Z durch ZL ersetzen, dann hast Du nur noch eine
Fehlermeldung.

eSBeO

von Rolf Magnus (Gast)


Lesenswert?

X, Y und Z sind keine Register, sondern Registerpaare. Mit ldi kann man
aber nur ein einzelnes Register laden. Man muß also den high- und
low-Teil einzeln laden. Das gilt sinngemäß auch für cpi.
Aus dem ldi würde dann:

      ldi    YH, 0
      ldi    YL, 0

Beim cpi sieht's dann etwa so aus:

      cpi    YL, 255

Da dein Y-Wert nie über 255 zu gehen scheint, kannst du dir den
Vergleich des High-Teils sparen. Sonst würde es etwa so aussehen:

      ldi    R16, high(255)
      cpi    YL,  low(255)
      cpc    YH,  R16

Mir ist allerdings nicht klar, warum du überhaupt die Y-Register
nimmst. Die sind eigentlich eher für die Adressierung von Speicher
gedacht, welche du hier nicht machst.

Was den Fehler in Zeile 16 angeht, hat der Assembler recht. Ein Label
mit Namen "wart1_1" existiert tatsächlich nicht.

von T.S. (Gast)


Lesenswert?

ich habe mit folgendem code ein delay versucht zu programmieren:
 .DEF bla = r28
  wart1_0:
      adiw   bla,1
      cpi   bla,255
  breq wart1_1
    breq wart1_0

        wart1_1:


jedoch erhalte ich immer noch eine blinkfrequenz von 4xx khz. wie mus
ich das anderslösen damit ich eine frequenz um die 10Hz erhalte?

von Rolf Magnus (Gast)


Lesenswert?

Am einfachsten lässt sich sowas mit einem Timer machen, aber mit
Warteschleifen geht's natürlich auch. Wenn's zu schnell ist, kannst
du auch zwei Warteschleifen verschachteln.

> .DEF bla = r28
>
>   wart1_0:
>      adiw   bla,1

Wieso eigentlich adiw?

>       cpi   bla,255
>   breq wart1_1
>     breq wart1_0

Das zweite breq wird niemals einen Sprung durchführen. Die "Schleife"
wird also nur einmal durchlaufen. Nach dem ersten Durchlauf hat 'bla'
den Wert 1 (sofern es anfangs auf 0 initialisiert war). Es ist also
nicht gleich 255. Somit führt keines der beiden breqs einen Sprung
durch. Wenn der Wert 255 wäre, würde das erste breq springen, und das
zweite würde erst gar nicht zur Ausführung gelangen.

>         wart1_1:

Eine einfache Warteschleife würde so aussehen:

    ser r16
warte:
    dec r16
    brne warte

Vor das dec kann man noch ein paar NOPs einsetzen, um die Schleife
langsamer zu machen. Wenn man noch länger warten will, nimmt man eben
zwei verschachtelte Schleifen:

    ser r16
warte1:
    ser r17
warte2:
    dec r17
    brne warte2
    dec r16
    brne warte1

Das kann man natürich auch noch weiter treiben, je nach gewünschter
Wartezeit.

von T.S. (Gast)


Lesenswert?

habe noch eine frage: was machen die Befehle dec und ser
hei danke für die antwort, mein programm funktioniert jetzt mit einer f
von 2.55Hz
code:
.INCLUDE "m8def.inc"
.CSEG
ldi    r16,0xFF
out   DDRD,r16
ldi    r17,0xFE
out   DDRB,r17
ldi    ZL,0
ldi    YL,0
ldi    XL,0

schlei:

      ldi    XL,0
      ldi    ZL,0
      ldi    YL,0
      ldi    r18,0x0F
      out    PORTD,r18
  wart3_0:
      ldi    ZL,0
  wart2_0:
      ldi    YL,0
  wart1_0:
      adiw   YL,1
      cpi   YL,255
      breq   wart1_1
        brlo   wart1_0
  wart1_1:
      adiw   ZL,1
      cpi   ZL,255
      breq   wart2_1
        brlo   wart2_0
  wart2_1:
      adiw   XL,1
      cpi   XL,4
      breq   wart3_1
        brlo   wart3_0
  wart3_1:
      ldi    XL,0
      ldi    ZL,0
      ldi    YL,0
      ldi    r18,0xF0
      out    PORTD,r18
  wart6_0:
      ldi    ZL,0
  wart5_0:
      ldi    YL,0
  wart4_0:
      adiw   YL,1
      cpi   YL,255
      breq   wart4_1
        brlo   wart4_0
  wart4_1:
      adiw   ZL,1
      cpi   ZL,255
      breq   wart5_1
        brlo   wart5_0
  wart5_1:
      adiw   XL,1
      cpi   XL,4
      breq   wart6_1
        brlo   wart6_0
  wart6_1:
      ldi    XL,0
      ldi    ZL,0
      ldi    YL,0
      ldi    r18,0xF0
      out    PORTD,r18



rjmp     schlei
.EXIT

von Simon K. (simon) Benutzerseite


Lesenswert?

Oh mein Gott. Sorry aber das ist ja echt würgs. Nur warteschleifen?

Das ist so, als würdest du mit 3 Jahren zum Zahnarzt gehen, 5Jahre lang
dort rumsitzen, 5minuten Zähne nachgucken lassen, und dann wieder
gehen.

Naja macht ja erstma nixx.

dec dekrementiert das Register um 1. pseudocode: Register = Register -
1
ser lädt das register mit 255 (0b11111111) pseudocode: Register = 255

von T.S. (Gast)


Lesenswert?

ja nur warteschleifen, hei ist mein erstes asm programm! wenn ich es
besser könnte hätte ich auch eine professionellere warte schlaufe
gemacht!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.