Forum: Mikrocontroller und Digitale Elektronik Noch weiter springen?


von AVRli (Gast)


Lesenswert?

Hi Leute,

ich komme bei meinem Projekt so richtig voran.
Nun stoppe ich an einer kleinen Sache aber ich komme nicht dahinter wie
man es geschickt umgehen kann. :-(

Ich habe nun wohl eine Grenze überschritten...
In der BRNE Zeile bleibt der Compiler hängen und meint...
": error : Relative branch out of reach"

  cpi r16,'A'
  brne CMD_END
...
nen paar Zeilen Code
...
  CMD_END:
  ret

Nun was er meint weiß ich... ;-I
CMD_END ist mehr als -64 bzw. +63 Worte entfernt...

Kann mir einer mal nen Tip geben wie ich denoch dahin springen kann?

Gruß AVRli...

von Tobi (Gast)


Lesenswert?

mit nem zusätzlichen jmp befehl.nimm nen cmd mit bedingung genau
umgekehrt zu der die du haben willst, der den nächsten befehl
überspring und dann kannst du als nächsten befehl den richtigen jmp
machen. ein bissl konfus, ich weiss :)

von Thomas Burkhardt (Gast)


Lesenswert?

Hi,

baue eine Hilfskonstruktion mit einem rjmp welcher deutlich weiter als
63 Worte reicht :)

Also:

  cpi r16,'A'
  breq GO_ON
  rjmp CMD_END
GO_OM:
...
nen paar Zeilen Code
...
  CMD_END:
  ret

von AVRli (Gast)


Lesenswert?

Danke für die schnelle Antwort! ;-)
Ist aber sehr aufwendig wenn man mehrere Zeichen vergleichen muss. ;-(

Also ich wollte wieder raushüpfen wenn eine bestimmte Zeichenfolge
nicht da ist.
Beispiel "ABC"

Das habe ich nun immer so gemacht...

  ld r16,X+
  cpi r16,'A'
  brne CMD_END
  ld r16,X+
  cpi r16,'B'
  brne CMD_END
  ld r16,X+
  cpi r16,'C'
  brne CMD_END
...
nen paar Zeilen Code
...
  CMD_END:
  ret

Das währen dann 3 Hilfsfunktionen... was für ein "durcheinander"...
;-)
Ich probiere es trotzdem mal...

Gruß AVRli...

von Thomas Burkhardt (Gast)


Lesenswert?

Mmmh, das ist als würdes du vielfache if-thens schachteln, also sowieso
nicht gut :->

Kannst du nicht deinen String irgendwo als Konstante ablegen und dann
per Y indiziert in einer Schleife abarbeiten?

Grüße

von AVRli (Gast)


Lesenswert?

Hi Thomas,

da hab ich noch keine Ahnung von.
Da fängt es dann wieder an spannend zu werden. :-)

Also ich lese meine Kommandos via RS232 in den SRAM
auf denn kann ich auch zugreifen...

Konstante würde ich so machen...

CMD_ABC:
.db "ABC"

Und nun in einer Schleife SRAM mit CMD_ABC vergleichen...
gibt es einen Unterschied dann raus ansonsten weiter...

Ansatz ok?

Gruß AVRli...

von crazy horse (Gast)


Lesenswert?

dann machs erstmal so:
  ld r16,X+
  cpi r16,'A'
  brne CMD_END1
  ld r16,X+
  cpi r16,'B'
  brne CMD_END1
  ld r16,X+
  cpi r16,'C'
  brne CMD_END1
  rjmp weiter
cmd_end1: rjmp cmd_end
weiter:
...
nen paar Zeilen Code
...
  CMD_END:
  ret

Nicht die eleganteste Art, aber erstmal verständlich und
funktionierend, kannst also erstmal weiterarbeiten. Die Feinheiten
kommen später :-)

von Andi (Gast)


Lesenswert?

Das einzelne Vergleichen jedes einzelnen Zeichens ist doch sehr Mühsam.
Voallem, wenn es häfiger Vorkommt.
Habe mal schnel ohne AVR-Studio ein kleines Beispiel gemacht, wie man
es "routinieren" könnte.


Der Pointer auf den Eingabetext ist in X (XL,XH).

 ldi zl,low(Text1*2)
 ldi zh,high(Text1*2)
 rcall TextVergleich
 brne VergleichText2
...
nen paar Zeilen Code
...
 ldi zl,low(Text2*2)
 ldi zh,high(Text2*2)
 rcall TextVergleich
 brne VergleichText3

TextVergleich:
 clr r16              ;Ausgangsflag auf 0 setzen
TV1:
 lpm r17,z            ;n-tes Zeichen nach r17 aus dem Flash lesen
 addw zl,1            ;Z-Pointer auf das nächste Zeichen verschieben
 tst r17              ;Schon am Ende des Vergleichtextes angekommen?
 breq TVExit          ;Dann Vergleich positiv und raus
 ld r18,x+            ;n-tes Zeichen des Eingabetextes nach r18
 cp r17,r18           ;Sind die Zeichen gleich?
 breq TV1             ;Wenn ja, dann nächstes Zeichen prüfen
 com r16              ;Ansonsten Vergleich auf negativ setzen (0
complement = FF in r16)
TVExit:
 tst r16              ;r16 auf 0 oder <> 0 testen
 ret

.dseg
Text1: .db "ABC",0
Text2: .db "DEF",0

Wichtig ist die 0 nach jedem Vergleichstext im Data-Segment damit das
Textende ermittelt werden kann.
Läßt sich natürlich noch verfeinern wenn es darum geht, das auf ein
komplettes Wort geprüft wird und nicht z. B. nur auf "aus" wenn man
als Eingabe "aussetzer" schreibt.

Ich habe es weder assembliert noch auf Korektheit prüfen lassen da ich
mit nen AVR für so was noch keinen Gebrauch hatte.
Also bitte nicht lästern bei evtl. Fehlern.
Soll auch mehr als Denkanstoß dienen.

Gruß
Andi

von crazy horse (Gast)


Lesenswert?

Alternativ kannst du natürlich auch bei cmd_end1 direkt ein return
hinsetzen, würde ich aber nicht empfehlen. Funktioniert zwar, aber man
sollte es bei Unterprogrammen mit einem Ausgang genug sein lassen.

von AVRli (Gast)


Lesenswert?

Hallo nochmal,

habe eine Lösung... die ist der vom Andi verdammt ähnlich.

CMD_AZ:
.db "ABC",0

SHOW_CMD_ABC:
  ldi ZL,low(CMD_ABC*2)
  ldi ZH,high(CMD_ABC*2)

CMD_ABC_COMPARE:
  lpm
  mov T1,r0
  cpi T1,0
  breq CMD_ABCgo
  adiw ZL,1

  ld T0,X+
  cp T0,T1
  breq CMD_ABC_COMPARE
  rjmp CMD_ABC_END

CMD_ABCgo:
...
Aktionen auf Befehl >63k
...

CMD_ABC_END

Funktionieren tut's... :-)
Danke Euch für den Austausch!

Gruß AVRli...

von Andi (Gast)


Lesenswert?

Wie bist denn darauf gekommen? ;-)
Mach es doch gleich als UP damit Du es auch für andere
Vergleichs-Strings verwenden kannst.
Am besten gleich so, dass das UP eine ganze Liste Befehle mit der
Eingabe vergleicht und hinter jedem Vergleichs-String gleich die
Adresse steht wo hin das UP dann springen soll.
z. B.:
 .db "ABS",0,Jump1
 .db "DEF",0,Jump2

Wenn Du das low-byte nach ZL und das high-byte nach ZH lädts
(wahrscheinlich über Umwege da Z der Pointer auf die Strings ist)
kannst Du dann mit dem Befehl IJMP (indirekt Jump jusing Register
Z-Pointer) gleich zu Jump1 oder Jump2 nach positivem Vergleich springen
lassen.
Viel Spaß noch beim basteln.

Gruß
Andi

von AVRli (Gast)


Lesenswert?

Hi Andi,

> Mach es doch gleich als UP damit Du es auch für andere
> Vergleichs-Strings verwenden kannst.

;-( puhhh das währe ja auch nicht schlecht.
Da es in der Tat mehrere Befehle sind.
Ich schlafe mal eine Nacht drüber.
Mal sehen vielleicht finde ich dann morgen raus wie man das macht.

Danke für den Tip... wieder was gelernt... :-)

Gruß AVRli...

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.