Forum: Mikrocontroller und Digitale Elektronik while( ) >>> mit Bedingungen


von __Son´s B. (bersison)


Lesenswert?

Hallo.
Möchte eine Endlosschleife durch eine Bedingung in der while-Schleife 
unterbrechen. Währe super einfach, ohne Interrupt und if().

Sobald Eingang/PB5 "1" ist, wird die Schleife gestoppt.
while((PINB & (1<<PB5)) == 0) // klappt nicht

umgekehrter Fall PB= 0= Stop
while(PINB & (1<<PB5)) // klappt auch nicht

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


Lesenswert?

__Son´s B. schrieb:
> klappt nicht
> klappt auch nicht
Was "klappt nicht"? Und wie sieht der Rest der Schleife aus? Denn das 
Problem liegt auch hier nicht im geposteten Code...

__Son´s B. schrieb:
> wird die Schleife gestoppt.
Eine Schleife wird nicht "gestoppt", sondern bestenfalls "verlassen"...

: Bearbeitet durch Moderator
von __Son´s B. (bersison)


Angehängte Dateien:

Lesenswert?

while(1) bedeutet, dass die Schleife endlos durch läuft.
Nach meinem Verständniss, bei jeder Schleife prüft, ob while noch "1" 
oder "wahr" ist.
Würde ich hier eine Bedingung einfügen, könnte ich den folgenden 
Schleifendurchlauf stoppen.

von Gerhard (Gast)


Lesenswert?

if () break;
ist auch ne Möglichkeit, eine Schelife zu verlassen.

von Peter II (Gast)


Lesenswert?

>   while (ADCSRA & (1<<ADSC));

hier scheint es ja auch zu gehen, also wird wohl der Fehler woanders 
sein. Eventuell "floatet" ja der Pin.

von __Son´s B. (bersison)


Lesenswert?

Gerhard schrieb:
> if () break;
> ist auch ne Möglichkeit, eine Schelife zu verlassen.
Durch while() scheint mir sehr einfach und schnell, die Schleife zu 
stoppen(!) um es später wieder weiter laufen zu lassen.

von __Son´s B. (bersison)


Lesenswert?

Peter II schrieb:
> Eventuell "floatet" ja der Pin.
???

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

__Son´s B. schrieb:
> Durch while() scheint mir sehr einfach und schnell, die Schleife zu
> stoppen(!) um es später wieder weiter laufen zu lassen.

So funktioniert das aber nicht.

von __Son´s B. (bersison)


Lesenswert?

Ist der Grundgedanke while(Bedingung) eigentlich unrealistisch oder 
praxisfern?

von Michael B. (laberkopp)


Lesenswert?

__Son´s B. schrieb:
> Ist der Grundgedanke while(Bedingung) eigentlich unrealistisch
> oder praxisfern?

Über den Grund wissen wir nichts, weil du erst mit dem Detail kommt was 
dann aus welchen obskuren Gründen auch immer nicht mehr passt.

while(0) wird jedenfalls nie ausgeführt.

: Bearbeitet durch User
von Andreas B. (bitverdreher)


Lesenswert?

Hi,
Du verläßt hier die Hauptschleife.
Was soll er denn Deiner Ansicht danach tun? Dahinter steht ja nichts.
Somit ist es nicht definiert, was er beim Verlassen dieser Schleife 
macht.

Gruß
Andreas

: Bearbeitet durch User
von __Son´s B. (bersison)


Lesenswert?

Andreas B. schrieb:
> Was soll er denn Deiner Ansicht danach tun?
(*) Wenn am PB5 "0" anliegt, läuft die Endlosschleife.
Solang am PB5 eine "1" anliegt, stoppt das folgende Programm, bis PB5 
wieder auf "0" gesetzt ist. Danach (*)

von c. m. (Gast)


Lesenswert?

1
while(1) {
2
  if (bedingung) 
3
    continue;
4
5
  anweisungen;
6
7
}

kennt c "continue" in schleifen?

von Bernhard S. (dl9rdw)


Lesenswert?

Hi, das Programm kommt aber nicht automatisch wieder an der Schleife 
vorbei, nur weil Dein Eingang wieder den Zustand wechselt.

Anweisungen werden Schritt für Schritt abgearbeitet.

Gruß Bernhard

von Gerd (Gast)


Lesenswert?

Ein Video zur while-SChleife:

http://et-tutorials.de/3033/schleifen-mit-while/

von mr. mo (Gast)


Lesenswert?

Was du willst ist folgendes:
1
while(1)
2
{
3
    if(Pin ist LOW)
4
    {
5
    // Hier kommt dein Programm hin
6
    }
7
}

von mr. mo (Gast)


Lesenswert?

Oder:
1
while(1)
2
{
3
    while(Pins ist HIGH);    // Wartet bis der Pin wieder auf LOW liegt
4
5
    // Dein Programm
6
}

von Kaj (Gast)


Lesenswert?

Ein Buch... besorg dir bitte ein C-Buch!
Und nein, selbst wenn du eins haben solltest, dann hast du es nicht 
gelesen, auch wenn du jetzt was anderes behaupten magst.
Auch ausreden wie "Ich hab keine Zeit und/oder kein Geld", sind und 
bleiben ausreden.

von Ulrich F. (Gast)


Lesenswert?

mr. mo schrieb:
> Was du willst ist folgendes:

Eine Endlosschleife?

Grundregel:
Es darf nur eine geben!

von mr. mo (Gast)


Lesenswert?

Ulrich F. schrieb:
> mr. mo schrieb:
>> Was du willst ist folgendes:
>
> Eine Endlosschleife?
>
> Grundregel:
> Es darf nur eine geben!

Hehe :)

Ich bin davon ausgegangen, dass der TO ein wenig mit denkt und natürlich 
nicht meinen Pseudocode eins zu eins in sein Programm kopiert :).

Ist natürlich nur eine Anregung wie man vorgehen könnte, gibt wie sie 
oft viele Möglichkeiten.

von __Son´s B. (bersison)


Lesenswert?

Viele gut gemeinte Beiträge liefen in die falsche Richtung.

Die while()-Funktion ist mir bekannt, der o.g. C-Code zeigt das.
Mir ging es wie Eingangs beschrieben um eine kleine Abkürzung. Dieses 
steht in keinem Fachbuch - daher scheinbar ein "NoGo" oder zu abstrakt.

von Michael B. (laberkopp)


Lesenswert?

__Son´s B. schrieb:
> Die while()-Funktion ist mir bekannt,

while() ist keine Funktion, Klammern hin oder her.

while hat beispielsweise keinen Rückgabewert.

while ist eine Kontrollstruktur, vielleicht noch statement.

Aber keine Funktion.

Und eine if-Schleife auch nicht ...

von Norbert H. (nobi)


Lesenswert?

Ich denke Du willst in einer Funktion warten, bis der PINB5 auf 1 
gegangen ist.

while(!(PINB&0x10));           oder auch
while((PINB & (1<<PB5)) == 0); wie du schreibst sollte eigentlich 
funktionieren.

Hast Du schon mal überprüft, ob der Pin überhaupt als Eingang 
konfiguriert ist?

und lass solche sachen wie "if(..) break" in einer Schleife,
das ist schlechter stiel, und sollte genauso wie continue nicht 
verwendet werden. (MISRA)

sonst nimm
1
int abbruch = FALSE;
2
3
while(!abbruch)
4
{
5
...
6
   if(PINB & (1<<PB5))
7
   {
8
      abbruch = TRUE;
9
   }
10
...
11
}
dabei wird die Schleife zumindest noch zu Ende geführt.

von __Son´s B. (bersison)


Lesenswert?

Norbert H. schrieb:
> Hast Du schon mal überprüft, ob der Pin überhaupt als Eingang
> konfiguriert ist?

DDRB &= ~(1<<PB5);

Norbert H. schrieb:
> und lass solche sachen wie "if(..) break" in einer Schleife,
> das ist schlechter stiel, und sollte genauso wie continue nicht
> verwendet werden. (MISRA)

Dank dir für den Tip!

von Peter II (Gast)


Lesenswert?

Norbert H. schrieb:
> und lass solche sachen wie "if(..) break" in einer Schleife,
> das ist schlechter stiel, und sollte genauso wie continue nicht
> verwendet werden. (MISRA)

wie soll man das denn sonst machen wenn man ein einer liste etwas sucht? 
Goto?
1
while( interator != list.end() ) {
2
   if ( interator == gesucht ) {
3
      break;
4
    }
5
}

was ist daran anzusetzen?

von Ulrich F. (Gast)


Lesenswert?

Ein Seitenausstieg aus einer Schleife, oder auch aus einer Funktion ist 
schlechter Stil.
So wie die Verwendung von GOTO.

Es ist nicht verboten.
Es macht manchmal Sinn, wenn alles andere zu kompliziert wird.

von Peter II (Gast)


Lesenswert?

Ulrich F. schrieb:
> Ein Seitenausstieg aus einer Schleife, oder auch aus einer Funktion ist
> schlechter Stil.

was aber bestimmt nicht die allgemeine Meinung ist.

von Andreas B. (bitverdreher)


Lesenswert?

Peter II schrieb:
[c]
> while( interator != list.end() ) {
>    if ( interator == gesucht ) {
>       break;
>     }
> }
[c/]

>
> was ist daran anzusetzen?

[c]

while( interator != list.end() && !(( interator == gesucht )) ) {

}
[c/]

so würde ich das machen.

Gruß
Andreas

von mr. mo (Gast)


Lesenswert?

Peter II schrieb:
> was ist daran anzusetzen?

Ich frage mich gerade auch wie man das ohne break lösen soll. Evtl. 
lernt man ja was neues.

von mr. mo (Gast)


Lesenswert?

Andreas B. schrieb:
> while( interator != list.end() && !(( interator == gesucht )) )

So einfach das man gar nicht dran denkt. Danke :)

von Mark B. (markbrandis)


Lesenswert?

Peter II schrieb:
> Ulrich F. schrieb:
>> Ein Seitenausstieg aus einer Schleife, oder auch aus einer Funktion ist
>> schlechter Stil.
>
> was aber bestimmt nicht die allgemeine Meinung ist.

Doch. Jedenfalls unter Leuten, die Programmierrichtlinien nicht 
konsequent ignorieren. Davon gibt es freilich eine Menge ;-)

von Der Andere (Gast)


Lesenswert?

mr. mo schrieb:
> Andreas B. schrieb:
>> while( interator != list.end() && !(( interator == gesucht )) )
>
> So einfach das man gar nicht dran denkt. Danke :)

Prima und wenn du dann mehrere Bedingungen hast, und Werte einzelner 
Bedingungen eventuell erst berechnet oder von Unterfunktionen geholt 
werden müssen?
Dann machst du eine while Bedingung, die 1000 Zeichen lang ist?

von Gas_t (Gast)


Lesenswert?

> while( interator != list.end() && !(( interator == gesucht )) )

Das ist deutlich schlechter lesbar und deswegen für mich schlechter 
Stil. Ein if () break; in einer übersichtlichen Funktion ist da deutlich 
besser in meinen Augen.

BTW: Warum einfach wenns auch kompliziert geht:

void Warte(uint16_t WarteMS)
{
  while(WarteMS)                  // Wartezeit
  {
    WarteMS--;                  // runter zählen
    _delay_ms(1);                // 1ms
  }
}

von Andreas B. (bitverdreher)


Lesenswert?

Der Andere schrieb:
> Dann machst du eine while Bedingung, die 1000 Zeichen lang ist?

Ich (und andere auch) habe nicht behauptet, daß man nie mit break aus 
einer Shliefe gehen soll. Man versucht es nur zu vermeiden. In diesem 
Fall war es einfach.

Allerdings kann man auch in Deinem Fall die Bedingung "interator == 
gesucht" innerhalb der Schleife erzeugen. Das muß nicht in der while 
Bedingung geschehen.

Gruß
Andreas

von Mark B. (markbrandis)


Lesenswert?

Der Andere schrieb:
> mr. mo schrieb:
>> Andreas B. schrieb:
>>> while( interator != list.end() && !(( interator == gesucht )) )
>>
>> So einfach das man gar nicht dran denkt. Danke :)
>
> Prima und wenn du dann mehrere Bedingungen hast, und Werte einzelner
> Bedingungen eventuell erst berechnet oder von Unterfunktionen geholt
> werden müssen?
> Dann machst du eine while Bedingung, die 1000 Zeichen lang ist?

Dann fasst man alle möglichen Abbruchbedingungen in einem Flag zusammen, 
welches man im Schleifenkopf abfragt.

von Andreas B. (bitverdreher)


Lesenswert?

Gas_t schrieb:
> Das ist deutlich schlechter lesbar und deswegen für mich schlechter
> Stil. Ein if () break; in einer übersichtlichen Funktion ist da deutlich
> besser in meinen Augen.

Und die break Bedingung dann in der Schleife suchen?
Bei kurzen Schleifen vielleicht...

Kannst es auch so schreiben, wenn Dir das besser gefällt:
while( interator != list.end() &&
    !(( interator == gesucht )) )


Gruß
Andreas

von S. R. (svenska)


Lesenswert?

Mark B. schrieb:
>> Dann machst du eine while Bedingung, die 1000 Zeichen lang ist?
> Dann fasst man alle möglichen Abbruchbedingungen in einem Flag zusammen,
> welches man im Schleifenkopf abfragt.

Andreas B. schrieb:
> Und die break Bedingung dann in der Schleife suchen?

Naja, ob ich jetzt am Ende der Schleife weiß, dass "done == true" ist, 
oder ob irgendwo in der Schleife ein "break" gefeuert hat, macht jetzt 
keinen Unterschied.

Im Übrigen bin ich der Meinung, dass Kommentare bei soetwas hilfreich 
sind.

von B. S. (bestucki)


Lesenswert?

Es gibt da durchaus zwei Ansätze:
1
char * SearchChar(char * String, char Char){
2
  while((*String != '\0) && (*String != Char)){
3
    String++;
4
  }
5
  return (*String == Char) ? String : NULL;
6
}
1
char * SearchChar(char * String, char Char){
2
  while(*String != '\0'){
3
    if(*String == Char){
4
      return String;
5
    }
6
    String++;
7
  }
8
  return NULL;
9
}

Ich bevorzuge die zweite Variante, obwohl das return innerhalb der 
Schleife ist (und somit einem break/goto entspricht) und ich sogar zwei 
davon habe.

Ich handhabe das meistens so:
Wenn es einfach und leserlich möglich ist, verwende ich die Bedingung im 
Schleifenkopf. Ist es hässlich, z.B. Flags über mehrere Ebenen, 
spendiere ich auch mal ein goto, das direkt hinter die Schleife springt. 
Zugegeben, dieser Fall tritt sehr selten auf, zumal ich für jeden 
Scheiss eine Funktion schreibe und dann meist ein return in der Schleife 
steht. Wenn ansonsten nichts in der Funktion gemacht wird (also reines 
Suchen), ist ein return in und eines nach der Schleife meiner Meinung 
nach kein schlechter Stil.

@TO: Warten in einer while-Schleife ist meist eine schlechte Idee, da 
dadurch der Controller auf unbestimmte Zeit blockiert ist. Besser ist 
es, nur auf eine Änderung der Eingangspins zu reagieren (pollen). Wenn 
die Bedingung nicht erfüllt ist, macht der Controller in der 
Zwischenzeit etwas anderes und prüft später nochmals.

von Dussel (Gast)


Lesenswert?

Ulrich F. schrieb:
> Ein Seitenausstieg aus einer Schleife, oder auch aus einer Funktion ist
> schlechter Stil.
Finde ich auch nicht. Ein
1
if(Fehler aufgetreten)
2
    return 1;
finde ich schöner und sinnvoller als
1
if(Kein Fehler aufgetreten)
2
{
3
    Zeug();
4
    Mehr_Zeug();
5
    ...
6
    Anderes_Zeug();
7
    Fehlercode=0;
8
}
9
else  // Wo? welche Fehler war das? Achso, zwei Bildschirmseiten höher
10
{
11
    Fehlercode=-1;
12
}
13
return Fehlercode;
oder
1
if(Fehler aufgetreten)
2
    return -1;
3
else   //Sinnlos
4
{
5
    ...
6
}
Oder wie würdest du in dem Fall vorgehen?

von Mark B. (markbrandis)


Lesenswert?

Dussel schrieb:
> else  // Wo? welche Fehler war das? Achso, zwei Bildschirmseiten höher

Dann liegt der Fehler aber woanders: Eine Funktion, die über zwei 
Bildschirmseiten geht, ist mit 99% Wahrscheinlichkeit einfach zu groß 
und schlecht designed.

"A function shall do one thing, and only one thing - and do it well".

von Ulrich F. (Gast)


Lesenswert?

Dussel schrieb:
> Oder wie würdest du in dem Fall vorgehen?
In dem Fall? KA, ist mir auch eigentlich recht egal...

Eben habe ich schon versucht zu sagen, dass es Trotz schlechtem Stil 
manchmal die einfachste Möglichkeit ist.

Bedenke:
Wer einmal begriffen hat, wie ein Hammer funktioniert, für den sieht 
plötzlich jedes Problem wie ein Nagel aus.


Alles, was die Lesbarkeit beeinträchtigt, ist schlechter Stil.
Und in der Regel gilt: Je mehr Ausstiegspunkte, desto unübersichtlicher.

von Speckbert (Gast)


Lesenswert?

Norbert H. schrieb:
> und lass solche sachen wie "if(..) break" in einer Schleife,
> das ist schlechter stiel, und sollte genauso wie continue nicht
> verwendet werden. (MISRA)

Eigentlich sagt MISRA , dass man pro Schleife maximal ein "break" 
verwenden soll (siehe MISRA 2004, Rule 14.6 bzw. Misra 2012, Rule 15.4). 
Ich verwende "break" ganz gerne um in kritischen Situationen sofort aus 
einer Schleife zu springen. Für die reguläre Iteration nutze ich aber 
auch die Prüfung im Schleifenkopf/-fuß.

Jedenfalls würde ich die Verwendung von "break" nicht generell 
verteufeln, es gibt durchaus Situationen wo es ganz nützlich sein kann 
und die Les- und Wartbarkeit des Codes erhöht.

von Der Andere (Gast)


Lesenswert?

Mark B. schrieb:
> Dann fasst man alle möglichen Abbruchbedingungen in einem Flag zusammen,
> welches man im Schleifenkopf abfragt.

Das ist dann aber eine andere Funktionalität, weil dann Code ausgeführt 
wird, der beim ersten brake nicht mehr ausgeführt worden wäre.
Einfaches Beispeil, es gehen mehrere Werte in eine Berechnung ein, aber 
einer davon ist 0 und durch den soll geteilt werden.
Also müsste man jede weitere Berechnung mit einem if (x !0 0) klammern.

Aber programmiert ruhig "stilistisch sauber" ich konzentriere mich auf 
fachlich korrekt und möglichst bugfrei :-)

von B. S. (bestucki)


Lesenswert?

Ulrich F. schrieb:
> Alles, was die Lesbarkeit beeinträchtigt, ist schlechter Stil.
> Und in der Regel gilt: Je mehr Ausstiegspunkte, desto unübersichtlicher.

Bedingt. Folgendes Beispiel halte ich für leserlich:
1
int foo( /* ... */ ){
2
  if(BedingungA){
3
    return FehlerA;
4
  }
5
  if(BedingungB){
6
    return FehlerB;
7
  }
8
  if(BedingungC){
9
    return FehlerC;
10
  }
11
  
12
  /* eigentliche Funktion */
13
  
14
  return Result;
15
}

Aber grundsätzlich gebe ich dir Recht. Funktionen, die über zwei 
Bildschirmseiten ragen und mit returns gespickt sind, sind nicht 
wirklich übersichtlich. Was hälst du von Exceptions? Das sind im Prinzip 
auch returns, einfach ein wenig anders.

von asdf (Gast)


Lesenswert?

Der Andere schrieb:
> der beim ersten brake

Du willst nicht bremsen, sondern abbrechen :-)

von Ulrich F. (Gast)


Lesenswert?

be s. schrieb:
> Was hälst du von Exceptions?

In meiner kleinen AVR Welt?
Nix!


Ansonsten bin ich da ein Freund von und setze sie gerne ein.

von B. S. (bestucki)


Lesenswert?

Ulrich F. schrieb:
> be s. schrieb:
>> Was hälst du von Exceptions?
>
> In meiner kleinen AVR Welt?
> Nix!
>
> Ansonsten bin ich da ein Freund von und setze sie gerne ein.

Sehe ich genau so.

von Michael B. (laberkopp)


Lesenswert?

mr. mo schrieb:
> Andreas B. schrieb:
>> while( interator != list.end() && !(( interator == gesucht )) )
>
> So einfach das man gar nicht dran denkt. Danke :)

Aber unsinnig.

Normalerweise will man ja mit dem gefundenen Element etwas machen (und 
das kann man nicht wenn es nicht gefunden wurde).
1
 while( interator != list.end() ) {
2
    if ( interator == gesucht ) {
3
       do_something(iterator) ;
4
       break;
5
     }
6
 }
geht dann nämlich schon nicht mehr mit Andreas seinem "Pattern".

: Bearbeitet durch User
von Daniel A. (daniel-a)


Lesenswert?

Michael B. schrieb:
> mr. mo schrieb:
>> Andreas B. schrieb:
>>> while( interator != list.end() && !(( interator == gesucht )) )
>>
>> So einfach das man gar nicht dran denkt. Danke :)
>
> Aber unsinnig.
...
> geht dann nämlich schon nicht mehr mit Andreas seinem "Pattern".

Das ist nicht das Problem mit dem Pattern. Abgesehen davon, dass 
list.end() C++ vermuten lässt, wobei std::find vorzuziehen währe, fällt 
anscheinend niemandem auf, dass man den Iterator in der Schleife erhöhen 
muss oder sonstwie auf das nächste Element setzen sollte.

In C könnte das so aussehen, wenn man es richtig macht:
1
#include <stdio.h>
2
3
int main(){
4
5
  int gesucht = 2;
6
  int list[] = {1,2,3};
7
  int*const list_end = list + sizeof(list) / sizeof(*list);
8
9
  int* it;
10
  for( it=list; it<list_end; it++ )
11
    if( *it == gesucht )
12
      break;
13
14
  if( it == list_end ){
15
    printf("Not found\n");
16
  }else{
17
    printf("Found %d at index %u\n",*it,(unsigned)(it-list));
18
  }
19
20
  return 0;
21
}

von S. R. (svenska)


Lesenswert?

Ich finde folgende Lösung deutlich angenehmer zu lesen. Kurz und 
knackig, und der Compiler warnt mich, wenn ich das Array überrenne.
1
#define LIST_SIZE 3
2
int list[LIST_SIZE] = {1, 2, 3};
3
4
for(size_t i = 0; i < LIST_SIZE; i++) {
5
  if(list[i] == gesucht) {
6
    /* tu was */
7
    break;
8
  }
9
}

Wenn im "nicht gefunden"-Fall noch eine spezielle Aktion dazu kommt, 
oder wenn ich wissen will, wie oft ich das Element gefunden habe, dann 
kommt ein Flag (oder Zähler) dazu.

von Ralph S. (jjflash)


Lesenswert?

... wegen des originalen Problems des digitalen Eingangs auf PB5.

Jetzt kenne ich die Schaltung der Hardware nicht, aber lt. Programm 
solltest du entweder einen externen Pop-Up Widerstand an PB5 haben, oder 
den internen Pop-Up Widerstand einschalten.

mit
1
DDRB &= ~(1 << PB5);

schaltest du PB5 als Eingang, aber dieser Eingang hängt in der Luft und 
hat keinen definierten Zustand.

mit
1
DDRB &= ~(1 << PB5);
2
PORTB |= (1 << PB5);

schaltest du den internen Pop-Up Widerstand ein .

Gruß,
Ralph

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ralph S. schrieb:
> internen Pop-Up Widerstand

Wo nennt man das so? Üblich ist "pull-up".

von DSausW (Gast)


Lesenswert?

> Wo nennt man das so? Üblich ist "pull-up".

Bei der Kirmes-Elektrik.
Das sind die Widerstände, die kurzzeitig unqualifiziert
überlastet werden und Dir entgegenkommen-
aber, wir schweifen ab.

von __Son´s B. (bersison)


Lesenswert?

Ralph S. schrieb:
> ... wegen des originalen Problems des digitalen Eingangs auf PB5.
So sieht der Kopfbereich aus.
Hier soll das Programm stoppen, wenn PB5 auf Vcc liegt.

int main(void)
{
  DDRB &= ~(1<<PB5);  // Eingang, kein pull-up, via.100k auf Gnd

  while(1)
  {

    //while((PINB & (1<<PB5))==0);  //Versuch1, klappt nicht
    //while(!(PINB & (1<<PB5))==1);  //Versuch2, Stop, wenn PB5 low
    //while(!(PINB & (1<<PB5)));  //Versuch3, klappt nicht
    //while((PINB & (1<<PB5))!=1);  //Versuch4, klappt nicht
    //while((PINB & (1<<PB5))!=0);  //Versuch5, reagiert nicht
    //while((PINB & (1<<PB5))==1);  //Versuch6, Stop, wenn PB5 low
    while(PINB & (1<<PB5));    //Versuch7, Stop, wenn PB5 low
    ...

Ich verstehe nicht, dass die die Prüfung auf 0 (Versuch 6+7) 
funktioniert, die Invertierung aber nicht.
Scheint sich um ein generelles Verständnisproblem zu handeln - aber wo 
steck der Fehler?

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


Lesenswert?

__Son´s B. schrieb:
> aber wo steck der Fehler?
Was kommt bei PINB & (1<<PB5) raus?
1) wenn der Pin high ist: 0b00100000 = 0x20 = 32
und es gilt !0b00100000 = 0b00000000 = 0x00 = 0
2) wenn der Pin low ist:  0b00000000 = 0x00 = 0
hier gilt   !0b00000000 = 0b00000001 = 0x01 = 1

So, und jetzt trägst du das einfach mal in deine Abfragen ein:
Bei Eingang high
while(32==0)
while(0==1)
while(0)
while(32!=1)
while(32!=0)
while(32==1)
while(32)

Bei Eingang low
while(0==0)
while(0==1)
while(1)
while(0!=1)
while(0!=0)
while(0==1)
while(0)

Und dann überlegst du, ob die jeweilige Bedingung 0 (=false) ergibt. 
Falls die Bedingung falsch ist oder 0 ergibt, dann wird die Schleife 
abgebrochen. Ist sie ungleich 0 oder wahr, dann wird die Schleife 
ausgeführt. So einfach ist das. Da muss man nicht wirr herumstochern...


EDIT: Korrigiert entsprechend nachfolgendem Post...  :-/

: Bearbeitet durch Moderator
von Daniel A. (daniel-a)


Lesenswert?

Lothar M. schrieb:
> es gilt !0b00100000 = 0b11011111 = 0xdf = 223

Es gibt da einen kleinen Unterschied zwischen dem Logischen und dem 
Binären nicht, und im code wurde das Logische verwendet. Also 
!0b00100000 = 0b00000000 = 0x00 = 0 und !0b00000000 = 0b00000001 = 0x01 
= 1.
Das Zeichen für Binär nicht ist '~'.

von __Son´s B. (bersison)


Lesenswert?

Lothar M. schrieb:
> So einfach ist das.
DANKE!

Lothar M. schrieb:
> Da muss man nicht wirr herumstochern...
Verzweifelungsaktivismus ;-/

von __Son´s B. (bersison)


Lesenswert?

Lothar M. schrieb:
> Was kommt bei PINB & (1<<PB5) raus?
> 1) wenn der Pin high ist: 0b00100000 = 0x20 = 32
Folgendes funktioniert leider auch nicht. Habe noch kein Ausgabedisplay 
um interne Zustände sichtbar zu machen.
while((PINB&(1<<PB5))==32); // PB1=1 soll Schleife stoppen

Wie kann ich sicher sein, dass bei
PINB&(1<<PB5) = 0b00100000 = 32
alle Bits ausser PB5, garantiert 0 sind?

Müsste nicht erst einmal der PINB komplet ausgelesen und im Anschluss 
verglichen werden?

von DirkB (Gast)


Lesenswert?

__Son´s B. schrieb:
> while((PINB&(1<<PB5))==32); // PB1=1 soll Schleife stoppen

Da stimmt was nicht:

Wenn der Kommentar stimmt, dann

while((PINB&(1<<PB1))==0); // PB1=1 soll Schleife stoppen


Wenn der Code stimmt, dann

while((PINB&(1<<PB5))==32); / // PB5=0 soll Schleife stoppen

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


Lesenswert?

__Son´s B. schrieb:
> Wie kann ich sicher sein, dass bei
> PINB&(1<<PB5) = 0b00100000 = 32
> alle Bits ausser PB5, garantiert 0 sind?
Gar nicht, das ist für diese Abfrage auch uninteressant. Hier wird nur 
das Bit PB5 betrachtet (der Profi sagt "verUNDet" oder "ausmaskiert").
Wenn du abfragen willst, ob der gesamte Port genau den Wert 0b00100000 
hat, dann musst du so schreiben:
if (PINB = (1<<PB5)) ...

> Wie kann ich sicher sein, dass bei
> PINB&(1<<PB5) = 0b00100000 = 32
> alle Bits ausser PB5, garantiert 0 sind?
Mal angenommen, der PB wäre real 0b10101010, dann bleibt durch die UND 
Funktion mit (1<<PB5) also 0b00100000 noch genau 0b00100000 übrig.

__Son´s B. schrieb:
> while((PINB&(1<<PB5))==32); // PB1=1 soll Schleife stoppen
Der Compiler wertet nur den Code aus, nicht die Kommentare!
Im Code wird Pin 5 am Eingangsport B abgefragt...

: Bearbeitet durch Moderator
von Daniel A. (daniel-a)


Lesenswert?

__Son´s B. schrieb:
> Wie kann ich sicher sein, dass bei
> PINB&(1<<PB5) = 0b00100000 = 32
> alle Bits ausser PB5, garantiert 0 sind?

Meinst du auf das Resultat von PINB & (1<<PB5) bezogen?
PB5 ist 5. 1<<PB5 ist 32 ist 0b00100000. Ein einzelnes '&' zeichen ist 
binär und. Es bleibt also so oder so nur das Bit von PB5 übrig:

PINB    a b c d e f g h
1<<PB5  0 0 1 0 0 0 0 0
-----------------------
Result  0 0 c 0 0 0 0 0

Falls du aber wissen willst, ob keines der Bits von PINB ohne PB5 
gesetzt ist, dann wäre dass so: !( PINB & ~(1<<PB5) )

PINB       a b c d e f g h
~(1<<PB5)  1 1 0 1 1 1 1 1
---------------------------
           a b 0 d e f g h

Lothar M. schrieb:
> Wenn du abfragen willst, ob der gesamte Port genau den Wert 0b00100000
> hat, dann musst du so schreiben:
> if (PINB = (1<<PB5))

c'mon, da müssen 2 gleich hin: if (PINB == (1<<PB5))

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


Lesenswert?

Daniel A. schrieb:
> c'mon, da müssen 2 gleich hin: if (PINB == (1<<PB5))
Ach schlags kaputt. Ich mache gerade VHDL, da reicht eines...  ;-)

von __Son´s B. (bersison)


Lesenswert?

Daniel A. schrieb:
> Meinst du auf das Resultat von PINB & (1<<PB5) bezogen?
Ja, es geht mir nur(!) um den Status von PB5! Daher ist die Maskierung 
richtig.

Ich möchte folgendes;
wenn an PB5 ein high anliegt, soll die Schleife durch while(...); 
gestoppt/angehalten werden. Aber nur dann!

DDRB &= ~(1<<PB5);  // ATTiny85

--Bsp.1--
Wenn also 0b0010 0000 anliegt, sollte der Vergleich
((PINB&(1<<PB5))==32)
"wahr", oder "1" sein!?

--Bsp.2--
Genau so, wenn 0b0010 0000 anliegt, müsste der Vergleich
((PINB&(1<<PB5))!=0)
gneauso "wahr" oder "1" sein!?

Warum klappt das nicht bei mir?

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


Lesenswert?

__Son´s B. schrieb:
> soll die Schleife durch while(...); gestoppt/angehalten werden.
Eine kleine Wiederholung: eine Schleife wird nicht "angehalten" oder 
"gestoppt". Sie wird "beendet", denn der Prozessor läuft mit Vollgas 
weiter...

> Wenn also 0b0010 0000 anliegt, sollte der Vergleich
> ((PINB&(1<<PB5))==32)
> "wahr", oder "1" sein!?
Richtig. Und dann läuft die Schleife noch einmal durch. Es reicht aber 
auch aus, auf
if  (PINB&(1<<PB5)) ...
abzufragen, denn dann ist das bei einem High am Pin B5 gleich wie
if (32) ...
und 32 ist ungleich 0 und damit wird die Schleife nochmal durchlaufen.

> Warum klappt das nicht bei mir?
Sehr wahrscheinlich, weil du noch was anderes falsch machst. Gern werden 
z.B. Taster mit Pullups nach GND geschaltet, und dann ist der Eingang 
natürlich '0', wenn die Taste gedrückt ist....

von J.-u. G. (juwe)


Lesenswert?

Was spricht eigentlich gegen die Verwendung der Makros "bit_is_set" bzw. 
"bit_is_clear"?
1
bit_is_set(PINB, PB5)

Könnte doch einige Verwirrung vermeiden. Und wenn man partout den 
Programmablauf unterbrechen will gibt es "loop_until_bit_is_set" bzw. 
"loop_until_bit_is_set".

von DirkB (Gast)


Lesenswert?

while heißt auf deutsch solange.

Die Schleife läuft solange die Bedingung wahr ist.

von __Son´s B. (bersison)


Lesenswert?

Lothar M. schrieb:
> Richtig. Und dann läuft die Schleife noch einmal durch. Es reicht aber
> auch aus, auf
> if  (PINB&(1<<PB5)) ...
Genau hier setzt mein Verstehen aus, diese Befehlt, egal ob if() oder 
while() funktioniert bei mir nicht. Egal ob 1 oder 0 an PB5, Schleife 
wird nicht ausgeführt.

Lothar M. schrieb:
> Sehr wahrscheinlich, weil du noch was anderes falsch machst. Gern werden
> z.B. Taster mit Pullups nach GND geschaltet, und dann ist der Eingang
> natürlich '0', wenn die Taste gedrückt ist....
Kein Pull-up eingeschaltet.
Externer Pull-down über 100k auf Gnd!

J.-u. G. schrieb:
> bit_is_set(PINB, PB5)
Danke, aber ich möchte erst einmal die Bit-Manipulation und deren 
Vergleiche vollständig verstehen.

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


Lesenswert?

__Son´s B. schrieb:
> Kein Pull-up eingeschaltet.
> Externer Pull-down über 100k auf Gnd!
Mal davon abgesehen, dass mir dazu nur "Warum" einfällt: was sagt das 
Messgerät?

von __Son´s B. (bersison)


Lesenswert?

Lothar M. schrieb:
> was sagt das
> Messgerät?
Bei externem 10k Pull-down, "0V", solang kein Vcc anliegt.

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.