Hallo,
ich hätte da mal eine Frage zur Abarbeitung einiger Befehle.
Bits setzen per define:
#define setzen1 11001100
#define setzen2 11001011
reg1 = setzen1;
[Something to do]
reg1= setzen2;
[Something to do]
reg1 = setzen1;
bits setzen durch log. Ops:
reg1= 11001100;
[something to do]
reg1 &= ~(1<< 2);
reg1 |=11;
[something to do]
reg1 &= ~((1<<1)|(1<<0));
reg1 |= (1<<2);
oder (falls das überhaupt geht):
reg1= 11001100;
[something to do]
reg1^=((1<<2) | (1<<1) | (1<<0));
Meine Frage nun, sofern die Operationen funktionieren, welche davon
verwendet man am Häufigsten bzw. welche ist die schnellste?
Und: Bitte um Korrektur, wenn ich Operationen falsch umgesetzt habe.
Vielen Dank für eure Hilfe.
gruß
Herbie
Herbie schrieb:> welche ist die schnellste?
Wofür?
Welche Zielplattform?
Z.B. ist ein Formel-1 Rennwagen der schnellste auf der Straße, aber auf
dem Feld ist ein Traktor schneller... :-/
Oh, entschuldigung.
Ich meinte, welche Operation ist auf einem Mikrocontroller der
ATMega-Serie (AVR) am Schnellsten durchzuführen?
Z.B. als Interrupt-Operation. Da sollen die Befehle ja möglichst schnell
abgearbeitet werden.
In dem Register sollen halt nur ein paar Bits umgeschrieben werden.
Danke für den Hinweis.
Kompiliere es doch mal und schau dir das listing / assembler an.
Generell ist es schneller, wenn reg = const als reg = (viele logische
ops).
Andererseits sieht das der Compiler vielleicht und macht ne Konstante
draus...
Ich verstehe ehrlich gesagt die Frage nicht so richtig.
Die beiden Teile sind nicht äquivalent, sie machen unterschiedliche
Dinge.
Die 3 Zuweisungen sind bestimmt nicht so zeitkritisch, daß Du hier über
eine Optimierung nachdenken müsstest.
Interessant ist da eher der Teil [something to to]
Udo Schmitt schrieb:> Die beiden Teile sind nicht äquivalent, sie machen unterschiedliche> Dinge.
Die 3 Teile sollten eigentlich alle das Gleiche machen.
Herbie schrieb:> reg1= 11001100;> [something to do]> reg1^=((1<<2) | (1<<1) | (1<<0));
Da habe ich noch vergessen:
[something to do]
reg1^=((1<<2) | (1<<1) | (1<<0));
(denke ich).
Wo ist denn der Fehler, wenn die nicht alle das Gleiche machen?
Herbie schrieb:> Meine Frage nun, sofern die Operationen funktionieren, welche davon> verwendet man am Häufigsten bzw. welche ist die schnellste?
Ich würde die Variante 1 nehmen, denn dann könnte ich einfach durch ein
Ändern des #defines definierte andere Werte auf das reg1 schreiben.
Bei den anderen beiden Versionen ist das wesentlich versteckter...
Das Setzen des Register reg1 soll am Ende immer gleich sein.
Also zwischen den [something to do]-Abschnitten.
Das erste Mal soll 11001100 in reg1 stehen. Dann kommt [something to
do], danach soll 11001011 in reg1 stehen. Dann wieder [something to do]
und danach soll wieder 11001100
in reg1 stehen.
Udo Schmitt schrieb:> Kann jetzt aber auch nicht mehr weiter reinschauen, muss arbeiten,> sorry.
Ok, danke für deine Hilfe. Viel Spaß beim Arbeiten.
Ich würde das Ganze im Simulator vom AVR-Studio ablaufen lassen.
Da gibt es für die Zeit und die Anzahl der Zyklen
eine gute Anzeige, kann man sogar rücksetzen.
Lothar Miller schrieb:> Ich würde die Variante 1 nehmen, denn dann könnte ich einfach durch ein> Ändern des #defines definierte andere Werte auf das reg1 schreiben.> Bei den anderen beiden Versionen ist das wesentlich versteckter...
Danke sehr. Die andern beiden Versionen wären halt variabel; aber
defines sind übersichtlicher.
Wäre denn die 1. Variante auch am Schnellsten oder tun die sich da alle
nicht viel?
AVR-Fan schrieb im Beitrag #1965931:
> Ich würde das Ganze im Simulator vom AVR-Studio ablaufen lassen.
Das habe ich leider nicht. Also ich kann es nicht über die
Entwicklungsumgebung testen.
(Zumindest momentan nicht)
ein blick in die assembler-doku hilft weiter bezgl der
ausführungszeiten.
da ein c-compiler mit unterschiedlichen optimierungs-varianten arbeiten
kann, ist auch der generierte assembler-code unterschiedlich.
generell schlägt eine logische operation mit einem takt zu buche,
genauso eine zuweisung. zusätzlich können noch stack-operationen
dazukommen, da man in c nicht so viel kontrolle über die einzelnen
register hat wie in assembler
> reg1 &= ~((1<<1)|(1<<0));> reg1 ^= ((1<<2) | (1<<1) | (1<<0));
In beiden Varianten läuft das bei reg1 = I/O-Register auf laden,
modifizieren, speichern als 3 getrennte Operationen raus.
> reg1 |= (1<<2);
Wenn reg1 im bitadressierbaren Bereich der I/O-Ports liegt, dann ist das
ein einziger Befehl, somit effizienter. Wenn nicht, dann lauft das genau
wie oben.
A. K. schrieb:> In beiden Varianten läuft das auf laden, modifizieren, speichern als 3> getrennte Operationen raus.
das muss aber nicht sein, die variable kann ja schon in einem Register
stehen. Bzw. sie kann eine Lokale Variable sein und nur in einem
Register vorhanden sein.