mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik CodeVision: Erfahrungen mit structs


Autor: Thomas Thiry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen!

Ich habe mal eine Frage bzgl. des CodeVision Compilers:
Ich habe in meinen bisherigen Programmen die Verwendung von structs
immer vermieden, da ich in einer Vorlesung mal gesagt bekommen habe,
dass structs im Bereich Mikrocontrollerprogrammierung mit äußerster
Vorsicht zu genießen sind.

Ich habe mein aktuelles Projekt aber doch auf die Verwendung von
Strukturen umgestellt, da ich finde, dass das die Wartung des
SourceCodes wesentlich vereinfacht.

Ich habe allerdings den Eindruck, dass der CodeVision Compiler
Strukturen nicht wirklich zu 100% unterstützt. Ich will das an einem
Beispiel verdeutlichen, wie ich mit Strukturen umgehe:

void main(void)
{
    struct beispiel test1;
    struct beispiel* pTest1;
}

In einer Headerdatei habe ich den Datentyp beispiel folgendermaßen
definiert:

struct beispiel {
     unsigned char variable1;
     unsigned char variable2;
};

Die erste Funktion im Hauptprogramm ist dann eine
Initialisierungsfunktion, in der ich den Strukturvariablen Defaultwerte
zuweise. An diese und an alle weiteren Funktionen übergebe ich jeweils
immer nur den Zeiger pTest1, z.B.:

void init(pTest1)
{
    pTest1->variable1 = 34;
    pTest1->variable2 = 56;
}

Wenn ich mein Projekt mit AVRStudio debugge, steht in den
Strukturvariablen teilweise nur Müll drin, obwohl es das nicht sollte.


Habt ihr vielleicht ähnliche Erfahrungen mit CodeVision gemacht; oder
mache ich mit der Handhabung von Strukturen noch einen Fehler?

Vielen Dank schonmal für eure Hilfe!

Gruß
Thomas

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Initalisierst Du denn den Pointer pTest1 auch irgendwo?

Wenn Du das nicht tust, dann geht jeder Zugriff darauf in die Hose.

Autor: Thomas Thiry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jawohl und zwar direkt nach der Definition des Zeigers:

pTest1 = &test1;


Sobald ich den Zeiger an eine Funktion übergebe und in dieser Funktion
mit dieser Struktur arbeite, oder auf deren Daten zugreife stimmt
nichts mehr.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zeig mal Dein vollstaendiges (moeglichst kleines)
Testprogramm.

Die Wahrscheinlichkeit dass der Fehler bei Dir liegt
und nicht beim Compiler ist groesser als 99%.

Autor: Thomas Thiry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ganze Programm kann und darf ich nicht posten (über 20 000 Zeilen
Code); aber ich kann es exemplarisch mal aufzeigen:

struct timeDate{
    BYTE measureStartDate[6];
    BYTE measureStopDate[6];
    BYTE actualDate[6];
};


void liesUhrzeit(struct timeDate* pZeitstempel)
{
     // Lies Informationen von I2C-RTC
    pZeitstempel->actualDate[0] = read_info();
    pZeitstempel->actualDate[1] = read_info();
    pZeitstempel->actualDate[2] = read_info();
    pZeitstempel->actualDate[3] = read_info();
    pZeitstempel->actualDate[4] = read_info();
    pZeitstempel->actualDate[5] = read_info();
}

//Globale Variablen:
struct timeDate zeitstempel;


// Hauptprogramm:
void main()
{
   liesUhrzeit(&zeitstempel);
}


Ich hoffe mal, dass dieser prinzipielle Ausschnitt die Problemstellung
verdeutlicht.

Was ich mir noch überlegt habe: Ist es vielleicht besser (oder sogar
notwendig) die Struktur in der Funktion liesUhrzeit wieder ans
Hauptprogramm zurückzugeben, also in etwa so:

struct timeDate* liesUhrzeit(struct timeDate* pZeitstempel)
{
     // Lies Informationen von I2C-RTC
    pZeitstempel->actualDate[0] = read_info();
    pZeitstempel->actualDate[1] = read_info();
    pZeitstempel->actualDate[2] = read_info();
    pZeitstempel->actualDate[3] = read_info();
    pZeitstempel->actualDate[4] = read_info();
    pZeitstempel->actualDate[5] = read_info();

    return pZeitstempel;
}

Sorry für das lange Posting ;-)

Autor: hans dieter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also das mit dem zurückgeben brauchst du eigentlich nicht, das wird nur
bei einigen funktioneen so gemacht, weil man die dann schachteln kann:

gibUhrzeitAus(liesUhrzeit(&zeit));

ich werde mal meine CV version suchen, mal sehen woran es leigt.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Codefragment sieht in Ordnung aus.

Die Rückgabe des Pointer in liesUhrzeit ist unnötig, da eben nur der
Pointer an die Funktion übergeben wird und keine Kopie der Struktur;
das ist auch gut so ("call-by-reference").
Würde die Struktur als Kopie ("call-by-value") an die Funktion
übergeben, dann würde sie dafür auf den Stack gelegt, der entsprechend
groß dimensioniert sein müsste.
Und sie müsste nach Aufruf der Funktion auch wieder zurückkopiert
werden, was auch nur Rechenzeit verbraucht.

Nein, dein Beispiel hier ist soweit korrekt.

Da wird Dir irgendetwas anderes Deine Strukturen zerstören.

Autor: hans dieter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kann es sein, dass du an den stack-grenzen gelangst? beobachte mal den
SP, wenn du an die stelle kommst, an der es nicht mehr geht.

Autor: Olaf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein das der Compiler Zeiger vom Typ "far" und "near"
unterstuetzt?

Olaf

Autor: hans dieter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nein macht der nicht, ich tippe stark darauf, dass da was mit der
read_info nicht stimmt.

also folgendes geht (mega16 mit standard-einstellungen):
<pre>
struct st
{
  int a;
  short b;
};

struct st test;

void foo(struct st* p)
{
  p->a = -1;
  p->b = 10;
}

void main(void)
{
  foo(&test);
}
</pre>

Autor: Thomas Thiry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@hans dieter
SP verhält sich "normal". Überlaufen tut er jedenfalls nicht, dann
müsste er ja in die Nähe des Wertes 0xFFFF kommen und an den Stellen,
an denen es nicht mehr geht, hat er den Wert 0x0EC3. CodeVision meldet
das meines Wissens nach auch, wenn der Data Stack zu klein ist.

@Olaf
Diese beiden Begriffe habe ich im Kontext von CodeVision noch nie
gehört. Ich weiß, dass es zu Problemen kommen kann, wenn ich Variablen
im Flash ablege und mithilfe eines Zeigers, der im SRAM liegt darauf
zugreifen will; aber solche Definitionen treten bei mir nirgendwo auf.

Es ist z.B. auch merkwürdig, dass AVRStudio den Strukturdatentyp nicht
richtig erkennt. In meinem obigen Beispiel habe ich ja einen Datentyp
struct timeDate. Will ich mir die Struktur zeitstempel in AVRStudio
anschauen ist sie auf einmal vom Typ struct file und natürlich stimmen
die darin enthaltenen Elemente auch nicht. Das muss aber ein Fehler bei
AVRStudio sein (würde ich zumindest mal vermuten).

Mal generell eine Frage: Könnt ihr mir vielleicht ein paar Tipps geben,
die es bei der Verwendung von Strukturen zu beachten gilt?

Autor: hubert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, das die structur in verschiedenen modulen
deklariert und implementiert ist, dann kann es ggf am
aligment liegen wenn das in verschiedenen modulen
unterschiedlich definiert ist?

aligment -> ausrichtung an Grenzen

kann z.B. dann beim siezof auf unterschiedliche Ergebnisse
kommen.

Nur so eine Spekulation von mir...

Autor: Thomas Thiry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Datentyp der Struktur ist in einem Headerfile deklariert. Diese
Headerdatei wird in meinen verschiedenen C-Files eingefügt.
In dieser Datei habe ich über die Präprozessoranweisung:

#ifndef DEFINITION_H
#define DEFINITION_H

struct timeDate{
...
}

#endif

Autor: olaf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit near und far kenne ich vom R8C/M16C, deshalb die Frage.

Hast du nur deinen Struct im header-File oder auch die
Variablendeklaration selber? Wenn du die naemlich in jedem C-Source neu
deklarierst dann hast du verschiedene Variablen wenn du sie nicht als in
allen Files bis auf eins als extern deklarierst.

Ich mache das immer so:

--------------------------
#ifdef MAIN
#define EXT
#else
#define EXT extern
#endif


typedef struct CIDSP {
    unsigned char  MID;     /*  8 Bit */
    unsigned short OID;     /* 16 Bit */
    unsigned char  PNM[6];          /* 48 Bit */
    unsigned char PRV;      /*  8 Bit */
    unsigned long PSN;      /* 32 Bit */
    unsigned char MDT;      /*  8 Bit */
    unsigned char CRC;      /*  7 Bit */
} CIDS;
EXT CIDS CID;
-----------------

Und nur im Hauptprogramm gibt es dann ein:

#define MAIN

Olaf

Autor: Thomas Thiry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen!

Ich habe die Lösung des Problems gefunden.
Rufus hatte mit seiner ersten Vermutung gar nicht so unrecht.

Die Beispielstruktur, die ich oben aufgezeigt habe ist in Wahrheit doch
etwas komplexer aufgebaut. Es handelt sich dabei um eine Status-struct,
in der alle möglichen Information zu Messwerten gespeichert werden,
u.a. auch Datum/Uhrzeit, Seriennummer usw.

Ich habe also zwei Strukturen definiert:
struct timeDate{
...
};

struct serialNumber{
...
};

Und nun die "Oberstruktur":
struct status{
unsigned char number;
struct serialNumber* serial;
struct timeDate* datestamp;
}

Und genau hier liegt der Fehler. Ich habe nämlich nur eine Variable vom
Typ status instanziiert, nicht jedoch die beiden Strukturen number und
datestamp. Dies waren also Zeiger die ins Leere zeigten.
Statt der Zeigerdeklarierung habe ich jetzt einfach geschrieben:

struct status{
unsigned char number;
struct serialNumber serial;
struct timeDate datestamp;
}

Vielen Dank nochmal für eure Hilfestellungen !

Gruß
Thomas

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.