Hallo,
langsam werden meine Codes länger und unübersichtlich, deswegen wollte
ich jetzt mein Projekt sinnvoll in externe Dateien auslagern. Bei dem
ganzen machen mir irgendwie globale Variablen in der ISR Probleme.
Mein Programm soll folgendes machen:
Wenn sich was an der Schnittstelle tut, wird ein Interrupt ausgelöst.
Somit bearbeitet mein µC den Krempel, der in der ISR(USART_RXC_vect)
{...} steht.
Jetzt habe ich aber 2 Variablen mit denen ich in der main Fkt. arbeiten
möchte.
1. uart_string <- Hat in meinem Fall 3 Felder. 2 Bytes + \0
Die Variable wird zum testen an PORTC ausgegeben um 8 LED's zu treiben.
2. uart_str_complete <- gibt einfach eine boolsche Aussage, ob nun alles
empfangen wurde. Dieser muss nach der verwendung des Codes wieder auf 0
zurückgesetzt werden.
Mein Problem ist nun: Nach der Auslagerung bekomme ich es ums verrecken
nicht mit den globalen Variablen gebacken.
z.B. das steht in uart.c
1
volatileuint8_tuart_str_count=0;
2
volatileunsignedcharnextChar;
3
volatilecharuart_string[UART_MAXSTRLEN+1]="";
4
volatileuint8_tuart_str_complete=0;
Normal sind diese Variablen doch global oder nicht?
Selbst wenn ich es direkt vor allen includes in meine main.h setze
klappt es nicht. Ich kann die Fkt. uart_string nicht in meiner Main
verwenden so wie es in meinem Code ist. Es kommt immer die
Fehlermeldung: 'uart_string' undeclared (first use in this function).
Hoffentlich habe ich mein Problem einigermaßen verständlich formuliert.
Weiß jemand eine Lösung für dieses Problem?
Als Anhang füge ich noch meinen Code hinzu.
Die Idee ist ja schon nicht schlecht, für main braucht man das
allerdings nicht.
Wenn du da jetzt deine globalen Variablen mit extern davor hinschreibts,
wird alles gut.
Oliver
Die Idee ist ja schon nicht schlecht, für main braucht man das
allerdings nicht.
Wenn du da jetzt deine globalen Variablen mit extern davor hinschreibst,
wird alles gut.
Oliver
Problem ist nur: Der header main.h wird öfter gecallt.
Nun wird die Fehlermeldung: multiple definition für die Var. ausgegeben.
Ich habe es auch schon mit einem global_var.h header versucht und dann
in meiner main.h geschrieben:
(Da gibt es hier ja eine schöne Anleitung)
main.h
1
...
2
...
3
#define EXTERN
4
#include"global_var.h"
5
6
...
7
...
global_var.h
1
#ifndef EXTERN
2
#define EXTERN extern
3
#endif
4
5
EXTERNvolatilecharuart_string[3]="";
Hat leider auch nichts gebracht...
Wenn ich es mit einer anderen Variable versuche und diese dann in die
global einfüge klappt es überall. Mir scheint es irgendwie, als hätte
der ISR ein Problem damit.
Thomas P. schrieb:> Hat leider auch nichts gebracht...
SChmeiss das EXTERN Makro raus und mach es so, wie es die meisten
machen.
Vor allen Dingen dann, wenn du nicht weisst das eine Initialisierung
automatisch aus einer Deklaration eine Definition macht.
Nicht künsteln! Dann funktioniert das auch
main.h
Daniel A. schrieb:> main.c:> volatile char uart_string[3] = "";>> main.h> extern volatile char uart_string[3];
Klappt leider auch nicht... :-(
Letztendlich macht das selbe ja der Header global_var.h
Irgendwie stehe ich mit dem extern noch ein wenig auf dem Schlauch.
Ich habe zumindest gelernt: Eine Variable welche innerhalb einer
Funktion deklariert wird, lebt nur so lange, wie diese auch ausgeführt
wird. Danach wird Sie aus dem Speicher gelöscht.
Alles andere was vor der main{} steht und nicht in einer Funktion ist,
ist doch grundsätzlich als global zu sehen, oder nicht?
Thomas P. schrieb:> Daniel A. schrieb:>> main.c:>> volatile char uart_string[3] = "";>>>> main.h>> extern volatile char uart_string[3];>> Klappt leider auch nicht... :-(
Doch das klappt.
Dann hast du noch einen Hund eingebaut.
> Letztendlich macht das selbe ja der Header global_var.h
Nein, das tust du eben NICHT!
Sobald du eine Initialisierung angibst, ist das 'extern' nur noch
Makulatur!
Die Initialisierung MUSS im Header File weg!
> Alles andere was vor der main{} steht und nicht in einer Funktion ist,> ist doch grundsätzlich als global zu sehen, oder nicht?
Darum gehts überhaupt nicht.
Es geht um die Unterscheidung zwischen Definition und Deklaration. Eine
Definition ist etwas, bei dem vom Compiler tatsächlich Speicherplatz
reserviert wird. Das sind Definitionen
1
inti;
2
doublej;
3
4
voidfoo()
5
{
6
j=1;
7
}
Eine Deklaration ist etwas, das den Compiler darüber informiert, dass
etwas existiert und welche Eigenschaften es hat. Das sind Deklarationen
1
externinti;
2
externdoublej;
3
4
voidfoo(void);
Das hier
1
externinti=5;
ist KEINE Deklaration, sondern eine Definition. Die Intialisierung
erzwingt dies.
Du kannst in einem kompletten Programm beliebig viele Deklarationen von
ein und demselben Teil haben, solange die nur alle übereinstimmen. Du
kannst aber nur EINE Defintion haben.
In jedem File wird das und nur das #includ-iert was tatsächlich in
diesem File (sei es Header oder C-File) notwendig ist. Sieh dir jede
Datei an. Jede ist in sich vollständig. Die Header Datei uart.h enthält
alles, was der Source Code in uart.h von sich preisgeben will. Aber auch
nicht mehr. Im Header File wird die Schnittstelle zu uart.c festgelegt.
Da sind alle Informationen, die ein Verwender deines UART Moduls vom
Modul wissen muss um es zu verwenden. Dazu gehören natürlich die nach
aussen sichtbaren Funktionen. Dazu gehören aber auch die globalen
Variablen, die vom Code in uart.c zur geschätzen (vorsichtigen)
Verwendung bereit gestellt werden. Und dazu gehören auch auch Makros,
sofern sie von allgemeinerem Interesse sind und nicht nur irgendwelche
Details im Code beschreiben, die ausser dem Code in uart.c niemanden was
angehen. In letzterem Fall kommen sie dann ins C-File. Aber der
entscheidende Punkt ist: Im Header File sind letzten Endes dann nur
Deklarationen (es gibt auch Ausnahmen), im C-File sind die zugehörigen
Definitionen.
Solche Rundumschlag-Header Dateien, die erst mal 200 andere Header
includieren, die meidest du besser. So viel Arbeit ist das nicht, bei
den AVR typisch kleinen Programmen jedes File in sich konsistent zu
machen.
F_CPU gibst du am besten in die Projekteinstellungen vom Atmel Studio
So, es funktioniert tatsächlich!
Karl Heinz schrieb:> Solche Rundumschlag-Header Dateien, die erst mal 200 andere Header> includieren, die meidest du besser. So viel Arbeit ist das nicht, bei> den AVR typisch kleinen Programmen jedes File in sich konsistent zu> machen.
Stimmt auch wieder...
Ich werde mich noch mit den Variablen auseinandersetzen, da besteht noch
ein wenig Nachholbedarf ;-). Oben hast du ja ein paar gute Beispiele
gebracht.
Vielen Dank für die Mühe, welche du dir gemacht hast Karl Heinz.
EDIT:
Kleine Frage noch: Was für einen Unterschied macht es, wenn ich die
F_CPU nicht in Atmel-Studio eintrage sondern als #define?
Gruß
Thomas
Thomas P. schrieb:> Kleine Frage noch: Was für einen Unterschied macht es, wenn ich die> F_CPU nicht in Atmel-Studio eintrage sondern als #define?
In den Projekteinstellungen steht sie einmal drin und gilt für alle
Dateien. Wenn du die Frequenz änderst, änderst du sie einmal und alle
wissen Bescheid.
Schreibst du es als define in jede einzelne Datei, musst du bei einer
Änderung jede Datei ändern. Vergisst du das oder benutzt eine Datei in
verschiedenen Projekten, compilieren z.B. die Timer mit einer anderen
Frequenz als der UART. Und diese andere Frequenz ist garantiert die
falsche.
mfg.
@ Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)
>Schreibst du es als define in jede einzelne Datei, musst du bei einer>Änderung jede Datei ändern.
Genau DAS macht man eben nicht. Man schreibt sie EINMAL in EINE
Header-Datei, z.B. main.h, die wird dann bei Bedarf von allen anderen
Dateien #include genutzt.
Falk Brunner schrieb:> Genau DAS macht man eben nicht. Man schreibt sie EINMAL in EINE> Header-Datei, z.B. main.h, die wird dann bei Bedarf von allen anderen> Dateien #include genutzt.
warum sollte aber Datei die überhaupt nichts von der main wissen soll
(nur dann kann man sie auch in anderen Projekten nutzen) eine main.h
einbinden?
Im makefile oder den Projekteinstellung ist F_CPU besser aufgehoben.
Falk Brunner schrieb:> Genau DAS macht man eben nicht. Man schreibt sie EINMAL in EINE> Header-Datei, z.B. main.h, die wird dann bei Bedarf von allen anderen> Dateien #include genutzt.
Das habe ich doch auch geschrieben, dass man das nicht macht. Aber in
main.h, wenn man sowas überhaupt hat, hat das auch nichts zu suchen.
Das gehört in die Projetkteinstellungen.
mfg.