Forum: Mikrocontroller und Digitale Elektronik logische Verknüpfung als Bedingung für Abbruch while-Schleife (Atmega / Atmel Studio 7)


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Zi P. (zippo)


Lesenswert?

Hallo,

ich stehe momentan auf dem Schlauch und auch nach 3h habe ich meinen 
Fehler nicht gefunden vielleicht kann ja einer von euch mir sagen was 
ich falsch mache.

Ich möchte eine while-Schleife abbrechen wenn entweder PinC0 gedrückt 
wird oder die Schleife 2 mal durchlaufen wurde. Wenn ich das Ganze auf 
dem Atmega88 habe, wird aber nur wenn der Taster losgelassen wird (mit 
internen Pullup eingeschaltet daher die Negation) die Schleife 
verlassen. Die Durchläufe interessieren mein Progamm nicht.
Ich habe schon verschiedene Klammern gesetzt aber keine brachte mich zum 
Erfolg.

Installiert ist das Studio 7.0 mit AVR GCC

1
  MAX7219_On();
2
  uint8_t i = 0;  
3
  
4
  while ( !(PINC & (1 << PC0)) && (i < 2) ){    
5
    _delay_ms(500);
6
    MAX7219_shutdown();
7
    _delay_ms(200);
8
    MAX7219_On();
9
    i++;}
10
11
Beste Grüße

: Bearbeitet durch User
von Christian M. (christian_m280)


Lesenswert?

Zi P. schrieb:
> oder

Zi P. schrieb:
> &&

Merkst es?

Gruss Chregu

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Zi P. schrieb:
> Ich möchte eine while-Schleife abbrechen wenn entweder PinC0 oder die
> Schleife 2 mal durchlaufen wurde.

> while ( !(PINC & (1 << PC0)) && (i < 2) ){

allgemein:
while Bedingung-zutrifft
   do action

--> versuch es mal mit der logischen "oder" Verknüpfung || anstelle 
eines "und" &&

von Harald K. (kirnbichler)


Lesenswert?

Zi P. schrieb:
> while ( !(PINC & (1 << PC0)) && (i < 2) )

Die Schleife wird solange durchlaufen, wie PC0 nicht gesetzt ist und i 
kleiner ist als 2.

Zi P. schrieb:
> Ich möchte eine while-Schleife abbrechen wenn entweder PinC0 oder die
> Schleife 2 mal durchlaufen wurde.

Etwas unklar ist, was mit "entweder PinC0" gemeint ist, da fehlt ein 
Satzteil.

von Zi P. (zippo)


Lesenswert?

Hallo,

ich bin gerade außer Haus und kann nicht am Rechner sogleich testen, 
aber ich will doch eine "while" Schleife unterbrechen und das geht doch 
nur wenn die Bedingung NULL wird -> while (0)

Wenn ich jetzt wie vorschlagen die ODER-Verknüpung nehme heißt es doch 
-> while (0 || 1)
Und das würde doch keinen Ausbruch aus der Schleife erzeugen außer ich 
lasse beide Bedingungen zu NULL werden.

Bitte korrigiert mich wenn ich falsch liege, ich bin erste gerade dabei 
mich wieder in AVR und GCC einzuarbeiten... ging in den Jahren einiges 
an Wissen den Berg hinunter.

von Zi P. (zippo)


Lesenswert?

Harald K. schrieb:
> Zi P. schrieb:
>> while ( !(PINC & (1 << PC0)) && (i < 2) )
>
> Die Schleife wird solange durchlaufen, wie PC0 nicht gesetzt ist und i
> kleiner ist als 2.


Danke für den Hinweis, ist korrigiert.

Undn nein genau wie du es beschreibst sollte es meiner Meinung nach auch 
laufen ... tut es nur nicht. i > 2 erzeugt keinen Abbruch

von Harald K. (kirnbichler)


Lesenswert?

Man könnte den Kram natürlich auch anders formulieren:
1
  uint8_t i;  
2
  MAX7219_On();
3
4
  for (i = 0; i < 2; i++)
5
  {
6
    if (PINC & (1 << PC0))
7
      break;
8
9
    _delay_ms(500);
10
11
    MAX7219_shutdown();
12
13
    _delay_ms(200);
14
15
    MAX7219_On();
16
  }

aber das, was da eingangs steht, sollte auch funktionieren.

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

du könntest dir ja auch einfach mal die Werte ausgeben lassen

von Oliver S. (oliverso)


Lesenswert?

Zi P. schrieb:
> wird aber nur wenn der Taster losgelassen wird (mit
> internen Pullup eingeschaltet daher die Negation) die Schleife
> verlassen. Die Durchläufe interessieren mein Progamm nicht.

Woher weißt du das?

Oliver

von Peter D. (peda)


Lesenswert?

Zi P. schrieb:
> Wenn ich das Ganze auf
> dem Atmega88 habe, wird aber nur wenn der Taster losgelassen wird (mit
> internen Pullup eingeschaltet daher die Negation) die Schleife
> verlassen.

Dann macht das Programm ja genau das, was Du hingeschrieben hast.

Zi P. schrieb:
> Die Durchläufe interessieren mein Progamm nicht.

Sicher?
Dazu muß aber die Taste permanent gedrückt sein.

von Pilot P. (klatschnass)


Lesenswert?

In C hat der Operator ! laut Doku eine höhere Priorität als &&.
In Python hat dein Konstrukt funktioniert.

Probier's mal mit:
 while ( (!(PINC & (1 << PC0))) && (i < 2) ){

Gruß klatschnass

Edit: Ok, das war Quatsch.
Der while-Ausdruck funktioniert so, wie er ist.
Das Problem liegt wohl eher daran, dass die Taste in der delay-Pause 
gedrückt und wieder losgelassen wird. Das bekommt die Schleife dann 
natürlich nicht mit. Deswegen hattest du auch den Eindruck, dass du die 
Taste langsam loslassen musst, damit es funktioniert. Da musst du wohl 
statt der Pause mit Interrupts arbeiten.

: Bearbeitet durch User
von Spess53 .. (hardygroeger)


Lesenswert?

Hi

> Da musst du wohl statt der Pause mit Interrupts arbeiten.

Aber Timer-Interrupts.

MfG Spess

von N. M. (mani)


Lesenswert?

Pilot P. schrieb:
> Da musst du wohl statt der Pause mit Interrupts arbeiten.

Oder einfach mit freilaufendem Timer und einer kleinen Statemachine.

Pilot P. schrieb:
> Das Problem liegt wohl eher daran, dass die Taste in der delay-Pause
> gedrückt und wieder losgelassen wird. Das bekommt die Schleife dann
> natürlich nicht mit.

Ja, das ist natürlich Quatsch. Da muss man ja jede nach dem bis zu 700ms 
den Taster drücken.

von Zi P. (zippo)


Lesenswert?

Also der Code funktioniert so wie er soll, mein Problem lag eine Zeile 
weiter. Dort habe ich im prinzip ein Signal erhalten, deswegen gab es 
immer wieder einen Rücksprung in die while Schleife.

Danke für eure Unterstützung.

Und die 700ms machen für mich schon Sinn da ich erst nach kurzem halten 
der Taste in ein Menü gelangen möchte.

Grüße

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Zi P. schrieb:
> mein Problem lag eine Zeile
> weiter. Dort habe ich im prinzip ein Signal erhalten, deswegen gab es
> immer wieder einen Rücksprung in die while Schleife.

dein oben gezeigter Code-Schnipsel gibt das aber nicht wieder.
Wie geht denn ein "_Rücksprung_ in eine While-Schleife?"
Echt? Sprung in eine Schleife hinein???? STAUN

von Hugo H. (hugo_hu)


Lesenswert?

Wegstaben V. schrieb:
> Wie geht denn ein "_Rücksprung_ in eine While-Schleife?"

Kennst Du keine Funktionsaufrufe?
1
MAX7219_...();

scheinen SPI-Kommunikation "durchzuführen" ...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Hugo H. schrieb:
> Wegstaben V. schrieb:
>> Wie geht denn ein "Rücksprung in eine While-Schleife?"
> Kennst Du keine Funktionsaufrufe?
> MAX7219_...();
> scheinen SPI-Kommunikation "durchzuführen" ...
Und wieso würde da dann irgendwas "springen"?
Die Funktionen geben ja nicht mal einen Wert zurück.

Zi P. schrieb:
> Und die 700ms machen für mich schon Sinn
Für mich sind die 700ms delay() ein Programmfehler, weil sie nur nutzlos 
Rechenzeit vergeuden.

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

Wegstaben V. schrieb:
> Echt? Sprung in eine Schleife hinein???? STAUN
da gibt es schon Wege

von Hugo H. (hugo_hu)


Lesenswert?

Lothar M. schrieb:
> Die Funktionen geben ja nicht mal einen Wert zurück.

Werden aber aufgerufen und kehren wohl auch wieder zum Statement nach 
dem Aufruf zurück.

von Stefan F. (Gast)


Lesenswert?

Der Fehler ist (wie so oft) nicht im gezeigten Stück Code. Das heißt, du 
konzentrierst dich auf die falsche Stelle.

Denn folgendes Testprogramm läuft auf meinem PC nämlich tadellos:
1
#include <stdio.h>
2
#include <stdint.h>
3
4
void _delay_ms(int ms)
5
{
6
    printf("_delay_ms(%d)\n", ms);
7
}
8
9
void MAX7219_On()
10
{
11
    puts("MAX7219_On()");
12
}
13
14
void MAX7219_shutdown()
15
{
16
    puts("MAX7219_shutdown()");
17
}
18
19
#define PC0 0
20
#define PINC 0
21
22
int main()
23
{
24
    MAX7219_On();
25
    uint8_t i = 0;
26
27
    while ( !(PINC & (1 << PC0)) && (i < 2) )
28
    {
29
      _delay_ms(500);
30
      MAX7219_shutdown();
31
      _delay_ms(200);
32
      MAX7219_On();
33
      i++;
34
    }
35
}

Ausgabe:
1
MAX7219_On()
2
_delay_ms(500)
3
MAX7219_shutdown()
4
_delay_ms(200)
5
MAX7219_On()
6
_delay_ms(500)
7
MAX7219_shutdown()
8
_delay_ms(200)
9
MAX7219_On()

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.