Hallo,
hier meine Struktur des Programmes
Main.c mit #include "Main.h"
Projekt.c mit #include "Main.h"
Main.h mit
#include <avr/io.h> und der anderen notwendigen AVR- Dateien
In der Main.h sind alle Makros, Funktionen, Prozeduren, Variablen usw.
aufgelistet
Ich kann in der *.h Datei ein Array definieren, nur eben keines mit
konstanten Werten ausfüllen ....
uint8_t TestArray[3]; // das geht
uint8_t TestArray[] = {1,2,3} // das geht nicht in der *.h,
logischerweise
Also behelfe ich mir damit, eine Prozedur zu schreiben, die ein
flüchtiges Array in ein globales Array schreibt, welches ich in der
Main.h definiert habe ...
void SchreibeArray(void)
{
uint8_t i, T_Array[] = {1,2,3};
for (i=0;i<3;i++) TestArray[i] = T_Array[i];
}
Gibt es einen anderen Weg (enum o.a.)????? Ich habe große Tabellen zu
verarbeiten und möchte nicht den SRAM überstrapazieren
Danke ...
???
in main.c
uint8_t T_Array[] = {1,2,3};
in main.h
extern uint8_t T_Array[];
und schon kennt die ganze Welt (bzw. alle Dateien, die main.h
inkludieren) dein T_Array.
"uint8_t TestArray[] = {1,2,3} // das geht nicht in der *.h"
Geht schon. Nur nicht mit mehreren Dateien, und natürlich mit Semikolon
hinten dran.
Oliver
Vielen Dank,
vielleicht ist es auch nur noch ein kleiner Fehler, aber bei mir geht es
leider so nicht
Die Main.c erkennt natürlich das Array aber eine andere Datei (z.B.
Init.c) eben nicht, trotz include Main.h am Anfang der Init.c und dem
Hinweis extern in der Main.h
../Init.c:79: undefined reference to `T_Array'
was könnte es sein? Wäre schön, wenn ich da weiter käme ...
Wenn ich in dr main.h -- uint8_t TestArray[] = {1,2,3};
einschribe, dann kommt sofort --- GCC plug-in Error .... file not found
Ich arbeite mit AVR Studio
Also, so gehts leider nicht. Wenn du aus allen Modulen auf T_Array
direkt zugreifen willst, dann muß das global deklariert sein, also
ausserhalb von irgendeiner Funktion.
Also etwa so:
datei main.c
====================
#include <avr/io.h>
uint8_t T_Array[] = {1,2,3};
int main()
{
...
}
datei main.h
====================
extern uint8_t T_Array[];
datei projekt.c
====================
#include <avr/io.h>
#include "main.h"
void ZumProgrammPunkt(void)
{
T_Array[2] = 5;
}
Innerhalb von Funktionen deklarierte Variablen sind nur dort sichtbar.
Dann musst du das Array als Parameter an andere Funktionen übergeben,
etwa so:
void ZumProgrammPunkt(uint8_t T_Array[]);
int main()
{
uint8_t T_Array[] = {1,2,3};
ZumProgrammPunkt(T_Array);
}
Oliver
Hallo,
setze einfach die Definition von "uint8_t TestArray2[] = {5,6,7,8};"
vor dem "int main(void)". Als globale Variable definiert, funktionierts.
Mit "extern" definierst Du nicht die Variable, sondern machst die Typ
Definition für andere bekannt. In "main.c" vor "int main(void)"
definierst Du erst die Variable und besetzt Sie mit Werten.
Also:
in Main.c
#include "Main.h"
uint8_t TestArray2[] = {5,6,7,8};
int main(void)
{
bla fasel
}
in Main.h
extern uint8_t TestArray2[];
in Projekt.c
#include "Main.h"
void ZumProgrammPunkt(void)
{
TestArray2[3] = 5;
}
Ich halts nicht aus -- das ist es --Heikos Variante funktioniert so wie
ich es wollte, Olivers' auch, etwas verworrener vielleicht bei mehreren
Dateien ---- danke Euch beiden !!!
Ich habe vorher in Assembler programmiert ...
Nur mal so aus Neugier ... wird jetzt sozusagen aus dem Programmfile
(*.hex) das Array gelesen und quasi an eine feste Stelle im SRAM
gespeichert?
In Assembler kann ich ja direkt aus dem Programmspeicher lesen (lpm) -
in C ist das schwierig (Programm stürzt ab) wenn ich
#include <avr/pgmspace.h> nehme, aber wie ....
Also, ein "#include" sollte kein Programm abstürzen lassen.
Der Compiler arbeitet Programmteile mit ein, die mehrere "init(x)" (ich
glaube x = 0-9) beinhalten, in denen sogenannte vorarbeiten durchführt
werden (definierte Variablen mit 0 vorbelegen und noch viele andere
Dinge), dabei wird die Variable im Speicher (RAM) initialisiert und der
Ram-Bereich ist reserviert, solange die Variable gültig ist, in diesem
Fall während der gesamte Laufzeit (Globale extern).
Bei den Vorarbeiten wird ebenfalls die Vorbelegung der Globalen Variable
durchgeführt, wobei die Werte natürlich im Flash stehen, solange Sie
ungleich 0 sind, glaube ich ?!
Variablenwerte aus dem Flash zu laden, macht irgendwie wenig Sinn, kann
aber mit dem von Dir angesprochenen realisiert werden. In solch einem
Fall sind diese Variablen im Flash aber Konstante und der Compiler
übernimmt diese Werte automatisch.
Übrigens, in der Doku vom WinAVR ist eine gute Beschreibung, wie das
Ganze funktioniert.
Also, sobald ich in meine Main.h
#include <avr/pgmspace.h> einschreibe, stürzt bei Build (F7) das
AVR-Studio Programm komplett ab, so dass ich sogar die Main.aps löschen
muss, um wieder an die Dateien zu kommen ...
Problem ist - ich möchte auf ca. 600 Byte - Konstanten zurückgreifen und
da ist dann der SRAM schon mehr als halb voll.
Als ich in Assembler programmiert habe, konnte ich die Konstanten im
üppigen Programmspeicher lassen und habe sie direkt angesprochen, wenn
ich sie brauchte. In C++ wird nun alles erst in den RAM geladen ....
Alles hornalt. Diese alten AVR-Studio-Versionen hatten einen Bug, der
wohl den Parser festgeklemmt hat, der die Ausgaben von GCC analysiert.
Wenn schon AVR Studio 4.12, dann build 498 (SP4 oder so). Oder gleich
auf die aktuellen Versionen (AVR Studio 4.13 und WinAVR 2007xxxx)
hochziehen.
@Jens-Erwin
>Problem ist - ich möchte auf ca. 600 Byte - Konstanten zurückgreifen und>da ist dann der SRAM schon mehr als halb voll.>Als ich in Assembler programmiert habe, konnte ich die Konstanten im>üppigen Programmspeicher lassen und habe sie direkt angesprochen, wenn>ich sie brauchte. In C++ wird nun alles erst in den RAM geladen ....
AFAIK kann man das in C(++) auf dem AVR nur "zu Fuss" machen, über die
Funktionen pgm_read.. etc. Einfach ein (normales) konstantes Array
definieren geht nicht, die landen trotzdem im RAM. Vielleicht kann man
es über ein Macro hintricksen. Aber ich bin weiss Gott kein C-Profi.
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29
MfG
Falk
@Oliver
>Nix da.>Selbstverständlich landet>uint8_t myVar[3] PROGMEM = {1,2,3};>im Flash. Der Zugriff auf die einzelnen Werte erfogt dann über>pgm_read()
Sagte ich das nicht?
MfG
Falk
Die Frage ist doch die, ob alle 600 Byte im Flash landen und dort
warten, oder nur die, die bearbeitet werden ...
das ist ja auch in Assembler so.
Ich hole also das Byte aus dem Programmflash und speichere es in ein
Register oder in den SRAM, sende es z.B. und hole das nächste Byte aus
dem Programmspeicher usw.
>> Die Frage ist doch die, ob alle 600 Byte im Flash landen und dort>> warten, oder nur die, die bearbeitet werden ...
???
die die du per attribut PROGMEM reinschiebst. wo liegt das problem?
@Jens-Erwin
>Die Frage ist doch die, ob alle 600 Byte im Flash landen und dort>warten, oder nur die, die bearbeitet werden ...
Es landen alle im FLASH und bleiben auch dort. Du kannst einzelne Werte
dann mit pgm_read... lesen.
>das ist ja auch in Assembler so.>Ich hole also das Byte aus dem Programmflash und speichere es in ein>Register oder in den SRAM, sende es z.B. und hole das nächste Byte aus>dem Programmspeicher usw.
Genau das machst du auch in C, nur dass es eben leider (mit GCC) nicht
direkt geht
uint8_t const_array[5] PROGMEM = {1, 2, 3, 4, 5};
tmp = const_arry[3]; // geht nicht mit GCC
sondern so gemacht werden muss
tmp = read_pgm_byte(&const_array[3]); // GCC Methode
MfG
Falk
So jetzt ist alles klar ... danke Euch allen
habe jetzt alle neue Software geladen .. und es geht !!!!
also, ich habe beim Simulieren mal den Disassembler und den
SRAM-Speicher beobachtet ..
PROGMEM funktioniert wunderbar, die Daten werden NICHT im SRAM
gespeichert, sondern nur dann, wenn man sie abruft ... also genau so wie
ich es brauche -- entspricht absolut dem lpm Befehl in Assembler
Damit kann man also wirklich größere Tabellen ablegen -- damit ist C++
für mich endgültig zum Durchbruch gegenüber Assembler gekommen
(zeitkritische Sachen ausgenommen) .....
Prima. Mit dem "++" von "C++" hast du es zwar noch nicht so, aber das
kann ja noch werden. Für Assembler-Freaks ist aber normales C sowieso
viel besser geeignet.
Oliver
P.S. Schau dir mal das #define zu read_pgm_byte an. Welcher Befehl mag
da wohl verwendet werden?