Forum: Mikrocontroller und Digitale Elektronik Framework zur Ansteuerung von LEDs


von Bernhard (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Zusammen!

Vor einiger Zeit habe ich einen Code entwickelt mit dem man LEDs 
verschieden ansteuern kann. Funktionen wie EIN, AUS, BLINKEN und BLITZEN 
werden unterstützt. Compiliert belegt dieser aktuell 374 Bytes.
Die LED's liegen an einem Port an Px0 bis Px3

Die Funktion led_process sollte in einem Timer z.B. jede 10ms aufgerufen 
werden.

Trotz der kleinen Größe finde ich ihn immernoch etwas umständlich.
Ich suche noch etwas "Intelligenz" wie z.B. der Code von Peter Dannegger 
(ich erinnere mich an die kleinen und schnellen Debounce-Routinen)

Vielleicht hat jemand noch eine Idee was man besser machen kann :)

Grüße,
Bernhard

von Karl H. (kbuchegg)


Lesenswert?

Das hier
1
  for (i = 0; i < LED_COUNT; i++) {
2
    if (ledctx[i].state == LED_OFF) {
3
      out &= ~_BV(i);

sind so typische Operationen, die du nicht haben willst, wenn der µC 
keinen Barrelshifter hat. Das _BV(i) muss dann vom Compiler in eine 
Schleife aufgelöst werden
1
   result = 0x01;
2
   for( j = 0; j < i; j++ )
3
     result <<= 1;

und das willst du eigentlich nicht. Vor allen Dingen, wenn es sich 
leicht vermeiden lässt
1
  uint8_t bitMask;
2
3
  bitMask = 0x01;
4
5
  for (i = 0; i < LED_COUNT; i++) {
6
7
8
    if (ledctx[i].state == LED_OFF) {
9
      out &= ~bitMask;
10
11
      ....
12
    }
13
    ....
14
15
    bitMask <<= 1;
16
  }




Deine Schreibweise ist furchtbar. Deine else hab ich erst im dritten 
Anlauf gesehen. Es ist nichts falsch an
1
   if ( ..... ) {
2
3
     ....
4
   }
5
6
   else if( ...... ) {
7
     ....
8
   }
9
10
   else if( ...... ) {
11
     ....
12
   }
13
14
   else {
15
     ....
16
   }

ausser, dass so auch ein halbblinder Blindenhund auf 5 Meter Entfernung 
sehen kann, dass es sich um mehrere Alternativen handelt, von denen die 
erste genommen wird.

Bei
1
   if ( ..... ) {
2
3
     ....
4
   } else
5
6
   if( ...... ) {
7
     ....
8
   } else
9
10
   if( ...... ) {
11
     ....
12
   }
13
14
   else {
15
     ....
16
   }

sieht man das weit nicht so gut, weil jeder automatisch immer auf den 
Zeilenafang schaut und nicht eine Zeile drüber, ob da vor dem if noch 
ein else steht. Beim schnellen drüber lesen sind das 3 voneinander 
unabhängige if. Und erst im dritten Anlauf entdeckt man dann noch die 
else und stellt die richtige Assoziation her, dass die 3 if dann doch 
nicht so unabhängig voneinander sind, wie es erst den Anschein hatte.

von Bernhard (Gast)


Lesenswert?

@Karl Heinz Buchegger:

Vielen Dank, jetzt ist der Code nur noch 322 Bytes lang.
Die _BV(i) Operationen bzw. 1 << i haben mir auch noch nicht gefallen. 
Deine Lösung ist super, ich sitze wahrscheinlich heute schon zu lang 
vorm Rechner, sonst wäre mir das auch gleich aufgefallen :)

Die Schreibweise habe ich angepasst, mit der Zeit gewöhnt man sich in 
der Tat ein paar Undinge an

Jetzt sieht das ganze so aus:
1
void led_process(void)
2
{
3
        static uint8_t out = 0;
4
        uint8_t i, mask;
5
6
        for (i = 0, mask = 1; i < LED_COUNT; i++, mask <<= 1) {
7
                if (ledctx[i].state == LED_OFF) {
8
                        out &= ~mask;
9
                } else if (ledctx[i].state == LED_ON) {
10
                        out |= mask;
11
                } else if (!ledctx[i].timer) {
12
                        if (ledctx[i].state == LED_BLINK) ledctx[i].timer = BLINK_TIME;
13
                        if (ledctx[i].flag) {
14
                                if (ledctx[i].state == LED_FLASHON) ledctx[i].timer = FLASH1_TIME;
15
                                if (ledctx[i].state == LED_FLASHOFF) ledctx[i].timer = FLASH2_TIME;
16
                                ledctx[i].flag = 0;
17
                                out &= ~mask;
18
                        } else {
19
                                if (ledctx[i].state == LED_FLASHON) ledctx[i].timer = FLASH2_TIME;
20
                                if (ledctx[i].state == LED_FLASHOFF) ledctx[i].timer = FLASH1_TIME;
21
                                ledctx[i].flag = 1;
22
                                out |= mask;
23
                        }
24
                } else {
25
                        ledctx[i].timer--;
26
                        continue;
27
                }
28
29
        }
30
        LED_PORT = (LED_PORT & 0xF0) | out;
31
}

von Bernhard (Gast)


Lesenswert?

Gerade festgestellt, wenn man folgenden Code mit einem else ergänzt, 
dann spart man jeweils 10 Bytes:

Davor
1
if (ledctx[i].state == LED_FLASHON) ledctx[i].timer = FLASH1_TIME;
2
if (ledctx[i].state == LED_FLASHOFF) ledctx[i].timer = FLASH2_TIME;

danach
1
if (ledctx[i].state == LED_FLASHON) ledctx[i].timer = FLASH1_TIME; else
2
if (ledctx[i].state == LED_FLASHOFF) ledctx[i].timer = FLASH2_TIME;

Ich vergleiche gleich mal die lst Files, der Unterschied ist schon 
beträchtlich und interessiert mich grad bennend

von Bernhard (Gast)


Lesenswert?

Sieht so aus als ob der Compiler ohne "else" den Wert von state komplett 
neu aus dem Speicher lädt.
Mit dem else wird der Wert im Register wiederverwendet.

Also macht es auch Sinn den Wert von z.B. ledctx[i].state in eine lokale 
Variable zu packen da diese recht oft verwendet wird.

Jetzt sind wir schon bei 278 Bytes - es funktioniert alles noch 
einwandfrei.
1
void led_process(void)
2
{
3
        static uint8_t out = 0;
4
        uint8_t i, mask, state;
5
6
        for (i = 0, mask = 1; i < LED_COUNT; i++, mask <<= 1) {
7
8
                state = ledctx[i].state;
9
10
                if (state == LED_OFF) {
11
                        out &= ~mask;
12
                } else if (state == LED_ON) {
13
                        out |= mask;
14
                } else if (!ledctx[i].timer) {
15
                        if (state == LED_BLINK) ledctx[i].timer = BLINK_TIME;
16
                        if (ledctx[i].flag) {
17
                                if (state == LED_FLASHON) ledctx[i].timer = FLASH1_TIME; else
18
                                if (state == LED_FLASHOFF) ledctx[i].timer = FLASH2_TIME;
19
                                ledctx[i].flag = 0;
20
                                out &= ~mask;
21
                        } else {
22
                                if (state == LED_FLASHON) ledctx[i].timer = FLASH2_TIME; else
23
                                if (state == LED_FLASHOFF) ledctx[i].timer = FLASH1_TIME;
24
                                ledctx[i].flag = 1;
25
                                out |= mask;
26
                        }
27
                } else {
28
                        ledctx[i].timer--;
29
                        continue;
30
                }
31
        }
32
33
        LED_PORT = (LED_PORT & 0xF0) | out;
34
}

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.