Forum: Mikrocontroller und Digitale Elektronik Variable mit merkwürdigem Verhalten


von Kai K. (kaya)


Lesenswert?

Hallo,

ich hab ein Problem mit einer Variablen. Also ich hab den Fehler nach 
langem suchen eingrenzen können. Es liegt an der Variablen in meinem 
Programm, die die Anzahl der ADC-Messungen, über die ein Mittelwert 
gebildet wird, angibt.

Ich setze den Wert z.Z. auf zwei. Wenn das Programm aber auf dem µC 
gespielt wird, lass ich mir z.Z. die Variable auf den LCD anzeigen, sie 
ist null.
Ich hab im Programm geschaut, aber rufe diese Variable nur beim auslesen 
des ADCs auf. Deklariert ist sie in einer C-Datei in der alle 
veränderbaren Variablen stehen. Witzig ist, dass wenn ich die Variable 
umbenenne (Rename in AVR-Studio5), funktioniert es und sie wird auf dem 
LCD als 2 angezeigt.

Woran kann sowas liegen?
Ich benutze unteranderem long long Zahlen. Kann dies zu instabilitäten 
führen. (Benutzten sollte man sie ja nicht unbedingt, aber ich hab 
Zeitdruck und bin froh wenn es erstmal läuft. Im zweiten Anlauf möchte 
ich die long long Variablen aus dem Programm nehmen)

Vielleicht kann mir jemand einen Tipp geben.

Vielen Dank.
Kai



µC: AT90CAN128
Software: AVR-Studio 5 (zum kompilieren)
          AVR-Studio 4.19 (zum flashen mit JTAGer Nachbau)


Ausschnitte aus dem Programm:

In h-Datei:
unsigned int quantity_readout;

In C-Datei:
quantity_readout=2;

In ADC:
for( i=0; i<quantity_readout; i++ )
{
        ADCSRA |= (1<<ADSC);
  while ( ADCSRA & (1<<ADSC) )
  {
           ;
  }
  result += ADCW;
}
ADCSRA &= ~(1<<ADEN);
result /= quantity_readout;

von (prx) A. K. (prx)


Lesenswert?

Es gibt bei Fehlersuche via Forum eine Daumenregel: Ziemlich oft liegt 
der Fehler nicht in den 10 Zeilen, in denen man ihn nach tagelanger 
Suche selbst vermutet aber nicht findet, oder ist darin jedenfalls für 
Dritte nicht erkennbar. Es ist daher oft nicht zielführend, nur exakt 
diese Zeilen aus dem Kontext zu reissen und zu posten.

Verschärfend kommt manchmal hinzu, dass nicht der Code selbst sondern 
ein erdachtes Äquivalent gepostet wird, in dem genau das Problem nicht 
mehr enthalten ist.

von Kai K. (kaya)


Lesenswert?

Ja das stimmt sicher. Aber wie kann sowas sein, dass eine Variable 
funktioniert, wenn ich sie zum Beispiel quantity_readout2 nenne und ohne 
die 2 funktioniert sie nicht. Ich kenne mich mit der tieferen Materie 
was beim kompilieren passiert nicht aus.kann es dort zu solchen fehlern 
führen?

ICh wollte auch nicht das jemand den Fehler findet. Ich kann sie ja 
umbenennen (dann funktioniert es) , aber ich hoffe, dass die Profis hier 
einfach mehr verständnis haben und sofort diesen Fehler erkennen, anhand 
des Verhaltens. Kann es sein, dass AVR-Studio 5 beim kompilieren was 
überschreibt? Kommt sowas vor?

von DirkB (Gast)


Lesenswert?

Das
1
unsigned int quantity_readout;
gehört in die .c, nicht in die .h

in die .h gehört dann ein
1
extern unsigned int quantity_readout;

von (prx) A. K. (prx)


Lesenswert?

Kai Krestegal schrieb:

> die 2 funktioniert sie nicht. Ich kenne mich mit der tieferen Materie
> was beim kompilieren passiert nicht aus.kann es dort zu solchen fehlern
> führen?

Ich kenne mich auf der Ebene etwas besser aus und ja, so etwas kann das 
Verhalten eines fehlerhaften Programmes verändern.

> Kann es sein, dass AVR-Studio 5 beim kompilieren was
> überschreibt?

Ja selbstverständlich. Da werden ein paar Dateien auf deinem PC 
überschrieben.

von (prx) A. K. (prx)


Lesenswert?

DirkB schrieb:

> in die .h gehört dann ein
> extern unsigned int quantity_readout;

Nur führt das entweder zu einer Fehlermeldung des Compilers oder es ist 
nicht das eigentliche Problem.

von Kai K. (kaya)


Lesenswert?

Wie A.K. schon schrieb hat das dazu geführt, dass der Kompiler 
Fehlermeldungen auswirft.

Ich werd die Variable erstmal umbenennen. Aber sinn macht das ja 
eigentlich nicht,oder??

von DirkB (Gast)


Lesenswert?

Da meckert nicht der Compiler.
Das sollte zu einer Meldung des Linkers führen.

von Kai K. (kaya)


Lesenswert?

Bei mir kamen aber Fehlermeldungen. Aber ich glaub ich hab sicher soviel 
saukram in meinem Programm, es ist ein wunder, dass es läuft.

Aber danke für eure Hilfe. Ich hab die Variabel jetzt readout_quantity 
genannt. Komisch ist ja, das das Programm mit dem vorher genannten Namen 
lief, als ich noch beim schreiben des Programms war. (immer mal wieder 
getestet)

von Stefan E. (sternst)


Lesenswert?

Variable ist 0, obwohl sie 2 sein sollte?
Problem verschwindet, wenn anderer Name?
=> Ich setzte mein Geld auf ein String-Array, welches um 1 zu kurz ist.

Es sind aber noch andere Szenarien denkbar, z.B. Stack-Überlauf.

von (prx) A. K. (prx)


Lesenswert?

Kai Krestegal schrieb:

> Wie A.K. schon schrieb hat das dazu geführt, dass der Kompiler
> Fehlermeldungen auswirft.

<seufz> Wer sowas ignoriert, bei dem ist Hopfen und Malz verloren.

Gibts noch weitere "völlig unwichtige" Fehlermeldungen und Warnungen?

> Ich werd die Variable erstmal umbenennen. Aber sinn macht das ja
> eigentlich nicht,oder??

Damit löst du nicht das Problem, du deckst es nur zu. Du solltest das 
tun, was Dirk geschrieben hat.

von Stefan E. (sternst)


Lesenswert?

Kai Krestegal schrieb:
> Aber danke für eure Hilfe. Ich hab die Variabel jetzt readout_quantity
> genannt.

Das behebt aber mit Sicherheit nicht dein ursprüngliches Problem. Du 
hast es nur an eine Stelle verlagert, wo es im Augenblick keine 
sichtbaren Symptome hat.

von Kai K. (kaya)


Lesenswert?

Ja ich sollte die Ursache bekämpfen und nicht nur das Symptom. Es wird 
sicher zufällig grad diese Variable gewesen sein. Beim nächsten mal eine 
Andere. Ich werd es nochmal mit dem extern versuchen.

von Kai K. (kaya)


Lesenswert?

Error  62  undefined reference to `quantity_readout' (adc.c)
Error  2  expected 'const uint16_t *' but argument is of type 'unsigned 
int' (eeprom.h)
Error  54  expected 'const char *' but argument is of type 'unsigned 
char *' (lcd-routine.h)

Error 2 und 54 kommen häufiger in der eeprom.h und lcd-routine.h vor.

von Kai K. (kaya)


Lesenswert?

DirkB schrieb:
> unsigned int quantity_readout;gehört in die .c, nicht in die .h
>
> in die .h gehört dann einextern unsigned int quantity_readout;

hab es wie oben geändert

von (prx) A. K. (prx)


Lesenswert?

Mach nur weiter so und lüg dir selber in die Tasche.

M.a.W: Komm wieder, wenn du sämtliche Fehler und vorzugsweise auch 
sämtliche Warnungen los bist. Und sie nicht bloss zugedeckt hast. Bis 
dahin ist das völlig witzlos.

von DirkB (Gast)


Lesenswert?

Variablen definitionen gehören in die .c
Variablen deklarationen kommen in die .h

Aus wievielen Modulen besteht denn dein Programm?

von Kai K. (kaya)


Lesenswert?

A. K. schrieb:
> lüg dir selber in die Tasche.

Ich hab doch grad angefangen das Problem (Ursache) zu suchen. Hol doch 
dann nicht gleich die verbale Brechstange raus. Bin ja gewollt zu 
lernen.

von Kai K. (kaya)


Lesenswert?

DirkB schrieb:
> Variablen definitionen gehören in die .c
> Variablen deklarationen kommen in die .h
>
> Aus wievielen Modulen besteht denn dein Programm?

So hab ich es auch bis jetzt aufgebaut. Und Variablen die auch in 
anderen Funktionen stehen, werden im Header deklariert.

Meint Module die Funktionen?

12 C-Dateien
14 H-Dateien

Im Programm benutz ich Timer,ADC,LCD,IO-PORTS,EEPROM,einige 
Berechnungen.

Wo ich noch einen Fehler vermute sind diese long long Variablen. Könnten 
die zu solchen Fehlern führen? Oder meine dermaßen deletantische EEPROM 
Speicherung mit fester Adresse.

von DirkB (Gast)


Lesenswert?

Kai Krestegal schrieb:
> So hab ich es auch bis jetzt aufgebaut. Und Variablen die auch in
> anderen Funktionen stehen, werden im Header deklariert.

So bekommt jede .c Datei (die ja alle seperat compiliert werden) eine 
eigene Variable mit dem selben Namen.
Der Linker versucht nun die unter einen Hut zu bekommen. Das sollte eine 
Meldung geben.
Das willst du so nicht haben.

Darum werden die Variablen nur einmal in einer .c deklariert.

Für die anderen .c erfolgt die Deklaratin über das extern.

von DirkB (Gast)


Lesenswert?

Mist.
Es muss heißen:

Darum werden die Variablen nur einmal in einer .c definiert.

Für die anderen .c erfolgt die Deklaration über das extern.

von Kai K. (kaya)


Lesenswert?

DirkB schrieb:
> So bekommt jede .c Datei (die ja alle seperat compiliert werden) eine
> eigene Variable mit dem selben Namen.
> Der Linker versucht nun die unter einen Hut zu bekommen. Das sollte eine
> Meldung geben.

Also ich deklariere die Variable nur in einer Header-Datei. Nicht in 
mehreren. Vielleicht hab ich mich blöd ausgedrückt oder hab es falsch 
verstanden.

von DirkB (Gast)


Lesenswert?

Du inkludierst diese Headerdatei doch sichelich in mehreren C-Dateien.

Da das #include des Preprozessors aber nur reiner Textersatz ist, steht 
dann in jeder C-Datei (in der der Header eingebunden wird) auch diese 
Definition.

von Kai K. (kaya)


Lesenswert?

Ich werd das morgen weiter machen. Vielleicht seh ich dann wieder mehr. 
Danke euch für die Hilfe!
Wünsch allen noch einen schönen Abend.
Kai

von Kai K. (kaya)


Lesenswert?

DirkB schrieb:
> Du inkludierst diese Headerdatei doch sichelich in mehreren C-Dateien.

Ja genau. Ich hab eine große includes.h in der stehen alle Header, die 
dann in jeder Funktion eingebunden werden. Aber ich beginne und ende die 
Header mit folgendem Zusatz:

Beispiel:

#ifndef PORTS_H_
#define PORTS_H_

void init_ports(void);


#endif /* PORTS_H_ */

Dadurch sollte es doch nur einmal eingebunden werden oder?

von DirkB (Gast)


Lesenswert?

Kai Krestegal schrieb:
> Dadurch sollte es doch nur einmal eingebunden werden oder?

Schon, aber in jeder C-Datei.

Jede C-Datei wird für sich compiliert.
Dabei hat der Compiler kein Wissen aus anderen Compilerläufen.
Es läuft erst der Preprozessor über die Datei. Diesee ersetzt die 
#includes durch den Inhalt der entsprechenden Datei und expandiert noch 
die Makros/defines.

Du kannst dir den Preprozessor-Output auch anschauen (Du musst die 
Compileroption setzten, die diese Datei erzeugt, bzw. nicht löscht)

Der Compiler erzeugt dann aus den .c die Objectdateien (.o oder .obj)

Diese werden dann vom Linker zu einem ausführbaren Programm gebunden.

von Kai K. (kaya)


Lesenswert?

Okay, tausend dank schon mal. Das schau ich aber morgen. Werd nun 
erstmal an der Matratze horchen.
Wünsch einen schönen Abend.

von Kai K. (kaya)


Lesenswert?

So mal ein Update hab die Ursache auf ein String Array eingrenzen 
können. Wenn ich diese aus dem Programm nehme, wird die Variable richtig 
angezeigt.

Stefan Ernst schrieb:
> Autor: Stefan Ernst
>         (sternst)
> Datum: 25.02.2012 20:59
>
> Variable ist 0, obwohl sie 2 sein sollte?
> Problem verschwindet, wenn anderer Name?
> => Ich setzte mein Geld auf ein String-Array, welches um 1 zu kurz ist.
>
> Es sind aber noch andere Szenarien denkbar, z.B. Stack-Überlauf.

Ich habe das Array wie folgt deklariert:
char supply_price_string[5];

In der Funktion wird folgendes gemacht:
/* supply price -> int to string */
supply_price_string[0]=(supply_price_int/1000)+48;
supply_price_string[1]=46;
supply_price_string[2]=((supply_price_int%1000)/100)+48;
supply_price_string[3]=((supply_price_int%100)/10)+48;
supply_price_string[4]=((supply_price_int%10)/1)+48;
supply_price_string[5]='\0';

Wenn ich diese Funktion entferne, läuft alles wieder.

von Kai K. (kaya)


Lesenswert?

Mit einer länge von 6 geht es auch wieder?

char supply_price_string[6];

von (prx) A. K. (prx)


Lesenswert?

Ein Array aus 5 Elementen in das du 6 Elemente reinschreibst findest du 
normal?

von Kai K. (kaya)


Lesenswert?

Nicht? Sry, aber jetzt nicht anfangen rum zu meckern.

Ich dachte da ist immer noch die 0 am Anfang ein Element

von (prx) A. K. (prx)


Lesenswert?

Kai Krestegal schrieb:

> Ich dachte da ist immer noch die 0 am Anfang ein Element

Ja, da schon, aber das Element [5] exitiert nicht, nur 0..4. Besorg dir 
ein ordentliches C Buch.

Interessanterweise haben sich beide Prophezeihungen bestätigt. Der 
Fehler lag nicht in den von dir geposteten Zeilen und es war ein 
Array-Überlauf.

> Sry, aber jetzt nicht anfangen rum zu meckern.

Meine Antwort bezog sich auf dein vorheriges Posting. Dass dir in 
gleicher Minute selber der Groschen fiel war mir da noch nicht bekannt.

von (prx) A. K. (prx)


Lesenswert?

Eine Kleinigkeit am Rande: Aus
supply_price_string[0]=(supply_price_int/1000)+48;
machst du besser
supply_price_string[0]=(supply_price_int/1000)+'0';

von Kai K. (kaya)


Lesenswert?

A. K. schrieb:
> supply_price_string[0]=(supply_price_int/1000)+'0';

Ah okay danke.

Man jetzt kann ich doch froh sein, dass ich den Fehler gefunden hab und 
nicht wie gestern Abend den Fehler nur verschieben wollte.

Danke euch allen für die große Hilfe!

Wünsch euch noch einen schönen Sonntag.
Kai

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.