mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Bisschen Assembler


Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leute. Ich versuche gerade folgendes schneller zu machen.

Es ist in einer Interrupt Routine und soll folgendes Bewirken:
Sagen wir es gibt den CNT_PORT. Ein Port, wo an den untersten 4 Bits
ein 4/16 Decoder hängt(74HCT154). Ich möchte jetzt den Zähler immer von
0-15 durchzählen ohne den Rest vom Port zu verändern.
Folgendes habe ich mir dabei ausgedacht:

  cli
    
  in temp1, CNT_PORT  //Aktuellen Counterport in temp1
  mov temp2, temp1  //Sicherungskopie nach temp2

  inc temp1    //Um 1 erhöhen
  andi temp1, 0b00001111  //untersten 4 Bits bleiben über
  
  andi temp2, 0b11110000  //untersten 4 Bits löschen
  or temp2, temp1    //Die untersten 4 Bits aus temp1

  out CNT_PORT temp1  //Alles wieder ausgeben

  sei

Ausgenommen der Register-Sicherungsroutinen.

Habt ihr nen Vorschlag wie ich das beschleunigen könnte?

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In Reihe 12 muss es

out CNT_PORT, temp2

heißen

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lass cli und sei weg, das macht der AVR selbst.
Den Rest kriege ich momentan auch nicht optimaler...

SREG-Sicherung und Registersicherung hast du aber sicherlich drin.

...

Autor: Christian Rötzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du die oberen vier Bits verwenden würdest, dann könntest Du Dir die
ganze "Verunderei" sparen:

in temp1,CNT_PORT
addi temp1,0x10
out CNT_PORT,temp1

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicht schlecht die Idee. So habe ich einen Hardwaremäßigen Overflow.
Aber das is nix, da ich alles schon verdrahtet habe.

@Hannes: Ah, war mir nicht sicher wegen cli und sei. Ist ja
aufjedenfall nötig. Nicht dass ein anderer Interrupt den PORT
zwischendurch noch ändert, während ich da am rumoperieren bin.

Ja sicherung habe ich drin
  push temp1      //Temp1 Sichern
  push temp2      //Temp2 Sichern
  in sreg_save, SREG    //SREG Sichern
.......

  out SREG, sreg_save    //SREG wiederherstellen
  pop temp2      //Temp2 wiederherstellen
  pop temp1      //Temp1 wiederherstellen


Autor: Hagen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du könntest den Wert in CNT_PORT in zwei separaten Registern speichern.
Eines der Register ist der Zähler bis 15 und das andere enthält die
obersten 4 Bits.

  exor r31, r30
  inc  r30
  andi r30, 0x0F
  or   r31, r30
  out  CNT_PORT, r31


In r30 der Zähler, in r31 die obersten 4 Bits, macht 2 Taktzyklen
weniger, dafür 2 Register mehr verbraucht.

oder

  inc  r30
  brsh @1
  subi r30, 0x10
@@1:
  out  CNT_PORT, r30

Hier wird in r30 beides gespeichert, sowohl der Zähler und die obersten
4 Bits. Sollte nun der Zähler bei 16=0x10 überlaufen so wird das
Half-Carry-Flag gesetzt und wir müssen einfach 0x10 abziehen.
Macht dann 4 Taktzyklen und 1 Register.

Gruß hagen

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm....

Wie ist denn folgendes?
  in temp1, CNT_PORT //(1)
  swap temp1 //(1)
  subi temp1, -0x10 //(1)
  swap temp1 //(1)
  out CNT_PORT //(1)

Macht 5 Takte. 1Register Hihi.

Frage: Ist
subi temp1, -0x10
das equivalent zu
addi temp1, 0x10

Ich meine das so in Erinnerung zu haben. Man subtrahiert ja mit einem
negativen Wert, um zu addieren, oder?

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Scheint zu gehen. Da hab ich mich ja mal wieder selbst übertroffen. Ich
alter ASM hacker ;) ;) ;) ;)

Autor: Simon K. (simon) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ok, klappt. Ausprobiert.

Danke an euch. Christian gab mir die zünende Idee mit dem High Nibble
des Ports verwenden.

Im Anhang das Produkt.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja ein Kommentar stimmt nicht. Egal jetzt. Nachti!

Autor: xyz (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Guten Morgen Simon!

Den Code den Du da Reingestellt hast zählt meiner Meinung nach
Rückwärts!

Ich progge momentan auf 8051 Derivate und hab mal ein Equivalent dazu
geschrieben (siehe Anhang).

Gruß xyz

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo xyz:

Das Problem ist, dass der AVR kein Befehl hat, um ein Immediate zu
addieren (Oder ich habe ihn schlicht übersehen). Man kann nur 2
Register addieren.

meinermeinungnach sollte aber zum Beispiel
ADDI reg, 0x01
das gleiche sein wie
SUBI reg, -0x01

bsp:

  0b00000000    steht im Register
  0b11111111    soll abgezogen werden (entspricht -0x01)

  0b00000000    Registerwert
  0b00000000    Komplement von -0x01
  ----------    addieren
  0b00000001    Kein Overflow, 1 addieren


So seh ich das.

Autor: Hartmut Gröger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Für vorzeichenlose 8-Bit Zahlen
enspricht subi reg,-1  "addi" reg,1.

Wenn du ein Doppelregister frei hast kannst du auch adiw/sbiw
benutzen und nur das Low-Byte verwenden.Geht aber nur bis max.
+/-63.

Mfg HG

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.