Forum: Mikrocontroller und Digitale Elektronik globale Variable in externer header-datei


von Balesi (Gast)


Lesenswert?

Ich programmiere einen ATTiny in C mit WinAVR.
Es ist ein größeres Programm und ich habe einige Funktionen in separaten 
c-files ausgelagert. Ich benutze aber teilweise VAriablen, die global 
angelegt werden sollen und von allen Files zugänglich sein sollen, u.a. 
auch für EEPROM

Ich habe mir schon diverse Beträge angesehen, u.a. diesen hier: 
Beitrag "Globale Variablen, mehrere Dateien", der sehr aufschlussreich 
war.

Leider habe ich aber dennoch Probleme und bekomme Fehlermeldungen. Hier 
ein Auszug aus meinen Dateien:
global.h
1
/******************************************************************************/
2
/****************************** globale Variablen *****************************/
3
/******************************************************************************/
4
#ifndef EXTERN
5
#define EXTERN extern
6
#endif
7
8
EXTERN uint8_t  ee_Fehlermode EEMEM; //Variablen EEPROM
9
EXTERN uint16_t ee_Sense_1 EEMEM;
10
EXTERN uint16_t ee_Sense_2 EEMEM;
11
EXTERN uint16_t ee_Sense_3 EEMEM;
12
13
EXTERN unsigned char messageBuf[2];
14
EXTERN volatile uint8_t v_sek;// v_sek = viertel sekunde -->wird in ISR hochgezählt

main.c
1
#include "global.h"
2
uint8_t stamp=0, sekunde = 0, Blinkcode =0xFF;

lern.c
1
#include "global.h"
2
3
void lernen(void)
4
{
5
  eeprom_write_word(&ee_Sense_1, 0xa4CD); 
6
  eeprom_write_word(&ee_Sense_2, 0xa99A); 
7
  eeprom_write_word(&ee_Sense_3, 0xaE66); 
8
}

eine der Fehlermeldungen:
1
../global.h:14: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'v_sek'

von Klaus W. (mfgkw)


Lesenswert?

#include <stdint.h> vergessen?

von Balesi (Gast)


Lesenswert?

Nein, habe ich sowohl in der main.c, als auch in der lern.c eingebaut

von def (Gast)


Lesenswert?

Hast du neben der Deklaration auch an eine globale Definition in einem 
der *.c files gedacht (z.B. in main.c)?!?

von def (Gast)


Lesenswert?

sry für Doppelpost!!

Aber mit der global.h, sagst du dem Compiler ja nur, dass es irgendwo in 
einer anderen Datei die beschriebenen Variablen gibt. Anlegen musst die 
aber trotzdem noch.

von Karl H. (kbuchegg)


Lesenswert?

Balesi schrieb:
> Nein, habe ich sowohl in der main.c, als auch in der lern.c eingebaut

Ich hätte es auch in die global.h mit aufgenommen, denn dort werden 
diese Datentypen ja auch verwendet
1
#ifndef GLOBAL_H_INCLUDED
2
#define GLOBAL_H_INCLUDED
3
4
#include <stdint.h>
5
6
/******************************************************************************/
7
/****************************** globale Variablen *****************************/
8
/******************************************************************************/
9
#ifndef EXTERN
10
#define EXTERN extern
11
#endif
12
13
EXTERN uint8_t  ee_Fehlermode EEMEM; //Variablen EEPROM
14
EXTERN uint16_t ee_Sense_1 EEMEM;
15
EXTERN uint16_t ee_Sense_2 EEMEM;
16
EXTERN uint16_t ee_Sense_3 EEMEM;
17
18
EXTERN unsigned char messageBuf[2];
19
EXTERN volatile uint8_t v_sek;// v_sek = viertel sekunde -->wird in ISR hochgezählt
20
 
21
#endif


Abgesehen davon:
Bitte poste kompletten, compilierbaren Code. Dann können wird den durch 
unsere Compiler jagen und selbst probieren.

von Balesi (Gast)


Lesenswert?

Danke für Eure Tipps, habe meinen Code folgendermaßen abgeändert:
global.h
1
/******************************************************************************/
2
/****************************** globale Variablen *****************************/
3
/******************************************************************************/
4
#ifndef EXTERN
5
#define EXTERN extern
6
#endif
7
#include <stdint.h>
8
#include <avr\eeprom.h>
9
10
EXTERN uint8_t  ee_Fehlermode EEMEM;//Variablen EEPROM
11
EXTERN uint16_t ee_Sense_1 EEMEM;
12
EXTERN uint16_t ee_Sense_2 EEMEM;
13
EXTERN uint16_t ee_Sense_3 EEMEM;
14
15
EXTERN unsigned char messageBuf[2];
16
EXTERN volatile uint8_t v_sek;// v_sek = viertel sekunde -->wird in ISR hochgezählt
main.c:
1
#include "global.h"
2
uint8_t  ee_Fehlermode EEMEM;
3
unsigned char messageBuf[2];
4
volatile uint8_t v_sek;// v_sek = viertel sekunde -->wird in ISR hochgezählt
lern.c
1
#include <stdint.h>
2
#include <avr\eeprom.h>
3
#include "Anlernvorgang.h"
4
#include "global.h"
5
6
void lernen(void)
7
{
8
9
uint16_t ee_Sense_1 EEMEM;
10
uint16_t ee_Sense_2 EEMEM;
11
uint16_t ee_Sense_3 EEMEM;
12
13
  eeprom_write_word(&ee_Sense_1, 0xa4CD); 
14
  eeprom_write_word(&ee_Sense_2, 0xa99A); 
15
  eeprom_write_word(&ee_Sense_3, 0xaE66); 
16
}

Jetzt habe ich folgende Fehlermeldung:
1
../lern.c: error: section attribute cannot be specified for local variables
Ich weiß nicht wie ich bei einer Auslagerung mit den Variablen fürs 
EEPROM umgehen muss

von Karl H. (kbuchegg)


Lesenswert?

Ich würde mir an deiner Stelle ein
global.c machen

global.c
********
1
#define EXTERN
2
#include "global.h"

dann in main.c
1
#include "global.h"
2
3
int main()
4
{
5
  ...
6
}

und in lern.c
1
#include <stdint.h>
2
#include <avr\eeprom.h>
3
#include "Anlernvorgang.h"
4
#include "global.h"
5
6
void lernen(void)
7
{
8
  eeprom_write_word(&ee_Sense_1, 0xa4CD); 
9
  eeprom_write_word(&ee_Sense_2, 0xa99A); 
10
  eeprom_write_word(&ee_Sense_3, 0xaE66); 
11
}


> ../lern.c: error: section attribute cannot be specified for local
> variables

Ist ja wohl ziemlich eindeutig.
Die section attributes von denen dein Compiler spricht, ist das EEMEM. 
Und die einzigen lokalen Variablen, auf die das zutrifft, sind ....

von Balesi (Gast)


Lesenswert?

Danke Karl heinz für deinen Tipp

Karl heinz Buchegger schrieb:
> Ist ja wohl ziemlich eindeutig.
> Die section attributes von denen dein Compiler spricht, ist das EEMEM.
> Und die einzigen lokalen Variablen, auf die das zutrifft, sind ....

Das habe ich auch vermutet, aber wie gesagt, wich wusste nicht wie ich 
damit umzugehen habe. Muss ich das Attribut nur einmalig benutzen, wenn 
ja an welcher Stelle, usw.

Ich habe zunächst die Funktion lernen, wie von dir vorgschlagen 
abgeändert, ohne erneute deklaration (oder definition). Da kam dann 
wieder eine Fehlermeldung. Nachdem ich dann eine global.c angelegt habe 
war diese verschwunden und es hat funktioniert.

Kannst du mir hierzu eine Erklärung geben? Ich möchte es gerne 
verstehen.

Das Problem scheint erledigt zu sein.

von Karl H. (kbuchegg)


Lesenswert?

Balesi schrieb:
> Danke Karl heinz für deinen Tipp
>
> Karl heinz Buchegger schrieb:
>> Ist ja wohl ziemlich eindeutig.
>> Die section attributes von denen dein Compiler spricht, ist das EEMEM.
>> Und die einzigen lokalen Variablen, auf die das zutrifft, sind ....
>
> Das habe ich auch vermutet, aber wie gesagt, wich wusste nicht wie ich
> damit umzugehen habe. Muss ich das Attribut nur einmalig benutzen, wenn
> ja an welcher Stelle, usw.


2 Paar Schuhe.
Du hattest
1
void lernen(void)
2
{
3
4
uint16_t ee_Sense_1 EEMEM;
5
uint16_t ee_Sense_2 EEMEM;
6
uint16_t ee_Sense_3 EEMEM;
7
8
  eeprom_write_word(&ee_Sense_1, 0xa4CD); 
9
  eeprom_write_word(&ee_Sense_2, 0xa99A); 
10
  eeprom_write_word(&ee_Sense_3, 0xaE66); 
11
}

Diese Variablen ee_Sense_1 etc. haben nichts mit deinen globalen 
Variablen zu tun. Das sind zunächst einfach nur stink normale 
funktionslokale Variablen, so wie in
1
void foo()
2
{
3
  int i;
4
5
  for( i = 0; i < irgendwas; ++i )
6
    ...
7
}

Jetzt hast du deinen funktionslokalen Variablen aber das EEMEM Attribut 
verpasst. D.h. du wolltest sie in das EEPROM verlgen. Das geht aber 
nicht. Funktionslokale Variablen können nicht im EEPROM liegen. 
Funktionslokale Variablen werden beim Betreten einer Funktion erzeugt 
und verschwinden wieder beim Verlassen einer Funktion. Bei einem EEPROM 
wäre das aber ziemlich kontraproduktiv. Gerade bei denen möchte ja man, 
dass sie überleben. Sie sollen sogar einen Stromausfall überleben :-)

> Ich habe zunächst die Funktion lernen, wie von dir vorgschlagen
> abgeändert, ohne erneute deklaration (oder definition). Da kam dann
> wieder eine Fehlermeldung.

Merk dir bitte eines:
Eine Aussage  "Da kam dann eine Fehlermeldung" ist genausoviel wert, wie 
wenn du zum Arzt gehst und sagst: Es tut weh

Höchst wahrscheinlich lautete die Fehlermeldung (und die wird vom Linker 
gewesen sein), dass du eine 'undefined reference' hast.

Logisch. Du hast jetzt zwar haufenweise extern Variablen aber keine 
Definition. extern sagt ja nur: irgendwo anders existiert die Variable. 
Aber wo? Wo ist sie denn? Man kann nicht immer nur sagen: irgendwo 
anders. Irgendwann muss man auch Farbe bekennen und sagen: Hier!

> Nachdem ich dann eine global.c angelegt habe

und genau diese global.c sorgt dafür, dass die Variablen dann auch 
tatsächlich angelegt werden, indem global.h durch das vorhergehende 
#define so manipuliert wird, dass es die Variablen ohne das vorangehende 
"extern" compiliert.
Ohne "extern": Dadurch werden die Variablen dann auch tatsächlich 
angelegt und damit gibt es dann genau die eine Stelle von der vorher 
gesagt wurde: Irgendwo existieren diese Variablen. Das global.c ist 
quasi der Teil in deinem Programm, der das geforderte "Hier!" enthält.

http://www.mikrocontroller.net/articles/FAQ#Globale_Variablen_.C3.BCber_mehrere_Dateien

von Balesi (Gast)


Lesenswert?

Vielen Dank für deine Zeit und deine Hilfe. Ich habe nun einiges gelernt 
und hoffentlich soweit verstanden, dass ich diese Hürden in Zukunft 
leichter nehmen kann.

Karl heinz Buchegger schrieb:
>> Ich habe zunächst die Funktion lernen, wie von dir vorgschlagen
>> abgeändert, ohne erneute deklaration (oder definition). Da kam dann
>> wieder eine Fehlermeldung.
>
> Merk dir bitte eines:
> Eine Aussage  "Da kam dann eine Fehlermeldung" ist genausoviel wert, wie
> wenn du zum Arzt gehst und sagst: Es tut weh

Ich weiß, konnte mich nicht mehr an den Wortlaut erinnern und hatte die 
global.c vergessen anzulegen, danach kam die Fehlermeldung dann nicht 
mehr

> Höchst wahrscheinlich lautete die Fehlermeldung (und die wird vom Linker
> gewesen sein), dass du eine 'undefined reference' hast)
So war es glaube ich auch

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.