Gast
#270730
Abend! Ich stehe zur Zeit vor folgendem Problem.Hier erstmal der Code
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
gibt es eine Möglichkeit die ganze Geschichte in einer Schleife zu behandeln?
|
Anzeige
|
code effizienter gestalten
Gast
#270730
Abend! Ich stehe zur Zeit vor folgendem Problem.Hier erstmal der Code
gibt es eine Möglichkeit die ganze Geschichte in einer Schleife zu behandeln? Wenn die Konstanten SEG1..SEG4 sich jeweils um 1 unterscheiden, dann
ja:
int seg;
for (seg = SEG1; seg <= SEG4; seg++)
{
SEGPORT |= (1 << seg);
spi_out(seg[16]);
SEGPORT &= (1 << seg);
}
Das allerdings erzeugt keinen sonderlich effizienten Code, weil die
Shift-Operatoren nicht vom Compiler durch Konstanten ersetzt werden
können. Je nach Prozessor ist eine Shift-Operation recht ineffizient.
Da ließe sich dies hier verwenden:
int seg;
int i;
seg = 1 << SEG1;
for (i = 0; i < 4; i++)
{
SEGPORT |= seg;
spi_out(seg[16]);
SEGPORT &= seg;
seg <<= 1;
}
Gast
#270732
man könnte es so lösen:
unsigned char segs[4] = {SEG1,SEG2,SEG3,SEG4};
unsigned char i;
for(i=0;i<4;i++)
{
SEGPORT |= (1<<segs[i]);
spi_out(seg[16]);
SEGPORT &= (1<<segs[i]);
}
man könnte segs auch so initialisieren:
unsigned char segs[4]= {(1<<SEG1),(1<<SEG2),(1<<SEG3),(1<<SEG4)};
Wenn die Segs in einer bestimmten Reihenfolge angeordent sind, kann man
auch die Laufvariable dafür benutzen...
rufus, du hast zweimal die tilde vergessen ;D
Gast
#270734
Oder:
#define AlleSEGS (1<<SEG1|1<<SEG2|1<<SEG3|1<<SEG4)
for (seg = 1<<SEG1; seg & AlleSEGS; seg <<= 1)
{
SEGPORT |= seg;
spi_out(seg[16]);
SEGPORT &= seg;
}
Gast
#270735
uhi, danke! Da sind ja schon einige nette Lösungen bei. Ich werde mir alle nochmal genauer gucken. Auf jeden Fall schonmal vielen, vielen Dank!
Gast
#270736
"Je nach Prozessor ist eine Shift-Operation recht ineffizient."
hm, irgendwie klingt das für mich seltsam. Ich bin jetzt kein
E-Techniker, habe noch nie einen Prozessor gebaut, aber kann ich mir
leider nicht besonders gut vorstellen, was man an einer Shift-Operation
besonders ineffizient machen kann. Kannst du mir das mal erläutern?
Zu den beiden Code-Schnippseln:
int seg;
for (seg = SEG1; seg <= SEG4; seg++)
{
SEGPORT |= (1 << seg);
spi_out(seg[16]);
SEGPORT &= (1 << seg);
}
und
int seg;
int i;
seg = 1 << SEG1;
for (i = 0; i < 4; i++)
{
SEGPORT |= seg;
spi_out(seg[16]);
SEGPORT &= seg;
seg <<= 1;
}
also den Compiler, der aus dem obigen Fetzen nicht denselben Code
erzeugt, wie aus dem unteren (wenn man nicht gerade alle Optimierungen
ausschaltet), sollte man wirklich nicht verwenden.
zu guter letzt: hast du dir eigentlich mal angeschaut, was der Compiler
bei höchster Optimierungsstufe, aus dem originär abgebildeten Listing
macht. Ich kann mir vorstellen, dass es Laufzeittechnisch auf jeden
Fall schneller sein sollte und sich von der Codegröße her auch in
Grenzen halten sollte.
Ciao, Fabian
Hi 1<<n ist auf dem AVR architekturbedingt nicht besonders effizient wenn n nicht zur compilezeit bekannt ist da der AVR nicht über einen Barrelshifter verfügt, er also pro Takt nur um 1 Bit schieben kann. Ist n also zur Compilezeit nicht bekannt wird aus 1<<n eine Schleife mit n Durchläufen. Das will man nicht wirklich haben wenn es sich irgendwie verhindern läßt. Matthias
Gast
#270738
Danke, jetzt hat es bezüglich des Shiftens 'Klick' gemacht! Antwort schreiben |
Anzeige
|