Forum: Mikrocontroller und Digitale Elektronik globale Variable in mehreren C-Files


von CManiac (Gast)


Lesenswert?

Hallo,

ich nutze den C30-Compiler von Microchip und programmiere auf einem PIC 
24 FJ
(16 Bit) uController.

Ich habe folgendes Problem:

Ich brauche feste Adressen für den RAM Bereich.

z.B.:
1
int var_test  __attribute__ ((address(0x8000)));

Jetzt soll diese Variable allen C-Files bekannt sein.

z.B.:
main.c
uart.c
eeprom.c

etc....

ich habe gedacht, dass ich die Deklaration in eine Headerfile legen kann 
und dann dieses Headerfile in den C-Files einbinde.

Dies geht leider nicht, dann kommt ein Multiple Deklaration Error...

Wie kann ich das Lösen?

- globale Variable deklarieren mit fester Adressierung und dann von 
allen C-Files darauf zugreifen können?!

Danke vielmals

Gruß
CManiac

von Namtam (Gast)


Lesenswert?

Zwei Möglichkeiten:
Du erzeugst ein weiteres C-File, schreibst dort die Deklarationen 
hinein. Dann fügst du jeweils bei den anderen C-Files, bei welchen du 
die Variablen benötigst, die Deklaration ein weiteres Mal auf, jedoch 
mit dem Zusatz "extern" vorab.

Oder aber du erzeugst ein weiteres C-File mit den Deklarationen und 
schreibst nun in das Header-File die Deklarationen mit dem Zusatz 
"extern". Dann bindest du diesen Header in die weiteren C-Files ein.
1
// Code in C-File:
2
int var_test  __attribute__ ((address(0x8000)));
3
// Code in Header, bzw. weiteren C-Files:
4
extern int var_test __attribute__ ((address(0x8000)));

Das Problem bei deiner Variante ist, dass du mit der Einbindung via 
Header-File mehrere Versionen deiner Variable bekommst, die dann 
unabhängig voneinander bearbeitet werden. Sprich: für jedes C-File, in 
welches du den Header einbindest, wird eine eigene Variable mit diesem 
Namen erstellt (so ungefähr).

Ich denke, so sollte es dann klappen :)

von CManiac (Gast)


Lesenswert?

Hallo,

danke für deine Antwort,

also klingt irgendwie recht schwierig mein Vorhaben umzusetzen.

Also ist es nicht ohne weiteres möglich eine Variable an einer Stelle zu 
deklarieren, und in anderen Quelldateien darauf zuzugreifen, ohne sie 
erneut zu deklarieren?!

Bin gerade etwas verwirrt :-)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> Oder aber du erzeugst ein weiteres C-File mit den Deklarationen und
> schreibst nun in das Header-File die Deklarationen mit dem Zusatz
> "extern". Dann bindest du diesen Header in die weiteren C-Files ein.

Ich nehme an, daß bei der Deklaration das attribute entfallen kann, 
da es nur den Linker betrifft, also nur bei der Definition relevant sein 
sollte.

Das hier kommt in exakt ein C-Source-File, nennen wir es der 
einfachheit halber mal global.c
1
int var_test  __attribute__ ((address(0x8000)));

Und das hier kommt in eine Headerdatei, die passenderweise global.h 
genannt werden sollte:
1
extern int var_test;

Die ist dann in jedem Sourcefile (*.c) mit #include "global.h" 
einzubinden, in dem auf die Variable var_test zugegriffen werden soll.

Das sollte es schon sein, was ist daran jetzt kompliziert?

von Olaf (Gast)


Lesenswert?

Schreib an den Anfang deines Header-Files folgendes:

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

EXT int var_test


In deinem Hauptrogramm wo du dein main() hast, da schreibst du
gleich als allererstes noch folgendes bevor du die Headerdatei
includiert:

#define MAIN

So wird deine Variable nur im Hauptprogramm deklariert und
in allen anderen Source wird sie extern deklariert.

Olaf

von CManiac (Gast)


Lesenswert?

Na jetzt hab ichs kapiert,

hatte auch das extern vergessen, so hat der Compiler weiterhin 
gemeckert....

Danke dir vielmals :-)

von Namtam (Gast)


Lesenswert?

So ginge es natürlich noch einfacher :)
Werde ich gleich auch bei mir mal umsetzen, um Platz zu sparen :P

von holdon (Gast)


Lesenswert?

hallo.

ich habe 2 c-files.

in dem rufe ich eine funktion "test()" auf.diese funktion befindet sich 
in meinem anderen c-file.dort wird ein wert aufgenommen und in eine 
variable gelegt.dieser wert soll dann zur weiterverarbeitung dem 
1.c-file zur verfügung stehen.
wenn ich die variable in dem 1. c-file auslesen will steht da nichts.
hier mein grober code:

1. C-file:

extern int16_t tilt_x;
void test();

void Task1()
{
 int16_t tilt;
 uint8_t variable8bit;
 DDRC = 0xff;

 switch(a) {
    case AKTIV: test();          // aufruf test()-funktion in 2. C-file
                tilt = tilt_x;
                variable8bit = (uint8_t)tilt_x;// LOW-Byte in variable
                PORTC = variable8bit; //ausgabe auf PORTC
                break;
    //usw.
 }
}

2. C-file:


void test()
{ int16_t tilt_x;
 //....
  tilt_x = 0x1102; // dieser Wert soll 1. C-file zur Verfügung stehen
}


kann mir jemand einen tipp geben?danke

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

tilt_x darf nicht innerhalb einer Funktion definiert werden, das aber 
tust Du im 2. C-File in void test().

von Karl H. (kbuchegg)


Lesenswert?

holdon wrote:

> void test()
> { int16_t tilt_x;

Das hier ist eine lokale Variable.
Da magst zwar noch eine globale Variable gleichen Namens haben, die wird 
allerdings nicht benutzt weil sie von der lokalen Variablen verdeckt 
wird.

> kann mir jemand einen tipp geben?danke

Wenn eine Funktion nur einen Wert zurückgeben kann, benutz doch bitte 
den Mechanismus, der für sowas vorgesehen ist: den Return Wert

1
int test()
2
{
3
    ....
4
5
    return 0x1102;
6
}

1
...
2
 switch(a) {
3
    case AKTIV: tilt = test();          // aufruf test()-funktion in 2. C-
4
            ....

von Der L. (vhdl-neuling)


Lesenswert?

weiß jetzt nicht genau was du mit dem "dann steht da nichts meinst", 
aber falls du die Funktion nicht aufrufen kannst, versuch es doch mal 
so:

Schreib eine Header-Datei und deklariere dort alle Funktionen, z.B. eine 
"routines.h".
Die bindest du dann mit #include "routines.h" in beide C-Dateien ein und 
schon fluppts ;)

Gruß,
derLars

von Karl H. (kbuchegg)


Lesenswert?

Der Lars wrote:
> weiß jetzt nicht genau was du mit dem "dann steht da nichts meinst",
> aber falls du die Funktion nicht aufrufen kannst, versuch es doch mal
> so:
>
> Schreib eine Header-Datei und deklariere dort alle Funktionen, z.B. eine
> "routines.h".
> Die bindest du dann mit #include "routines.h" in beide C-Dateien ein und
> schon fluppts ;)
>

Der Vorschlag ist zwar gut, hat aber nichts mir dem Problem an sich zu 
tun.

von holdon (Gast)


Lesenswert?

vielen dank.hat prima geklappt. :)

von Der L. (vhdl-neuling)


Lesenswert?

Karl heinz Buchegger wrote:
> Der Vorschlag ist zwar gut, hat aber nichts mir dem Problem an sich zu
> tun.

Ok, hatte das falsch verstanden. Die letzte Diplomarbeitsnacht war doch 
zu lang :))

von Tommy T. (tommy776)


Lesenswert?

hallo ich bin´s nochmal.

wie schon erwähnt hat es mit der wertrücklieferung gut geklappt.mein 
daraus resultierendes problem hat sich aber leider noch nicht gelöst:

der zurückgelieferte wert "tilt" aus
...
 switch(a) {
    case AKTIV: tilt = test();          // aufruf test()-funktion in 2. 
C-
            ....

soll auf die adresse des folgenden falles nach "AKTIV" gelegt werden.

...switch(a) {
   case AKTIV: tilt = test();
               a = SENDEN;
   case SENDEN: ...
                apsDataReq.asdu = (uint8_t *) 
&appMessageBuffer.daten.tilt;
                ...

Das ganze dient einer Funkübertragung.Als ich es so gemacht habe wie von 
euch empfohlen (also mit return-wert) war die Übertragung erstmal 
gestoppt.
Also wie kann ich es realisieren,dass der Rückgabewert auf der 
Speicherstelle "&appMessageBuffer.daten.tilt" steht???

von Karl H. (kbuchegg)


Lesenswert?

Tommy Tacker wrote:

> Also wie kann ich es realisieren,dass der Rückgabewert auf der
> Speicherstelle "&appMessageBuffer.daten.tilt" steht???


Ins blaue geraten (da Empfehlungen, die auf nur wenigen Codezeilen 
basieren eigentlich immer geraten werden müssen)
1
    appMessageBuffer.daten.tilt = tilt();
??

oder vielleicht auch:
1
...
2
  switch(a) {
3
    case AKTIV: tilt = test();
4
                a = SENDEN;
5
                                   // fallthrough
6
   case SENDEN: ...
7
                apsDataReq.asdu = (uint8_t *)&appMessageBuffer.daten.tilt;
8
                *apsDataReq.asdu = tilt;
9
                ...

oder vielleicht auch:
1
...
2
  switch(a) {
3
    case AKTIV: tilt = test();
4
                a = SENDEN;
5
                                   // fallthrough
6
   case SENDEN: ...
7
                apsDataReq.asdu = (uint8_t *)&appMessageBuffer.daten.tilt;
8
                appMessageBuffer.daten.tilt = tilt;
9
                ...

oder vielleicht auch
1
void foo()
2
{
3
  static int16_t tilt;
4
5
...
6
  switch(a) {
7
    case AKTIV: tilt = test();
8
                a = SENDEN;
9
                                   // fallthrough
10
   case SENDEN: ...
11
                apsDataReq.asdu = (uint8_t *)&appMessageBuffer.daten.tilt;
12
                appMessageBuffer.daten.tilt = tilt;
13
                ...


oder ....

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.