www.mikrocontroller.net

Forum: Compiler & IDEs LED-Blinker eleganter?


Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich breche mir hier einen ab mit einer möglichst eleganten & vielseitig 
einsetzbaren Pulserzeugung z.B. für eine Signal-LED die mehrere Zustände 
anzeigen soll.

Das Problem: Ich kann's nicht elegant & vielseitig.
Daher würde ich mich über Verbesserungen des folgenden Codes sehr freuen 
und hoffentlich etwas lernen.

Denkbar wär' auch dass die Zeiten in einer Tabelle (Array) stehen, und 
ggf. wiederholt werden. Dann könnte man noch vielseitigere Pulsfolgen 
erzeugen.

Der folgende Code funktioniert, in einer Timer ISR findet ca. alle 10ms 
das eigentliche Blinken statt.

  uint8_t led_on   = 0;
  uint8_t led_off   = 0;
  uint8_t led_cycles   = 0;
  uint8_t led_tick_ref   = 0;
  uint8_t led     = 0;

Die Funktion:


void flash(uint8_t on, uint8_t off, uint8_t cycles)
{
  led      = 1;
  led_on    = on;
  led_off     = off;
  led_cycles  = cycles;
  
  led_tick_ref = tick + led_on;
}

Alle x ms = 1 tick in einer Timer ISR :


  if (led_cycles > 0)
  {
    if(tick == led_tick_ref)
    {
      led = !led;
      
      if(led)
      {
        PORTB &= ~(1<<PB0);
        led_tick_ref = tick + led_off;
        led_cycles--;cycle
      }
      else
      {
        led_tick_ref = tick + led_on;
        PORTB ^= 1<<PB0;
      }
    }
  }


Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann leg doch für jeden Zustand ein Array an mit sagen wir 32 Bits
(also 4 Bytes).  Mit deinen 10 ms Abtastzeit hättest du dann eine
Periode von 32 ˙ 10 ms = 320 ms, das müsste optisch OK sein.  Ein
eingeschaltetes Bit bedeutet dabei jeweils eine eingeschaltete
LED, mehrere zusammenhängende Bits ergeben eine längere Einschalt-
dauer.  Durch das ganze Array schiebst du ein ,,Abtastbit'' durch,
wenn das hinten rausfällt, musst du vorn wieder anfangen.

Indem du verschiedene Arrays vorhälst und innerhalb der ISR nur
einen Zeiger auf das aktuelle, kannst du verschiedene Blinkmuster
verwalten.

Bei 32 bits kannst du das vom Schreibaufwand her ganz elegant lösen,
indem du statt eines Arrays und statt des Abtastbits jeweils 32-bit-
Zahlen benutzt (uint32_t).  Das ist zwar nicht wirklich effektiv im
Hintergrund dessen, was der Compiler daraus macht, aber dafür sehr
einfach aufzuschreiben, und möglicherweise stört die Ineffektivität
hier gar nicht.  Ungefähr so:
uint32_t blink1 = 0xfff00fff;
uint32_t blink2 = 0xf0f0f0f0;
uint32_t blink3 = 0xfff00000;
uint32_t *blinkp = &blink1;

ISR(TIMER0_COMPA_vect)
{
  static uint32_t mask = 1;

  if (*blinkp & mask)
    LED_ON();
  else
    LED_OFF();

  mask <<= 1;
  if (mask == 0) mask = 1;
}

Eine Änderung des angezeigten Musters erfolgt, indem man blinkp
jeweils auf eine der Adressen von blink1, blink2 oder blink3
umschaltet.  Wenn dich die kurze Inkonsistenz beim Umschalten
nicht stört (es blinkt dann eine Periode lang ,,irgendwie''),
dann würde ich mir nicht einmal die Mühe machen, das Umschalten
mit der kompletten Periode (mask läuft über und wird wieder auf
1 gesetzt) zu synchronisieren.

Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Vorschlag! Auf den ersten Blick würde ich sagen, dass 
beide Wege etwa gleich 'groß' sind, aber ich kenne mich nicht damit aus, 
deswegen werde ich das bei Gelegenheit erstmal ausprobieren.
Zeiger habe ich bisher immer verdrängt, ich werde mich nochmal einlesen 
müssen.

Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also, dein Verfahren ist in meinem Programm mit einem Muster und dem 
Aufruf über

*blinkp = &blink1;
mask = 1;

erstaunlicherweise ca. 20 Bytes größer als mein umständliches Gerechne 
(834+10 vs. 822+4 Bytes).

Ich hatte gedacht, dass es auch schneller sein müsste - allerdings 
werden immer zwei 32 bit Operationen durchgeführt.
Leider kann ich das nicht tiefergehend analysieren, daher werde ich mich 
erstmal anderen Baustellen in meinem Programm zuwenden.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die 32-bit-Operationen im AVR-GCC sind nicht sonderlich toll optimiert,
das heißt: eigentlich sind sie es gar nicht.  Das ist automatisch
generierter C-Code, der da in der Bibliothek sitzt.  Aber solange du
nicht die letzten 20 Bytes an Flash-ROM-Größe brauchst und es auf ein
paar CPU-Takte nicht ankommt, hast du damit zumindest einen (meiner
Meinung nach) relativ gut überschaubaren Quellcode und eine einfache
Möglichkeit, verschiedene Blinkmuster unterzubringen.

Autor: Bastler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jörg,

danke für die Info. Dein Code ist auf jeden Fall kompakter zu schreiben 
und ich freue mich, dass ich jetzt auch diese Möglichkeit kennengelernt 
habe.
Wenn, dann kommt es bei mir auf die Rechenzeit an, da ist aber auch noch 
Luft.
Ich werde mir heute nachmittag mal ein C-Buch vornehmen und nochmal 
Zeiger studieren ;-)

Dankeschön für die Hilfe!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.