Forum: Compiler & IDEs call by reference will nicht , Atmega163, C


von Jens N. (midibrain)


Angehängte Dateien:

Lesenswert?

Hallo,

möchte die Uhrzeit in einer Funktion berechnen.
Dafür übergebe ich ihr die Adressen von std,min und sec (Stunden, 
Minuten, Secunden)
In der timer.c soll dann mithilfe eines SekundenFlags aus dem 
TimerInterrupt die Zeit berechnet werden und die Werte an die durch die 
Zeiger referenzierten Speicherplätze für std,min und sec gelegt werden.
Da das nicht funktioniert lass ich die Funktion gerade nur feste Werte 
verarbeiten, lasse also die Zeitberechnung weg. Um zu sehen ob die 
Funktion überhaupt angesprungen wird gibt sie einen Zähler zurück. Der 
zählt in der Main auch artig hoch, Funktion wird also angesprungen.

Anbei der, zugegebenermaßen umfangreiche, Code in C, aber man soll ja 
alles posten. Entscheident sind warscheinlich die timer.c und timer.h 
sowie die RedDisplayClock.c

Vielleicht enddeckt ja jemand den Fehler.

Jens

von Jens N. (midibrain)


Lesenswert?

hat keiner eine Idee oder ist der Code zu umfangreich?
Jens

von Oliver S. (oliverso)


Lesenswert?

Wie stellst du denn fest, daß das nicht funktioniert?

Oliver

von midibrain (Gast)


Lesenswert?

Hallo Oliver,

die Ausgabe auf dem Display ist falsch. sec hat immer den Wert 5, min 
und std bleiben 0.
Wenn ich in der Main statt der Variablen Zahlen in den Ausgabeaufruf für 
das Display setze funzt es. Ich denke irgendetwas mit der 
Zeigergeschichte funktioniert nicht, die 5 sieht so nach Speichermüll 
aus.

Jens

von Karl H. (kbuchegg)


Lesenswert?

midibrain schrieb:
> Hallo Oliver,
>
> die Ausgabe auf dem Display ist falsch. sec hat immer den Wert 5, min
> und std bleiben 0.
> Wenn ich in der Main statt der Variablen Zahlen in den Ausgabeaufruf für
> das Display setze funzt es. Ich denke irgendetwas mit der
> Zeigergeschichte funktioniert nicht, die 5 sieht so nach Speichermüll
> aus.

Die Zeigersache ist in Ordnung.
Aber hier, diese Funktion ist fehlerhaft.
1
void put_number_lcd(uint8_t a, uint8_t b, uint16_t number)
2
//setzt eine Zahl bis max. 99 rechtsbündig an position a, b  
3
{
4
uint8_t i = 0;
5
  if(number < 10)
6
    {
7
      put_string_lcd(a,b,"0");
8
      b += 1;
9
      i = 1;
10
    }
11
    if((number < 100) && (number > 9))
12
      {
13
        i = 2;
14
      }
15
  
16
  char tmp[i];
17
  itoa(number, tmp, 10);
18
  put_string_lcd(a, b, tmp);
19
}

Um einen String "23" zu bilden, benötigst du ein Array der Länge 3(!), 
und nicht 2.
Denn der String besteht aus 3 Zeichen. '2', '3' und dem abschliessenden 
'\0' Zeichen, welches jeden String beendet.

Korrigier das mal und sieh nach, ob das dann schon alles war.

: Bearbeitet durch User
von Paul (Gast)


Lesenswert?

Mach mal das in der Timer.c volatile

volatile uint8_t sec = 0;
volatile uint8_t min = 0;
volatile uint8_t std = 0;

von Karl H. (kbuchegg)


Lesenswert?

Ich weiss, das steht (stand zumindest) im Kernighan&Ritchi auch so 
drinnen. Aber warum schreibst du
1
  return(i);

return ist kein Funktionsaufruf. return kann man einen Ausdruck angeben, 
der ausgewertet wird und dessen Ergebnis zurückgegeben wird. Nirgendwo 
in der Syntax wird gefordert, dass der Ausdruck in Klammern stehen muss. 
Bringt auch nicht viel.
1
  return i;
ist genausogut lesbar, wenn nicht sogar besser. Und sogar mit weniger 
Aufwand und einfacher zu tippen.

Du schreibst ja auch nicht
1
   j = (i);
oder?

: Bearbeitet durch User
von Jens N. (midibrain)


Lesenswert?

Hallo Karl-Heinz,

erstaunlich was Du alles sehen kannst...

Es war tatsächlich die falsche Stringlänge in der Displayroutine!
Habe die Stringlänge geändert und nun ist die Ausgabe korrekt, die 
Zeigergeschichte war es also nicht.

Vielen Dank und einen geruhsamen Sonntag Abend aus Berlin.

Jens

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Ich hätt ja die Funktion ezeit_ausgabe so geschrieben (wenn ich im µC 
den Platz im Flash habe)
1
//***************************************************************************************
2
void ezeit_ausgabe(uint8_t std, uint8_t min, uint8_t sec)
3
{
4
  char buff[20];
5
6
  sprintf( buff, "%02d:%02d:%02d", std, min, sec );
7
  put_string_lcd( TIMEPOSITION_Z, TIMEPOSITION_S, buff );
8
}

aber so eine Zahlenausgabe an sich ist ja auch nützlich.

Merke: du brauchst an solchen Stellen nicht kleckern. Ob du temporär ein 
Array der Länge 3 oder 10 anlegst, ist Jacke wie Hose. Wenn diese 
Differenz im Speicherverbrauch dein Programm sprengt, dann ist die Kacke 
sowieso schon am dampfen.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> aber so eine Zahlenausgabe an sich ist ja auch nützlich.

Allerdings solltest du dir mal überlegen, was deine Funktion 
put_number_lcd so alles macht, wenn du der mal irrtümlich zb die Zahl 
587 übergibst, wie sie zb durch einen ungewollten Programmfehler 
durchaus auch schon mal vorkomme kann.
Das letzte was du nämlich brauchen kannst ist, dass dir deine 
Basis-Ausgabefunktionen abkratzen, weil da Fälle entstehen, die du 
selbstverständlich nicht bedacht und auch nicht berücksichtigt hast, 
weil die im Nichtfehlerfall nicht vorkommen. Nur ist halt selten etwas 
von Anfang an perfekt.

Wenn die führenden 0-en dann nicht stimmen, dann ist das kein Beinbruch. 
Wenn du dann aber versucht ein Array der Länge 0 zu allokieren, dann IST 
das ein Beinbruch. Kein Beinbruch hingegen ist es, wenn du itoa den 
Integer 7 konverteren lässt und itoa dazu ein char Array der Länge 7 zur 
Verfügung stellst. Dann werden eben temporär ein paar Teile des Arrays 
nicht benutzt, aber erst mal passiert sonst nicht viel. Insbesondere 
zerschiesst du dir dann auch nicht den Stack, indem du ein Array 
überläufst.

: Bearbeitet durch User
von Jens N. (midibrain)


Lesenswert?

Hallo Karl-Heinz,

hab die Ausgaberoutine dahingehend geändert das sie Zahlen > 99 
ignoriert. Das ist keine elegante lösung aber verhindert erst einmal 
merkwürdiges Verhalten aufgrund falscher (zu großer) Werte.
Das mit dem return(x) habe ich mir wohl am Anfang des programmierens 
"eingefangen". Ist wirklich unnütz, werde es mir abgewöhnen.

Vielen Dank noch einmal für die Hilfe und die Tip`s, immer wieder toll 
bei Euch im Forum!

Jens

P.S.: Wie kann ich diesen Beitrag als "gelöst" kennzeichnen?

von Fred (Gast)


Lesenswert?

Außerdem gibts in C kein call-by-reference... nitpick

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.