Forum: Compiler & IDEs WINAVR - Header Programmvariablen


von Peter Bauer (Gast)


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

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Peter Bauer (Gast)


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

von Die Union Alternative (Gast)


Lesenswert?

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

von Peter Bauer (Gast)


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

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


Lesenswert?

> der Compiler hat ein problem mit
> der "extern union" in der Deklaration.

Selbstverständlich darf man eine union extern deklarieren.

von Peter Bauer (Gast)


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

von Rufus Τ. F. (rufus) Benutzerseite


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

von Peter (Gast)


Angehängte Dateien:

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

von Peter (Gast)


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

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

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

Nein.

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.