Hallo,
ich beschäftige mich gerade mit Flankenerkennung und da bin ich über den
Artikel "High-Speed capture mit ATmega Timer" gestolpert.
Der dort veröffentlichte Code funktionierte auf Anhieb in der Arduino
Umgebung, möchte ihn aber gerne auch im AVR Studio ohne die Arduino
Libraries nutzen. Deshalb habe ich begonnen, den Code umzuschreiben.
Jetzt hänge ich bei:
1
2
constuint16_tprojectRamUsage=380+64;
3
constuint16_tbufSize((RAMEND-0x100-projectRamUsage)/sizeof(uint16_t));// use as much RAM as possible
4
constuint8_tRANGE_EXTENSION_BITS=4;// factor for upper measurement range = 2^(RANGE_EXTENSION_BITS+1)
zu den mittleren Zeile spuckt der Kompiler folgenden Fehler aus:
Error 1 expected declaration specifiers or '...' before '(' token
Ich hätte jetzt hinter "bufSize" noch eine Zuweisung (=) erwartet, aber
das ist nicht der Fehler.
Gruß
Radler
>constuint8_tRANGE_EXTENSION_BITS=4;// factor for upper measurement
5
>range=2^(RANGE_EXTENSION_BITS+1)
6
>
>> zu den mittleren Zeile spuckt der Kompiler folgenden Fehler aus:>> Error 1 expected declaration specifiers or '...' before '(' token
Klar, Garbage in - Garbage out.
Da fehlt etwas.
Der Compiler denkt, dass du eine Funktion bufSize deklarieren willst,
die ein const uint16_t zurückgibt, und einen Fehler bei den Parametern
gemacht hast. Daher die Fehlermeldung.
Woran machst du fest, dass es nicht der Fehler ist?
() macht hier nur Sinn zur Gruppierung bzw. die äußere Klammer
eigentlich gar keinen Sinn (bufSize ist ja keine Funktion).
Daher muss da sehr wohl ein = hin, du möchtest ja bufSize einen Wert
zuweisen.
Und er sagt dir ja auch, er hat was vernünftiges erwartet, es fehlt
etwas vor dem '('.
Die [] machen hier nur Sinn, wenn es zB uint16_t buf[bufSize]; wäre.
Mein erster Gedanke war halt auch, dass da ein "=" fehlt, also habe ich
es hinzugefügt aber direkt eine weitere Fehlermeldung bekommen.
Ich werde es morgen noch mal probieren und die Meldung posten. Schonmal
danke!
Student schrieb:> Woran machst du fest, dass es nicht der Fehler ist?> () macht hier nur Sinn zur Gruppierung bzw. die äußere Klammer
...oder wenn man C++ hat(te): Das
int i(3);
durch
int i = 3;
zu ersetzen wird aber nicht funktionieren weil projectRamUsage in C
keine CompileTime-Konstante ist.
Generell ist das, was der Code da anzustellen versucht, HACK — egal ob
in C oder C++
Radler schrieb:> Der dort veröffentlichte Code funktionierte auf Anhieb in der Arduino> Umgebung, möchte ihn aber gerne auch im AVR Studio ohne die Arduino> Libraries nutzen.
Und anscheinend auch ohne C++.
Johann L. schrieb:> ...oder wenn man C++ hat(te): Das>> int i(3);>> durch>> int i = 3;>> zu ersetzen wird aber nicht funktionieren weil projectRamUsage in C> keine CompileTime-Konstante ist.
Genau. In C würde man alles als #define schreiben.
also:
Wird ein "="-Zeichen eingefügt kommt folgende Fehlermeldung:
Error 1 initializer element is not constant
Ersetze ich das const durch #define kommen zwei Warnungen zu der Zeile
und 30 Errors unter anderem bei dem Array, dass duch "bufSize" definiert
wird:
Warning 1 data definition has no type or storage class [enabled by
default]
Warning 3 type defaults to 'int' in declaration of 'bufSize'
[enabled by default]
Error 5 initializer element is not constant
Wie müssten die Zeilen richtigerweise lauten?
Im Prinzip benötige ich auch gar nicht diese variable Definition des
RAMs, da ich ja nicht ständig den µC wechsel.
Der Originale Code funktioniert ja mit 3 oder 4 µC...
Warum schluckt die Arduino IDE die Codezeilen problemlos und das AVR
Studio nicht?
Gruß und Danke!
Radler
Es gibt da ein magisches Wort names static, das macht aus nicht
änderbaren Variablen Compiletime-Konstanten. Nur solche können ein
globales Array dimensionieren.
1
2
staticconstuint16_tprojectRamUsage=380+64;
3
staticconstuint16_tbufSize=((RAMEND-0x100-projectRamUsage)/sizeof(uint16_t));// use as much RAM as possible
4
staticconstuint8_tRANGE_EXTENSION_BITS=4;// factor for upper measurement range = 2^(RANGE_EXTENSION_BITS+1)
Oder man verzichtet auf ein paar Byte RAM und holt sich den Buffer per
malloc().
Radler schrieb:> #define projectRamUsage 380 + 64
Das solltest Du sicherheitshalber klammern.
Sieh Dir mal an, was hier passieren würde:
int a = 10 * projectRamUsage;
Wie groß ist a?
Habe noch eine Frage:
Progamm lässt sich jetzt im AVR Studio kompilieren und funktioniert auch
soweit, aber die eingestellte Baudrate stimmt nicht ganz.
Ich muss im Programm eine Baudrate von 110000 definieren, damit HTerm
das richtige bei 115200Baud ausspuckt.
Läuft mein µC zu schnell?
Ich nutzte eine UART initialisierung die glaub hier aus einem Artikel
stammt, die bis jetzt auch immer sehr gute Dienste geleistet hat.
Gruß
Radler
Radler schrieb:> Läuft mein µC zu schnell?
Nach Deinen Zahlen läuft Dein µC um den Faktor 1,05 zu schnell. Hast Du
denn einen Quarz angeschlossen?
Beschreibe doch mal Deinen Aufbau vollständig (Foto wäre auch ganz gut)
und zeige insbesondere die "UART initialisierung die glaub hier aus
einem Artikel stammt, die bis jetzt auch immer sehr gute Dienste
geleistet hat."
Bitte nicht immer alles aus der Nase ziehen lassen. Macht keinen Spaß.
Radler schrieb:> Warum schluckt die Arduino IDE die Codezeilen problemlos und das AVR> Studio nicht?
Wie schon mehrmals gesagt wurde: Weil du es offenbar bei ersterer als
C++-Code übersetzt, bei letzerer aber als C-Code.
Und in C müssen Initialisierungswerte globaler Variablen immer
Konstanten sein. Da eine const-Variable nunmal keine echte
Compilezeit-Konstante ist, kann man sie nicht zur Initialisierung einer
anderen verwenden, so wie du das oben mit programRamUsage zur
Initialisierung von bufsizes machst. Außerdem gibt's Initialisierungen
im Konstruktor-Style wie oben die von bufsize in C nicht.
Radler schrieb:> Progamm lässt sich jetzt im AVR Studio kompilieren und funktioniert auch> soweit, aber die eingestellte Baudrate stimmt nicht ganz.> Ich muss im Programm eine Baudrate von 110000 definieren, damit HTerm> das richtige bei 115200Baud ausspuckt.>> Läuft mein µC zu schnell?
Scheint so. Mit welchem Quarz betreibst du den µC denn?
Carl D. schrieb:> Es gibt da ein magisches Wort names static, das macht aus nicht> änderbaren Variablen Compiletime-Konstanten.
Mit Verlaub: Das ist Blödsinn.
Ok sorry!
Zum Aufbau: Zwei Arduino Nano. Der eine schaltet einen Pin in einer
gewissen Reihenfolge ein und wieder aus, mehr nicht.
Mit dem anderen Taste ich das Signal ab und gebe mir die Einschalt/
Ausschaltzeiten über UART am HTerm aus.
Setzte ich die Baudrate runten, läuft alles synchron (zb 9600) und bei
hohen Raten muss ich "nachregeln"
Im Anhang die Initialisierung.
Wenn ich so recht überlege, habe ich noch nie höhe Baudraten gebraucht,
wodurch mir der Fehler somit noch nicht aufgefallen ist.
Rolf M. schrieb:> Und ein enum soll typsicherer sein als ein #define
Ja, immer.
Aber es ist wie gesagt ein hack. Die erste Limitation tritt schon auf,
wenn man einen anderen Variablentyp als int braucht, dann kann mal
keinen enum mehr einsetzen.
Für genau diesen Fall ist ein enum aber besser, da der Compiler die
Variable einsetzt und nicht das define. Dies hat z.B. bei Compilefehlern
den Vorteil, dass der Name angezeigt wird und nicht bloss eine Nummer.
Beim Fehler am Ort: 380+64 weiss man unter Umständen nicht, wo das ist.
Ein weiterer Vorteil tritt bei mehrfacher Verwendung dieser Variablen
auf. Der Compiler verbraucht nur einmal diesen Speicher, da er weiss das
es eine konstante Variable ist, mit mehrfacher Verwendnung. Bei einem
define wird aber überall der Wert vom Preprozessor eingesetzt, womit zu
Compilezeit die Relationen zueinander verloren gehen.
Operator S. schrieb:> Ein weiterer Vorteil tritt bei mehrfacher Verwendung dieser Variablen> auf. Der Compiler verbraucht nur einmal diesen Speicher, da er weiss das> es eine konstante Variable ist, mit mehrfacher Verwendnung. Bei einem> define wird aber überall der Wert vom Preprozessor eingesetzt, womit zu> Compilezeit die Relationen zueinander verloren gehen.
Compiler sind da erstaunlich gut. gcc erkennt z.B. auch, wenn das
gleiche String Literal an mehreren Stellen im Code eingesetzt wird und
führt das zusammen. Sogar bei einem "Hello world" und einem "world" wird
nur der erste String gespeichert und für den zweiten einfach mitbenutzt.
Und ob bei einem Integer der Wert überhaupt gespeichert werden muss, ist
dann auch wieder die Frage. Ggf. wird er einfach als immediate in ein
Register geladen und fertig. Das ist einfacher und platzsparender, als
erst die Adresse zu laden und dann von der Stelle aus dem Speicher zu
lesen.