www.mikrocontroller.net

Forum: Compiler & IDEs Array-Konstante als Tabellenersatz


Autor: Jens-Erwin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ...




Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jens-Erwin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Oliver (Gast)
Datum:

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

Oliver

Autor: Jens-Erwin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mal schnell, nur das Problem betreffend, einen Test geschrieben 
---

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


Danke

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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


Autor: Süsens, Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
}

Autor: Süsens, Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Uuuups, Oliver war schneller!

Autor: Jens-Erwin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ....

Autor: Süsens, Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: pumpkin (Gast)
Datum:

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


pumpkin

Autor: Jens-Erwin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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 ....

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Build succeeded with 0 Warnings...

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

Oliver

Autor: Jens-Erwin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AVR-Studio 4.12 Service-pack 1

Windows XP

WinAVR-20060125-install am 15.2.2006 abgeladen

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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-Tu...

MfG
Falk

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: pumpkin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jens-Erwin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: pumpkin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jens-Erwin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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) .....

Autor: OliverSo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.