www.mikrocontroller.net

Forum: Compiler & IDEs Tabelle mir Präprozessor erzeugen?


Autor: risu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

um mit dem 16-Bit Timer (ATmega48) bestimmte Frequenzen erzeugen zu 
können, möchte ich eine Tabelle mit Werten für OCR1A im EEPROM ablegen, 
die folgendermaßen aussehen soll (hier auf 4 Elemente verkürzt; 
tatsächlich soll die Tabelle etwa 100 16-Bit-Werte umfassen):
uint16_t const OCR[] __attribute__ ((section(".eeprom"))) = {1250, 1176, 1111, 1053};

Die Elemente des Arrays gehorchen der Formel F_CPU/(2*f), wobei f mit 
400 beginnt und in Schritten von 25 ansteigt.

Kann ich diese Tabelle vom Präprozessor oder Compiler erzeugen lassen? 
Die Tabelle soll zur "compile time" entstehen und nicht auf dem Atmega 
berechnet werden. Bisher erzeuge ich die Tabelle in Excel, exportiere 
sie als Text, bearbeite sie, und kopiere sie dann in meine Quelldatei.

Gruß
 risu

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Implizite Schleife ist im Präprozessor nicht drin, aber rechnen kann er 
schon (bzw. dann der Compiler). Also ={F(1),F(2),F(3),...} mit 
entsprechendem Makro F(x).

Wird das zu viel, kann man den Quellcode der Tabelle von einem Programm 
auf der Entwicklungsmaschine erzeugen lassen.

Wenn dir das auch nicht passt, kannst du zuätzlich den M4-Präprozessor 
vorschalten. Der kann Schleifen, auch wenn's etwas komisch aussieht.

Autor: risu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, hatte gehofft, dass es einen Trick gibt für eine Schleife!

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
risu wrote:
> um mit dem 16-Bit Timer (ATmega48) bestimmte Frequenzen erzeugen zu
> können, möchte ich eine Tabelle mit Werten für OCR1A im EEPROM ablegen,

Konstanten legt man besser im Flash ab, da ist mehr Platz und das Lesen 
geht schneller.

Nur wenn die Werte zur Compilezeit noch unbekannt sind oder später 
geändert werden müssen, nimmt man den EEPROM.



Peter

Autor: 900ss D. (900ss)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So geht es auch. Du sparst dir das ausrechnen der einzelnen Werte 
sondern mußt nur die Tabelle mit den Frequenzen erstellen. Die 
Frequenzen lassen sich ja im Kopf errechnen ;-)

#define FREQUENZEN L(400), \
                   L(425), \
                   L(450), \
                   L(475)



#define L(f)   (F_CPU/(2*f))
uint16_t const OCR[] __attribute__ ((section(".eeprom"))) =
  {
      FREQUENZEN
  };
#undef L

Edit: nochmal angepaßt, damit es auch im EEPROM liegt. Im Flash geht es 
aber auch.

Autor: risu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, 900ss D. ! Nachdem sich eine "Präprozessor-Schleife" als nicht 
machbar herausgestellt hat, ist das sicher die beste Lösung.

Gruß
 risu

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@900ss: Weshalb der Umweg über Makro?

@risu: Schleife geht nicht, dies aber schon:
 #define F(n) ...
 #define FF(n) F(n+0),F(n+1),...,F(n+9)
und dann
 ... { FF(0),FF(10),... };
was auf 10xFF statt 100xF rausläuft.

Autor: 900ss D. (900ss)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. wrote:
> @900ss: Weshalb der Umweg über Makro?

Geht natürlich auch ohne das Makro in diesem Fall.
Aber diese Lösung nutze ich als "Standard" oft, da auch mehrspaltige 
Tabellen so zu nutzen sind. Und ich habe es deshalb hier so übernommen.
Es lassen sich noch viele andere schöne Sachen damit machen.
Im Beispiel brauchst Du nur die "Tabelle" STATES ändern und der erzeugte 
Enumerator und auch die Funktion GetStatusText() passen automatisch.
#define STATES     L(STATE1, 1), \
                   L(STATE2, 4), \
                   L(STATE3, 7), \
                   L(STATE4, 8)

#define L(a,b)   ( a = b )
enum eStates
{
  STATES
};
#undef L

static u08 *GetStatusText( u08 id )
{
    switch(id)
    {
    #define L(id,value) case id: return #id;
       STATES
    #undef L
       default:return "not defined";
    }
}


Solche Konstrukte sind allerdings sehr grenzwertig, da sie schon 
schlecht "lesbar" sind.
Außerdem muß man aufpassen, dass die "Tabelle" STATES nicht zu ang wird, 
da ja der Präprozessor dieses als eine lange Zeile sieht. D.h. die max. 
mögliche Zeilenlänge ist die begrenzende Größe und dass ist von Compiler 
zu Compiler unterschiedlich, wenn ich nicht irre.

Die Idee stammt übrigens nicht von mir. Hat mir mal ein Kollege so 
gezeigt.

Autor: risu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für alle Kommentare vielen Dank!

Autor: StinkyWinky (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin der Meinung, es sollte so heissen:
#define STATES     L(STATE1, 1) \
                   L(STATE2, 4) \
                   L(STATE3, 7) \
                   L(STATE4, 8)

#define L(a,b)   a = b,
enum eStates
{
  STATES
};
#undef L

static u08 *GetStatusText( u08 id )
{
  switch(id)
  {
    #define L(id,value) case id: return #id;
      STATES
    #undef L
      default:return "not defined";
  }
}

Den Originalcode von 900ss D kann ich sonst nicht compilieren.

Autor: 900ss D. (900ss)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmmm... ja, habe es so aus dem Kopf hingeschrieben und nicht getestet. 
Hatte gerade keinen Source "in der Hand", wo ich es abschreiben konnte.
Sorry an alle, die ich verwirrt habe.

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.