www.mikrocontroller.net

Forum: Compiler & IDEs WINAVR - Header Programmvariablen


Autor: Peter Bauer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
habe bei "uC & Elektronik" einen Beitrag laufen wegen I2C projekten
in WINAVR. Da es aber scheinbar keine Projekte dazu gibt will/muß ich
jetzt auch nochmals ganz von vorne auf einen neuen Weg anfangen die I2C
zu schreiben. Habe dabei vor, die Projekte von Atmel 311 usw. auf WINAVR
umzuschreiben. Dabei habe ich aber das Problem, das eine in der Header
definierte Variable in der C-File nicht erkannt wird.

Auszug aus Header:
union TWI_statusReg                       // Status byte holding
flags.
{
    unsigned int all;
    struct
    {
        unsigned char lastTransOK:1;
        unsigned char RxDataInBuf:1;
        unsigned char genAddressCall:1;                        // TRUE
= General call, FALSE = TWI Address;
        unsigned char unusedBits:5;
    };
};

extern union TWI_statusReg TWI_statusReg;



Auszug aus C:

 TWI_statusReg.all = 0;


Doch leider erkennt der Compiler nicht die Variable. Hat jemand ahnung
woran es liegen kann?

Gruß,
Peter

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

Bewertung
0 lesenswert
nicht lesenswert
Du hast die Variable nur deklariert, nicht definiert. In der Headerdatei
steht nur drin, daß es eine Variable gibt, aber nicht, wo. Um das "wo"
zu klären, musst Du in einem Sourcefile noch eine Instanz dieser
Variablen anlegen.

  union TWI_statusReg TWI_statusReg;

in ein Sourcefile geschrieben löst das Problem.

Fast.

Der Name der Variablen darf nicht der Namen des Typs (hier: der union)
entsprechen, also solltest Du das ganze umbenennen:

  union TWI_statusReg mein_status_reg;

und auch die Deklaration in der Headerdatei entsprechend anpassen.

Autor: Peter Bauer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Rufus,

deklaration steht ja auch in der Header nach der deklaration. Mit dem
Problem des gleichen Namens kannst du recht haben, ich habs mal
geändert -> aber kein Erfolg.
Habe auch noch mal versucht die Instanz in der Funktion selbst
anzulegen. aber auch kein Erfolg.

Es kommt immer die Fehlermeldung:

d:\elektronik\winavr_projekte\atmega32\twi_test/twi.c:63: undefined
reference to `TWI_statusReg'

Was tun?
Der ursprüngliche Code von Atmel ist für IAR ausgelegt. Ich weis nicht,
ob das so viel ausmachen kann.

Gruß, Peter

Autor: Die Union Alternative (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du darft dann natürlich auch nicht
 TWI_statusReg.all = 0;
schreiben, sondern musst
 mein_status_reg.all = 0;

Autor: Peter Bauer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, das war klar.
Ich hatte halt nur die Deklartion und den entsprechenden aufruf
geändert.

Jetzt glaube ich das ich es gefunden. der Compiler hat ein problem mit
der "extern union" in der Deklaration. Mit einem reinem "union"
kann er kompilieren.

Tja wenn man auf dem Schlauch steht hilft halt immer wieder eine
Pause.

Danke an alle die sich Gedanken und die Arbeit zu antworten gemacht
haben.

Gruß
Peter

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

Bewertung
0 lesenswert
nicht lesenswert
> der Compiler hat ein problem mit
> der "extern union" in der Deklaration.

Selbstverständlich darf man eine union extern deklarieren.

Autor: Peter Bauer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jörg,
hast du das mit WINAVR schon mal gemacht? Ich meine eine Definition:

extern union Beispielunion meineunion;

zum laufen gebracht.

Ich hab halt das extern weggelassen, dann konnte er kompilieren. Kann
zwar leider unter der woche immer nicht testen, weil ich da keinen
eigenen Rechner habe, wo ich die Software laufen lassen kann. Aber mich
würden trotzdem Erfahrungen dazu interessieren.
Werde mich auf alle Fälle am WE nochmals damit beschäftigen.
Zwangsweise, will ja die ATMEL I2C Routinen übertragen und zum laufen
bringen.

Gruß,
Peter

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

Bewertung
0 lesenswert
nicht lesenswert
In der Headerdatei sollte unbedingt "extern" stehen, im C-Sourcefile
muss das "extern" weggelassen werden.

Wenn Du die Zeile

  union Beispielunion meineunion;

sowohl in Deiner Headerdatei als auch im C-Sourcecode unterbringst,
sollte eigentlich der C-Compiler nörgeln, da das eine doppelt
definierte Variable ist.

Allerdings gibt es eine gcc-Abartigkeit, daß der diesen
Standardprogrammierfehler (der vor allem dann auftritt, wenn eine
Headerdatei mit der Definition von Variablen in mehreren Sourcefiles
eingebunden wird), "verschluckt" und klammheimlich alle
"Doubletten" überlagert.
Das kann man aber irgendwie abschalten, wie, das wird man vermutlich
auch irgendwie herausfinden können.

Die "saubere" und vor allem portierbare Variante ist jedenfalls,
Variablen in Headerdateien nur zu deklarieren (indem das Wort
"extern" verwendet wird) und sie in genau einem Sourcefile des
Projekts zu definieren (indem das Wort "extern" weggelassen wird).

Natürlich muss die Definition ausserhalb jedes Funktionsrumpfes
erfolgen, da die Variable sonst eine automatische Variable ist, auf dem
Stack landet und nur so lange existiert, bis die betreffende Funktion
verlassen wird.
In diesem Fall ist ein Zugriff auf diese Variable aus anderen Modulen
nicht möglich, auch der Linker wird das betreffende Symbol nicht
auflösen können.

Beispiel:

######## bla.h #########

union Beispielunion
{
  int a;
  char b;
}


extern union Beispielunion meineunion;

######## bla.c ############

#include "bla.h"

union Beispielunion meineunion;

void irgendeinefunktion(void)
{
  meineunion.a = 0;
}

######### ende #########

Autor: Peter (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter

Bevor Du das Rad ein zweites mal erfindest: unter folgendem Link
findest Du eine umfangreiche Funktions-Sammlung, bzw. Libraries für
WinAVR, unter anderem auch für den I2C-Bus:

http://hubbard.engr.scu.edu/embedded/avr/avrlib/index.html

Ich bin gerade daran, für ein eigenes Speicher-kritisches Projekt einen
minimale I2C-Bus Treiber Funktionen entworfen, konnte sie aber noch
nicht testen, da die HW noch im Bau ist!

Ich habe ein kurzes Beispielprojekt mit diesen Funktionen im beigefügt,
aber wie gesagt, noch ohne Gewähr dass es richtig tut!

Mit freundlichen Grüßen Peter

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ouups....

Da ist schon ein Bug in TWI_write(): 0xFE statt 0xF0
TWDR = (TWI_adr & 0xFE);  // put slave address+WRITE to TWDR

Ich weiss leider nicht, wie man in diesem Forum Beiträge editiert, bzw.
aktualisiert, geht das überhaupt?

Gruss Peter

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich weiss leider nicht, wie man in diesem Forum Beiträge editiert,
>bzw. aktualisiert, geht das überhaupt?

Nein.

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.