Forum: Mikrocontroller und Digitale Elektronik AVR variablen gültigkeit & zugriff


von Josh (Gast)


Lesenswert?

Hallo, ich habe ein kleines Problem mit dem angehängten code.

Ich möchte mithilfe der Funktion void displayDefRestTime() die 
rstTimeXxx variablen anzeigen, nachdem diese von der funktion restTime 
bearbeitet wurden.

Mein Problem ist, das mir der Compiler (AVR GCC) singemäß folgende 
Fehlermeldung ausgibt:
"variablen restTimeXxx in void restTime() nich declariert"

Welche möglichkeiten habe ich dies zu tun ohne globale oder statische 
Variablen einzusetzen? Eigendlich müssten doch meine variablen während 
des aufrufes von restTime() noch gültig sein, da die aufrufende Funktion 
nicht beendet wurde?
Gibt es auf uc eine möglichkeit mehrere variablen per return zurück zu 
geben?
Wie siehts mit Arrys oder pointern aus ?

1
//Resttime module
2
//it can be used with the RTC module
3
4
5
void displayDefRestTime()
6
{
7
  //define the variables for restTime()
8
  int rstTimeSek=userTimeSek;
9
  int rstTimeMin=userTimeMin;
10
  int rstTimeHour=userTimeHour;  
11
12
  //call Rest Time to process the rest Time
13
  restTime();
14
15
  //now we can display the rest Time
16
  lcd_write_int16(rstTimeHour);
17
  lcd_write_string(PSTR(":"));
18
    lcd_write_int16(rstTimeMin);
19
  lcd_write_string(PSTR(":"));
20
    lcd_write_int16(rstTimeSek);
21
  
22
23
  }//end of void displayRestTime()
24
25
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
26
void restTime()
27
{
28
  //don't forget to init the variables in the calling funktion.
29
  //the following ones are necesery
30
  
31
  for(int i=Sekunden;i>0;i--)
32
  {
33
  
34
    //looks if Sekonds are Zero
35
    if (rstTimeSek==NULL)
36
      {//if #0
37
     //..then looks if Minuten>0 and substracts one minute 
38
     //and set seconds to 60
39
     
40
     if(rstTimeMin) 
41
      { rstTimeMin--;
42
        rstTimeSek=60;}
43
        ////if minutes are Zero,
44
     else 
45
       { //else if#1
46
     //looks if Hour>0 and substracts one Hour 
47
     //and set Minutes to 60
48
         if(rstTimeHour)
49
      { rstTimeHour--;
50
        rstTimeMin=60;
51
           }//close else if#1 
52
          else
53
        rstTimeSek=0; //if rstTime Sek & Min & Hour is Zero, 
54
                    //let SEK Zero 
55
           }//#close else if#1
56
         }//close if#0
57
      else //Main If else, if Seconds not 0, substract 1 Second
58
        rstTimeSek--;
59
60
  }//end of while(Sekunde)
61
62
63
64
65
  for(int i=Minuten;i>0;i--)
66
  {
67
  
68
    //looks if Minutes are Zero
69
    if (rstTimeMin==NULL)
70
      {//if#0
71
        
72
    if(rstTimeHour)
73
    {//if#1
74
        rstTimeMin=60;
75
    rstTimeHour=NULL;       
76
        }//if#1
77
    else
78
    rstTimeMin=0; //if rstTime Min & Hour is Zero, let Min Zero 
79
80
         }//close if#0
81
      else //Main If else, if Seconds not 0, substract 1 Second
82
        rstTimeMin--;
83
84
  }//end of while(Minuten)
85
86
87
  for(int i=Stunden;i>0;i--)
88
  {
89
  
90
    //looks if rstTime hours aviable
91
    if (rstTimeHour)
92
      {//if#0
93
94
        rstTimeHour--;
95
96
     }//close if#0
97
   //if no Hours aviable let them Zero (do nothing)
98
  
99
100
  }//end of while(Stunden)
101
102
103
104
}//end of int restTime(); funktion
105
106
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Danke
josh

von Karl H. (kbuchegg)


Lesenswert?

Josh schrieb:

> Mein Problem ist, das mir der Compiler (AVR GCC) singemäß folgende
> Fehlermeldung ausgibt:
> "variablen restTimeXxx in void restTime() nich declariert"
>
und recht hat er

> Welche möglichkeiten habe ich dies zu tun ohne globale oder statische
> Variablen einzusetzen?

keine

> Eigendlich müssten doch meine variablen während
> des aufrufes von restTime() noch gültig sein, da die aufrufende Funktion
> nicht beendet wurde?

nope.
In C wird der Scope von Variablen statisch zur Compiletime festgelegt. 
Wenn du dynamische Bindung willst, musst du dir einen LISP Dialekt 
suchen, der dynamische Bindung unterstützt.

> Gibt es auf uc eine möglichkeit mehrere variablen per return zurück zu
> geben?
> Wie siehts mit Arrys oder pointern aus ?

Wie wäre es, wenn du dir ein Einführungsbuch zu C zu Gemüte führen 
würdest? Dort erfährst du dann auch, dass man Funktionen Argumente 
mitgeben kann ....

1
int foo( int a, int b )
2
{
3
  return a + b;
4
}
5
6
int bar1()
7
{
8
  int h = 5, j = 8, m;
9
  int x = 10, y = 12, z;
10
11
  m = foo( h, j );
12
  z = foo( x, y );
13
}

... und das das der C-übliche Weg ist, wie die aufrufende Funktion der 
aufgerufenen Funktion einen Teil ihrer Variablen zur freundlichen 
Bearbeitung zur Verfügung stellt. Aber: Die aufrufende Funktion stellt 
der aufgerufenen Funktion Variablen zur Verfügung und nicht "die 
aufgerufene Funktion greift einfach auf Variablen des Aufrufers zu wie 
sie lustig ist"

von Josh (Gast)


Lesenswert?

Hallo,

vielen dank für die Antwort.

Ein solches buch habe ich mir zu gemüte geführt, und die funktionen 
deines Bsp sind mir bekannt.

ich hatte gehofft eine möglichkeit zu finden 3 variable zurück zu geben 
um die Funktion nicht 3fach ausführen zu müssen.

Aber wenn das nicht klappt werde ich diese eben umbauen müssen

mfg
josh

von Filth _. (filth)


Lesenswert?

Deine Methode kann doch ein Array zurückgeben, in dem 3 Vars abgeleget 
werden.

von ... .. (docean) Benutzerseite


Lesenswert?

Alex G. schrieb:
> ein Array zurückgeben

auch das ist nicht einfach bzw sorgt für nette Effekte...

Lieber ein paar static Var. außerhalb deiner Fkt.

von Filth _. (filth)


Lesenswert?

Oh ok, war mir so nicht bekannt.

von Flo (Gast)


Lesenswert?

kannste ja referenzen in der Funktion übergeben, dann können die 
Parameter von der Funktion verändert werden.

void Increment(int &a)
{
  a++;
}


... //irgendwo im code

int i = 0;
increment(i);

//i ist jetzt 1

von horst (Gast)


Lesenswert?

> Eigendlich müssten doch meine variablen während des aufrufes von
> restTime() noch gültig sein, da die aufrufende Funktion
> nicht beendet wurde?

Die Funktion restTime kann ja auch von anderer Stelle aufgerufen werden. 
Z.b. von einer Funktion, in der es die entsprechenden Variablen nicht 
gibt.

> Gibt es auf uc eine möglichkeit mehrere variablen per return zurück zu
> geben?

Bei Arrays kannst du z.B. die Adresse übergeben. Ist ein wenig 
umständlich hier, vor allem wenn Du dich damit noch nicht so gut 
auskennst.

Nimm lieber Strukturen, dann hast du eine Variable mit mehrern Werten:

typedef struct
{
 int sek;
 int min;
 int hr;
} TIME;

TIME restTime (TIME rstTime)
{
 rstTime.sek = 1;
 rstTime.min = 2;
 rstTime.hr  = 3;

 return rstTime;
}

von Josh (Gast)


Lesenswert?

Hallo,

vielen dank für die reichlichen Antworten.

>Bei Arrays kannst du z.B. die Adresse übergeben. Ist ein wenig
>umständlich hier, vor allem wenn Du dich damit noch nicht so gut
>auskennst.

Ich dachte zeiger sind aufgrund des adressbereiches bei AVRs 16 Bit 
lang, weswegen man vor der verwendung absehen sollte?

>Nimm lieber Strukturen, dann hast du eine Variable mit mehrern Werten:

Das kling gut, und werde ich in Zukunft wohl so machen.

von Bernd O. (bitshifter)


Lesenswert?

Flo schrieb:
> void Increment(int &a)
> {
>   a++;
> }
>
> int i = 0;
> increment(i);
>
> //i ist jetzt 1
Nicht ganz. Erst mal müssen die Fehler beseitigt werden ;-)

1:
> void Increment(int &a)
> {
>   a++;
> }
a ist eine Adresse und kein Wert. Der Inkrement wirkt aber auf die 
Adresse. Korrekt wäre:
(*a)++;

2:
Der Compiler kennt nun die Funktion "Increment", aufgerufen wird aber 
"increment" (case-sensitive).

3,
Die Funktion erwartet einen Pointer auf int, bekommt aber ein int.
Korrekt wäre:
"Increment(&a);"


Gruß,
Bernd

von P. S. (Gast)


Lesenswert?

Bernd O. schrieb:

> 1:
>> void Increment(int &a)
>> {
>>   a++;
>> }
> a ist eine Adresse und kein Wert.

Hier wird eine Referenz erwartet, kein Zeiger. Das ist so richtig.

> Die Funktion erwartet einen Pointer auf int, bekommt aber ein int.
> Korrekt wäre:
> "Increment(&a);"

Nein, siehe oben.

von horst (Gast)


Lesenswert?

> Ich dachte zeiger sind aufgrund des adressbereiches bei AVRs 16 Bit
> lang, weswegen man vor der verwendung absehen sollte?

Und wie lang sind drei int? Die werden bei meiner Variante nämlich 
lustig auf dem Stack herumkopiert. Diese Variante ist auch nicht auf 
Effizienz ausgelegt.

Wenn ich mich recht erinnere, ist ein int auch 16 Bit lang. int8_t oder 
uint8_t reichen hier aber evtl. auch.

von Mark B. (markbrandis)


Lesenswert?

Peter Stegemann schrieb:
> Bernd O. schrieb:
>
>> 1:
>>> void Increment(int &a)
>>> {
>>>   a++;
>>> }
>> a ist eine Adresse und kein Wert.
>
> Hier wird eine Referenz erwartet, kein Zeiger. Das ist so richtig.

Moment, reden wir hier von C oder von C++?

von Hc Z. (mizch)


Lesenswert?

Es gibt einen Weg, die ursprüngliche Absicht umzusetzen, aber nur mit 
gcc.  gcc kann nested functions (eine Funktionsdefinition innerhalb 
einer anderen).  Diese innerhalb definierte Funktion kann auf die 
lokalen Variablen der Funktion(en), in denen sie steht, zugreifen.

Also genau das, was der TE ursprünglich wollte.  Man muss sich nur klar 
sein, dass das kompatibel zu nix außer der gcc-Familie ist.

von Flo (Gast)


Lesenswert?

Also ich hab den Code vor dem Posten kurz im devcpp ausprobiert 
(natürlich mit nem großen 'I' beim Aufruf) und es funktioniert so.

Das ganze nennt sich Referenz und so könnte der TE einige Werte, die er 
als Parameter verwendet, durch die Funktion verändern lassen.
So hab ich die Frage wenigstens verstanden.
:-)

von Karl H. (kbuchegg)


Lesenswert?

Flo schrieb:
> Also ich hab den Code vor dem Posten kurz im devcpp ausprobiert
> (natürlich mit nem großen 'I' beim Aufruf) und es funktioniert so.

Du hast einen C++ Compiler benutzt.
In C gibt es keine Referenzen.

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.