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):
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
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.
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
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 ;-)
@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.
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
enumeStates
8
{
9
STATES
10
};
11
#undef L
12
13
staticu08*GetStatusText(u08id)
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.
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.