Forum: Mikrocontroller und Digitale Elektronik Bisschen Assembler


von Simon K. (simon) Benutzerseite


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:

1
  cli
2
    
3
  in temp1, CNT_PORT  //Aktuellen Counterport in temp1
4
  mov temp2, temp1  //Sicherungskopie nach temp2
5
6
  inc temp1    //Um 1 erhöhen
7
  andi temp1, 0b00001111  //untersten 4 Bits bleiben über
8
  
9
  andi temp2, 0b11110000  //untersten 4 Bits löschen
10
  or temp2, temp1    //Die untersten 4 Bits aus temp1
11
12
  out CNT_PORT temp1  //Alles wieder ausgeben
13
14
  sei

Ausgenommen der Register-Sicherungsroutinen.

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

von Simon K. (simon) Benutzerseite


Lesenswert?

In Reihe 12 muss es

out CNT_PORT, temp2

heißen

von Hannes L. (hannes)


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.

...

von Christian Rötzer (Gast)


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

von Simon K. (simon) Benutzerseite


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
1
  push temp1      //Temp1 Sichern
2
  push temp2      //Temp2 Sichern
3
  in sreg_save, SREG    //SREG Sichern
4
.......
5
6
  out SREG, sreg_save    //SREG wiederherstellen
7
  pop temp2      //Temp2 wiederherstellen
8
  pop temp1      //Temp1 wiederherstellen

von Hagen (Gast)


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

von Simon K. (simon) Benutzerseite


Lesenswert?

Hmm....

Wie ist denn folgendes?
1
  in temp1, CNT_PORT //(1)
2
  swap temp1 //(1)
3
  subi temp1, -0x10 //(1)
4
  swap temp1 //(1)
5
  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?

von Simon K. (simon) Benutzerseite


Lesenswert?

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

von Simon K. (simon) Benutzerseite


Angehängte Dateien:

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.

von Simon K. (simon) Benutzerseite


Lesenswert?

Naja ein Kommentar stimmt nicht. Egal jetzt. Nachti!

von xyz (Gast)


Angehängte Dateien:

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

von Simon K. (simon) Benutzerseite


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.

von Hartmut Gröger (Gast)


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

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.