Forum: Mikrocontroller und Digitale Elektronik code effizienter gestalten


von Paul (Gast)


Lesenswert?

Abend!
Ich stehe zur Zeit vor folgendem Problem.Hier erstmal der Code
1
SEGPORT |= (1<<SEG1);
2
spi_out(seg[16]);     // all off
3
SEGPORT &= ~(1<<SEG1);      
4
SEGPORT |= (1<<SEG2);
5
spi_out(seg[16]);     // all off
6
SEGPORT &= ~(1<<SEG2);    
7
SEGPORT |= (1<<SEG3);
8
spi_out(seg[16]);     // all off
9
SEGPORT &= ~(1<<SEG3);        
10
SEGPORT |= (1<<SEG4); 
11
spi_out(seg[16]);     // all off
12
SEGPORT &= ~(1<<SEG4);

gibt es eine Möglichkeit die ganze Geschichte in einer Schleife zu
behandeln?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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;
  }

von Rahul (Gast)


Lesenswert?

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...

von Simon K. (simon) Benutzerseite


Lesenswert?

rufus, du hast zweimal die tilde vergessen ;D

von A.K. (Gast)


Lesenswert?

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;
  }

von Paul (Gast)


Lesenswert?

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!

von Fabian Scheler (Gast)


Lesenswert?

"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

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

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

von Fabian Scheler (Gast)


Lesenswert?

Danke, jetzt hat es bezüglich des Shiftens 'Klick' gemacht!

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.