Tabelle mir Präprozessor erzeugen?

Gast #1032522
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):
1
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
#1032524
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.
#1032544
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
#1034725
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 ;-)

1
#define FREQUENZEN L(400), \
2
                   L(425), \
3
                   L(450), \
4
                   L(475)
5

6

7

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

Edit: nochmal angepaßt, damit es auch im EEPROM liegt. Im Flash geht es 
aber auch.
#1034885
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.
1
#define STATES     L(STATE1, 1), \
2
                   L(STATE2, 4), \
3
                   L(STATE3, 7), \
4
                   L(STATE4, 8)
5

6
#define L(a,b)   ( a = b )
7
enum eStates
8
{
9
  STATES
10
};
11
#undef L
12

13
static u08 *GetStatusText( u08 id )
14
{
15
    switch(id)
16
    {
17
    #define L(id,value) case id: return #id;
18
       STATES
19
    #undef L
20
       default:return "not defined";
21
    }
22
}

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.
Gast #1035923
Lesenswert?

Ich bin der Meinung, es sollte so heissen:
1
#define STATES     L(STATE1, 1) \
2
                   L(STATE2, 4) \
3
                   L(STATE3, 7) \
4
                   L(STATE4, 8)
5

6
#define L(a,b)   a = b,
7
enum eStates
8
{
9
  STATES
10
};
11
#undef L
12

13
static u08 *GetStatusText( u08 id )
14
{
15
  switch(id)
16
  {
17
    #define L(id,value) case id: return #id;
18
      STATES
19
    #undef L
20
      default:return "not defined";
21
  }
22
}

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren