mikrocontroller.net

Forum: Compiler & IDEs Probleme mit while


Autor: Matthias H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,
ich habe Probleme mit folgendem Stück Code:

...
volatile uint16_t zCounter

...

ISR(INT0_vect)
{
  if (PINC & (1 << PINC0)) zCounter++;
..
}

..

int main (void)
{
  uint16_t Counter;

..
  Counter = 300;
  zCounter = 0;
 sei();
  PORTC |= (1 << PC0);

  while (zCounter < Counter);

  PORTC &= ~(1 << PC0);
  cli();
..
}

Die while- Schleife wird einfach übergangen. Wenn ich da "while 
(zCounter != Counter);" schreibe, klappt alles. Im INT0-Eingang befindet 
sich ein Encoder, dessen Signal ich zählen möchte. An PC0 hängt der 
Motor. Ich hoffe, der Code-Auszug reicht, um das Problem darzustellen.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sieht so aus, als ob du den Code hier eingetippt hast. Das ist keine 
gute Idee, poste lieber den echten Code. Da ist vermutlich ein 
Flüchtigkeitsfehler drin, der hier nicht drin ist.

Autor: Matthias H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das Problem ist, dass ich mit einem anderen Rechner im Netz bin. Hab 
leider im Moment keine Möglichkeit, den Code zu kopieren.

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, dass der Compiler die While-Schleife einfach mal 
wegoptimiert?
Wobei das "volatile" das je verhindern sollte.
Definiere "Counter" doch auch mal volatile.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da ist nichts wegzuoptimieren, es muss auch ohne volatile bei Counter
funktionieren.

Paranoia: du benutzt nicht zufälliger Weise WinAVR-20080402?

Autor: Matthias H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
genau den benutze ich. Gibt es da Probleme?

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie ist der INT0 konfiguriert, als Flanken- oder als Level-Interrupt?
Was veranlasst dich zur Vermutung, dass die While-Schleife
übersprungen wird?

Meine Vermutung: INT0 ist als Level-Interrupt konfiguriert, und der
Low-Pegel am Interrupteingang dauert so lange an, dass der
Interrupthandler währenddessen mindestens 300mal direkt hintereinander
abgearbeitet werden kann. Weil das schneller geht, als dein Auge es
erfassen kann, denkst du, die While-Schleife wurde übersprungen.

Warum verhält sich das Programm bei "while(zCounter != Counter);"
anders?

Da zwischen zwei Interrupthandleraufrufen genau eine Instruktion der
main-Funktion ausgeführt wird, wird zwischen zwei Prüfungen der
While-Bedingung der Counter mehrmals inkrementiert. Je nach Timing
kann es deswegen passieren, dass in einem Schleifendurchlauf bspw. der
Wert 299 gesehen wird, im nächsten Durchlauf steht er aber schon auf
einem Wert >300, so dass die Schleife nicht abbricht. Vielleicht tut
sie dies aber, nachdem Counter ein oder mehrere Male bei 65535
überlaufen ist und die While-Abfrage irgendwann doch bei exakt 300
stattfindet. Bis dahin hat sich die Schleife aber zigtausende Male
gedreht, so dass dein Auge die Verzögerung tatsächlich wahrnimmt.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>genau den benutze ich. Gibt es da Probleme?

Wurde wegen Bugs gestrichen.
Nimm erstmal den 200705xx.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
holger wrote:
>>genau den benutze ich. Gibt es da Probleme?
>
> Wurde wegen Bugs gestrichen.
> Nimm erstmal den 200705xx.

Quatsch. Nimm einfach einen aktuelleren:
http://sourceforge.net/project/showfiles.php?group_id=68108

Die neueste Version ist vom 12.5.

Autor: Matthias H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oh Mann, richtig. Ich hab mich beim MCUCR vertan und den Low Level als 
Interrupt definiert. So ist das, wenn man den nur als Hex-Zahl schreibt. 
Dann wird die Fehlersuche schwer. Vielen Dank für den Tipp, yalu. Das 
Kann dann natürlich nichts werden, wenn ich nur den Home-Puls des 
Encoders nutze und er die meiste Zeit Low ist.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Upgrade trotzdem das WinAVR.  Die Version 20080402 hatte einen richtig
üblen Bug.  Einer der Patches für den Xmega hatte unbeabsichtigterweise
einen Einfluss auf nicht-Xmega-CPUs und hat bei diesen komplett falsche
Sprünge generiert.

Autor: G. L. (sprintersb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein Fehler ist noch drin:
while (zCounter < Counter);

Das sind 16-Bit-Werte. Da AVR 16 Bits nicht atomar laden kann, kann es 
sein, daß zwischen dem Einlesen der einzelnen Bytes eine IRQ getriggert 
wird. Dann würde das eingelesene zCounter aus zwei Teilen bestehen: 
einem alten Byte von vor Ausführung der ISR, das schon in einem Register 
steht, und einem neuen Byte, das durch die ISR verändert wurde.

Daher muss atomar auf zCounter zugegriffen werden, um sporadische 
Fehlfunktion zu vermeiden:
uint16_t z;

do
{
   cli();
   z = zCounter;
   sei();
} while (z < Counter);

Autor: Matthias H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Georg-johann Lay
 es sind zwar jetzt noch keine Probleme aufgetreten, aber ich werde dies 
ändern. Klingt auch einleuchtend.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.