Forum: Compiler & IDEs Array-Konstante als Tabellenersatz


von Jens-Erwin (Gast)


Lesenswert?

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 ...




von Oliver (Gast)


Lesenswert?

???

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

von Jens-Erwin (Gast)


Lesenswert?

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

von Oliver (Gast)


Lesenswert?

Stell deinen Code mal komplett hier rein. Sonst wird das nichts. Die 
Glaskugeln sind gerade alle wieder in der monatlichen Wartung.

Oliver

von Jens-Erwin (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe mal schnell, nur das Problem betreffend, einen Test geschrieben 
---

es wäre wahnsinnig toll, wenn ich da weiter käme ...


Danke

von Oliver (Gast)


Lesenswert?

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


von Süsens, Heiko (Gast)


Lesenswert?

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;
}

von Süsens, Heiko (Gast)


Lesenswert?

Uuuups, Oliver war schneller!

von Jens-Erwin (Gast)


Lesenswert?

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 ....

von Süsens, Heiko (Gast)


Lesenswert?

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.

von pumpkin (Gast)


Lesenswert?

kommt drauf an wie du's benutzt, gib mal code zum beäugen.


pumpkin

von Jens-Erwin (Gast)


Angehängte Dateien:

Lesenswert?

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 ....

von Oliver (Gast)


Lesenswert?

Build succeeded with 0 Warnings...

Welche Version vom AVR-Studio, welcher WinAVR, welches Betriebssystem?

Oliver

von Jens-Erwin (Gast)


Lesenswert?

AVR-Studio 4.12 Service-pack 1

Windows XP

WinAVR-20060125-install am 15.2.2006 abgeladen

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Falk (Gast)


Lesenswert?

@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

von Oliver (Gast)


Lesenswert?

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()

Oliver

von pumpkin (Gast)


Lesenswert?


von Falk (Gast)


Lesenswert?

@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

von Jens-Erwin (Gast)


Lesenswert?

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.

von pumpkin (Gast)


Lesenswert?

>> 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?

von Falk (Gast)


Lesenswert?

@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

von Jens-Erwin (Gast)


Lesenswert?

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) .....

von OliverSo (Gast)


Lesenswert?

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?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.