Hallo,
ich habe eine in C erstellte, ich nenne sie mal Regelungs-/
Steuerungssoftware in einer Regelung.c Datei, bei der ich eine Funktion
alle 10ms aus main aufrufe.
In dieser Funktion werden bestimmte Aktionen durch etwa 10 Flags
gesteuert und Sollwerte durch 5 Variablen für Berechnungen vorgegeben.
Ich möchte diese Flags und Sollwerte durch verschiedene Funktionen aus
main heraus verändern. Z.B. Set_Geschwindigkeit(100); oder Set_FlagA;
Bisher habe ich deshalb die Flags und Variablen in der Regelung.c Datei
static global angelegt und Funktionen geschrieben, die diese Flags und
Variablen verändern können.
Das heißt innerhalb dieser c.Datei sind die Variablen global, aus main
heraus sind sie aber nicht sichtbar.
Gibt es andere, bessere Möglichkeiten das zu lösen?
Ich überlege die globalen Variablen noch in einer Struktur
zusammenzufassen. Könnte ich mir die globalen Variablen aber auch
irgendwie ganz sparen?
Dann müsste ich aber lokale Variablen einer Funktion von außen verändern
können. Ist das möglich? Die Funktion soll nicht von den anderen
Funktionen aufgerufen werden, also kann ich ihr auch keine Werte
(ohnehin viele) übergeben.
Oder müsste ich das Programm von Grund auf anders organisieren damit ich
solche Sachen vermeide?
Danke und Gruß Stefan
Stefan schrieb:> Gibt es andere, bessere Möglichkeiten das zu lösen?
Was hältst Du denn an dem Konzept für schlecht?
Möchtest Du den Code im Modul mehrfach simultan mit anderen
Parametersätzen nutzen können, oder geht es Dir um irgendein "Prinzip"?
Es geht mir eigentlich ums Prinzip. Ich bin Student und habe gelernt,
dass globale Variablen unschön sind.. Teilweise sind sie aber nötig. Nun
weiß ich nicht ob sie bei mir nötig sind, oder ich unschön programmiert
habe;-)
Das ganze ist eine Projektarbeit und ich wollte das Programm so
gestalten, dass eventuell andere Nachfolger einfach meine C-Datei und
H-Datei einbinden, eine Funktion void Control(void); alle 10ms aufrufen
damit die Regelung und Steuerung arbeitet und mittels einmaligem Aufruf
anderer Funktionen z.B. die Geschwindigkeit ändern können ohne der
Funktion Control(void) jedesmal eine lange Parameterliste zu übergeben,
was fast die meiste Zeit gar nicht erforderlich ist.
Beantwortet das deine letzte Frage?
Das ganze läuft auf einem ARM Cortex-M3. Ist es da für die
Ausführungsgeschwindkeit sinnvoll die globalen Variabeln noch in einer
Struktur zu organisieren?
suzo schrieb:> Bei C, anders als bei C++, braucht man globale Variable.
Was sollte da in C++ anders sein als in C?
Stefan schrieb:> Das ganze läuft auf einem ARM Cortex-M3. Ist es da für die> Ausführungsgeschwindkeit sinnvoll die globalen Variabeln noch in einer> Struktur zu organisieren?
Für die Ausführungsgeschwindigkeit nicht, aber für die Übersichtlichkeit
des Codes.
> Das ganze ist eine Projektarbeit und ich wollte das Programm so> gestalten, dass eventuell andere Nachfolger einfach meine C-Datei und> H-Datei einbinden, eine Funktion void Control(void); alle 10ms aufrufen> damit die Regelung und Steuerung arbeitet und mittels einmaligem Aufruf> anderer Funktionen z.B. die Geschwindigkeit ändern können ohne der> Funktion Control(void) jedesmal eine lange Parameterliste zu übergeben,> was fast die meiste Zeit gar nicht erforderlich ist.
Du kannst auch der Funktion einen einzigen Parameter übergeben, der ein
Zeiger auf eine Struktur ist, die alle nötigen Werte enthält. Wo diese
Struktur tatsächlich steht, ist deinem Regler dann egal.
Danke für die Antworten erstmal.
Rolf Magnus schrieb:> Du kannst auch der Funktion einen einzigen Parameter übergeben, der ein> Zeiger auf eine Struktur ist, die alle nötigen Werte enthält. Wo diese> Struktur tatsächlich steht, ist deinem Regler dann egal.
Wenn ich der Funktion einen Zeiger auf eine Struktur übergebe, müsste
die Struktur aber innerhalb meiner C-Datei auch wieder global sein,
damit verschiedene Funktionen die Werte verändern können oder?
Oder wie lege ich die Struktur an und manipuliere dann am Besten die
Werte in der Struktur?
Stefan schrieb:> müsste> die Struktur aber innerhalb meiner C-Datei auch wieder global sein
Überleg dir mal den Unterschied zwischen "Global" und "Sichtbar".
Wenn du eine globale Struktur/Variable anlegst, dann ist die auf jeden
Fall nur 1 mal und zwar global da. Es kann nur sein, dass sie von einer
bestimmten Quelldatei aus nicht sichtbar ist. Du darfst aber trotzdem
nicht ungestraft dort eine zweite andere gleichnamige Struktur/Variable
anlegen. Der Linker wird dir da dann Probleme machen.
Du wirst also sowas nicht machen können und meinen, du hättest zwei
verschiedene globale Variable namens h:
main.c
Stefan schrieb:> Es geht mir eigentlich ums Prinzip. Ich bin Student und habe gelernt,> dass globale Variablen unschön sind.
Du hast keine globalen Variablen in dem Sinn, dass sie in jedem
Software-Modul sichtbar wären. Sondern sie sind in einem einzelnen Modul
"gekapselt", und andere können darauf nur über definierte Schnittstellen
(Funktionen) zugreifen. Passt doch.
Abgesehen davon: Im Embedded-Bereich ist die Verwendung von globalen
Variablen durchaus erforderlich und auch üblich. Mehr als 70% aller
Autos fahren mit Motorsteuerungen mit größtenteils globalen Variablen
durch die Gegend.
Lothar Miller schrieb:> Du wirst also sowas nicht machen können und meinen, du hättest zwei> verschiedene globale Variable namens h:> main.c> short h;>> main() {> ....> }> sub.c> long h;>> sub() {> ....> }
Also avr-gcc meint in so einem Fall:
"Build succeeded with 0 Warnings..."
Lothar Miller schrieb:> Überleg dir mal den Unterschied zwischen "Global" und "Sichtbar".> Wenn du eine globale Struktur/Variable anlegst, dann ist die auf jeden> Fall nur 1 mal und zwar global da. Es kann nur sein, dass sie von einer> bestimmten Quelldatei aus nicht sichtbar ist. Du darfst aber trotzdem> nicht ungestraft dort eine zweite andere gleichnamige Struktur/Variable> anlegen. Der Linker wird dir da dann Probleme machen.>> Du wirst also sowas nicht machen können und meinen, du hättest zwei> verschiedene globale Variable namens h:> main.c>
Rolf Magnus schrieb:> Stefan schrieb:>> Das ganze läuft auf einem ARM Cortex-M3. Ist es da für die>> Ausführungsgeschwindkeit sinnvoll die globalen Variabeln noch in einer>> Struktur zu organisieren?>> Für die Ausführungsgeschwindigkeit nicht, aber für die Übersichtlichkeit> >des Codes.
Es kann durchaus einen Einfluss auf die Ausführungsgeschwindigkeit und
Codegröße haben wenn man modulglobale Variablen in einer Struktur
zusammenfasst. Das alles ist aber Compiler- und Systemabhängig.
Grund:
Der Compiler kennt beim Übersetzen des Moduls (der einzelnen C-Datei)
die Adressen der globalen Variablen nicht. Über diese entscheidet erst
der Linker. Er muss also für jeden Zugriff eine komplette Adresse in ein
Register laden. Werden die Variablen aber in eine Struktur
zusammengefasst so kennt der Compiler den Offset der einzelnen Elemente
zueinander und muss nur eine Adresse in ein Register laden und kann dann
mit Offset adressieren.
Matthias
Lothar Miller schrieb:> Du wirst also sowas nicht machen können und meinen, du hättest zwei> verschiedene globale Variable namens h:> main.c short h;>> main() {> ....> }> sub.c long h;>> sub() {> ....> }
Stimmt das geht nicht, weil die Sichtbarkeit wirklich global über alle
Module ist. Aber ich habe meine globalen Variablen in meinem Modul mit
static angelegt, vielleicht kam das in meinem 1. Post nicht genug
heraus. Also sind sie nur in meinem Modul sichtbar, außer ich deklariere
sie irgendwo anderes mit extern, oder? Vielleicht setze ich die Begriffe
auch nicht sauber genug oder falsch ein. Bezeichnet man eine in der
Sichtbarkeit eingeschränkte globale Variable anders?
Also habe ich diesen genannten Fall:
Daniel V. schrieb:> Und so?:> static short h;>> main() {> ....> }> sub.c static long h;>> sub() {> ....> }
Und wie in diesem letzten Fall müsste ich die Struktur static global in
meinem Modul anlegen damit mehrere andere Funktionen in diesem Modul
Werte innerhalb der Struktur verändern können oder?
Wenn das, wie ich es nun verstanden habe, auch als eine Kapselung
innerhalb eines Moduls bezeichnet werden kann und wohl häufig eingesetzt
wird, kann ich mich damit zufrieden geben und diese Lösung umsetzen:-)
Ich dachte nur vielleicht gibt es noch andere Möglichkeiten/Konzepte,
von denen ich bislang noch nichts gehört habe oder habe noch nicht weit
genug gedacht.
Danke auch an den Rest und die Erklärung über die Adressierung mit
Offset. Dann werde ich, wenn nicht noch andere Ideen kommen, das ganze
wie bisher, zusätzlich noch in einer Struktur organisiert lösen.
Ralf G. schrieb:> Also avr-gcc meint in so einem Fall:> "Build succeeded with 0 Warnings..."
Überraschend.
Und noch überraschender, was hier ganz ohne Fehler und Warnung passiert:
main.c
1
chara;
2
charb;
3
longc;
4
chard;
5
6
intmain(void)
7
{
8
while(1)
9
{
10
b=a+3;
11
sub();
12
a++;
13
}
14
}
sub.c
1
struct
2
{
3
shortv2;
4
shortv1;
5
}a;
6
7
longb;
8
charc;
9
chard;
10
11
voidsub(void){
12
b=a.v1;
13
}
Dis Sicht der Dinge aus dem AVR-Studio-Debugger siehe Screenshots.
Einmal aus Main.c und einmal von Sub.c aus gesehen. Interessant: die
Adressen. Es wird einfach der Speicherplatz für das jeweils größere
Element mit gleichem Namen reserviert.
Stefan schrieb:> Also sind sie nur in meinem Modul sichtbar, außer ich deklariere> sie irgendwo anderes mit extern, oder?
Nein, eine in einem Modul als static deklarierte Variable ist auch mit
"extern"-Deklaration aus einem anderen Modul heraus nicht sichtbar.
Der Linker wird beim "extern"-Zugriff auf so eine Variable
korrekterweise "undefined symbol" ausgeben.
Lothar Miller schrieb:> Und noch überraschender, was hier ganz ohne Fehler und Warnung passiert:
Das ist eine sehr lästige und unappetitliche Eigenschaft des gcc, daß
der mehrfach definierte globale Symbole übereinanderlegt. Das lässt sich
mit -no-common auch abschalten (und sollte, wie Dein Beispiel nahelegt,
auch wirklich tunlichst abgeschaltet werden).