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
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.
@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 | }
|
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.