Forum: Compiler & IDEs Anfängerfrage: etwas machen wenn 2 ereignisse eingetreten sind


von Rocco L. (kaufparkangucker)


Lesenswert?

Hallo,

wie kann man follgendes schreiben:

fals am PINC1 ein high anliegt und an PINB1 ein low soll PORTD1 high 
sein

mein kläglicher Versuch sieht so aus:
if((PINC & (1 << PINC1)) && (PINB & !(1 << PINB1))){ PORTD |= (1<<PD1);

Danke für die Hilfe

vG Rocco

von cde (Gast)


Lesenswert?

Sieht ganz gut aus, aber:
1
(PINB & !(1 << PINB1))
muss
1
!(PINB & (1 << PINB1))
heissen. Außerdem fehlt ein "}" (bzw. das "{" ist zu viel), die 
Formatierung allgemein ist verbesserungswürdig.

von Karl H. (kbuchegg)


Lesenswert?

Rocco L. schrieb:
> Hallo,
>
> wie kann man follgendes schreiben:
>
> fals am PINC1 ein high anliegt und an PINB1 ein low soll PORTD1 high
> sein
>
> mein kläglicher Versuch sieht so aus:
> if((PINC & (1 << PINC1)) && (PINB & !(1 << PINB1))){ PORTD |= (1<<PD1);
>

Der Knackpunkt liegt darin, dass du die Formulierung
1
an PINB1 ein low
umformulierst in
1
an PINB1 kein high

Warum ist das so?
WEil du mittels

  if( iregendetwas & ( 1 << Pinnummer ) )

aubfragst ob etwas high ist.
Ob dieses etwas low ist, ist dann einfach die gegenteilige Bedingung

 if( !( irgendetwas & ( 1 << Pinnummer ) )

aber die 'Phrase'
1
   irgendetwas & ( 1 << Pinnummer )
die musst du so wie sie ist erhalten. Denn die isoliert dir dieses eine 
bestimmte Bit aus dem irgendetwas. Und erst dann, wenn du dieses Bit 
hast, kannst du entscheiden und abfragen ob dieses Bit jetzt 0 oder 
nicht 0 sein soll.

von Rocco L. (kaufparkangucker)


Lesenswert?

Danke für die schnellen antworten

Unb besonderen Dank and die schöne Erklährung von Herrn Buchegger. Diese 
"irgendwas" Erklährungen liegen mir auch total ;-)

Nein erlich - vielen Dank, habe es glaube verstanden und versuche es 
gleich mal umzusetzen.

von Rocco L. (kaufparkangucker)


Lesenswert?

irgend was passt trotzdem noch nicht...
Ziel sol es sein einen einfachen Motor anzusteuern.
Die H-Brücke für den Motor hängt an D0 und D1.
Der Atmega bekommt seinen Befehl von einem Weiteren Controler der ihm 
sagt in welche Richtung der Atmega den Motor drehen lassen soll.

Bevor das alles los geht gibt es eine Initialisierung wo der Motor so 
lange Richtung Kältebad fährt bis ein Arm einen Taster auslöst. Damit 
soll der Atmega wissen das der Motor nun im Kältebad ist.
Also drehe so lange nach links bis B0 ein high bekommt.

1
//C0 cw in vom Mainframe
2
//C1 ccw in vom Mainframe
3
//
4
//B0 Taster Kältebad
5
//B1 Taster Wärmebad
6
//
7
//D0 cw out zum Motor  -> Richtung Kältebad
8
//D1 ccw out zum Motor  -> Richtung Wärmebad
9
//D2 LED on als Anzeige das mit dem Beladen begonnen werden kann
10
11
#include <inttypes.h>
12
#include <avr/io.h>
13
#include <avr/interrupt.h>
14
//#define F_CPU 1000000UL
15
//#include <util/delay.h>
16
#include <stdint.h>
17
18
19
int main(void){
20
21
DDRB = 0xff;    //Ausgänge
22
DDRD = 0xff;    //Ausgänge
23
DDRC = 0x00;    //Eingänge
24
25
while(1){
26
//Initialiserung - ins Kältebad fahren
27
  PORTD |= (1<<PD0);
28
// Prüfen ob das Kältebad erreicht wurde
29
    if(PINB & (1 << PINB0)){  //fals Taster am Kältebad gedrückt ist
30
      PORTD &= ~(1<<PB0);    //cw off -> Motor aus
31
      PORTD |= (1<<PD2);    //LED ein
32
      break;
33
    }
34
    if (!(PINB & (1 << PINB0))){
35
      PORTD &= ~(1<<PD2);    //LED aus
36
      break;
37
    }
38
//end if
39
}  //Ende while
40
41
// Hauptroutine###############################################################
42
while(1){
43
  
44
  //Start des Programms an sich mit einem C1 = logisch 1 vom Mainframe
45
  //und PINB1 = logisch 0
46
  //fals ccw vom Mainframe und Taster Wärmebad nicht gedrückt -> ccw zum Motor
47
  if((PINC & (1 << PINC1)) && !(PINB & (1 << PINB1))){ PORTD |= (1<<PD1);}  //ins Wärmebad fahren
48
  //fals ccw vom Mainframe und Taster Wärmebad gedrückt       -> nichts machen
49
  if((PINC & (1 << PINC1)) && !(PINB & (1 << PINB1))){ PORTD &= ~(1<<PD1);}  //nichts tun
50
51
  //fals cw vom Mainframe und Taster Kältebad nicht gedrückt -> cw zum Motor
52
  if((PINC & (1 << PINC0)) && !(PINB & (1 << PINB0))){ PORTD |= (1<<PD0);}  //ins Kältebad fahren
53
  //fals cw vom Mainframe und Taster Kältebad gedrückt       -> nichts machen
54
  if((PINC & (1 << PINC0)) && !(PINB & (1 << PINB0))){ PORTD &= ~(1<<PD0);}  //nichts tun
55
56
} // Ende while
57
58
return 0;
59
60
}

von Karl H. (kbuchegg)


Lesenswert?

Was jetzt genau dein Problem ist, hab ich auch noch nicht heraus. Da 
muss ich deine Fehlerbeschreibung noch weiter studieren. Und bitte: Sag 
nicht 'da passt noch irgendewtwas noch nicht', denn darunter kann sich 
auf dieser Seite des Monitors keiner etwas vorstellen.

Aber eines gleich mal vorweg
1
while(1){
2
//Initialiserung - ins Kältebad fahren
3
  PORTD |= (1<<PD0);
4
// Prüfen ob das Kältebad erreicht wurde
5
    if(PINB & (1 << PINB0)){  //fals Taster am Kältebad gedrückt ist
6
      PORTD &= ~(1<<PB0);    //cw off -> Motor aus
7
      PORTD |= (1<<PD2);    //LED ein
8
      break;
9
    }
10
    if (!(PINB & (1 << PINB0))){
11
      PORTD &= ~(1<<PD2);    //LED aus
12
      break;
13
    }
14
//end if
15
}  //Ende while

Frag nicht zuviel ab! Das else ist schon erfunden. Wenn ein bestimmtes 
Bit nicht 1 ist, dann muss es 0 sein. Eine andere Möglichkeit gibt es 
nicht! Anstelle das du da haufenweise Bedingungen abprüfst, die man bei 
der Fehlersuche alle wieder einzeln untersuchen und überlegen muss, 
schreib doch einfach else, dann ist nämlich alles klar.
1
while(1){
2
//Initialiserung - ins Kältebad fahren
3
  PORTD |= (1<<PD0);
4
// Prüfen ob das Kältebad erreicht wurde
5
    if(PINB & (1 << PINB0)){  //fals Taster am Kältebad gedrückt ist
6
      PORTD &= ~(1<<PB0);    //cw off -> Motor aus
7
      PORTD |= (1<<PD2);    //LED ein
8
      break;
9
    }
10
    else {
11
      PORTD &= ~(1<<PD2);    //LED aus
12
      break;
13
    }
14
//end if
15
}  //Ende while

und dann sieht man jetzt nämnlich auch: Egal ob das Bit HIgh oder Low 
ist, du breakst dich in jedem Fall aus der SChleife raus.
In diesem Fall wäre es überhaupt besser, auf das break zu verzichten. 
Mach es doch weniger kompliziert so
1
  LED ein
2
  Motor ein
3
4
  while( Endposition nicht erricht )
5
    Nichts tun (abwarten und Tee trinken)
6
7
  Motor aus
8
  LED aus
das ist einfach, simpel, überschaubar und man muss nicht dauernd um die 
Ecke denken, wann und wo jetzt welche Schleife aus welchem Grund 
verlassen wird. Zudem entspricht das besser dem, wie man wohl als Mensch 
an die Sache rangehen würde.

von Stefan E. (sternst)


Lesenswert?

1
    if(PINB & (1 << PINB0)){  //fals Taster am Kältebad gedrückt ist
2
      PORTD &= ~(1<<PB0);    //cw off -> Motor aus
3
      PORTD |= (1<<PD2);    //LED ein
4
      break;
5
    }
6
    if (!(PINB & (1 << PINB0))){
7
      PORTD &= ~(1<<PD2);    //LED aus
8
      break;
9
    }
Die beiden "if" haben genau komplementäre Bedingungen und in beiden 
Code-Blöcken steht ein "break". Also wird die umgebende Endlosschleife 
nur einmal durchlaufen (außer der Pin ändert genau dazwischen den 
Zustand). Wohl kaum das, was du eigentlich haben wolltest.

1
  //fals ccw vom Mainframe und Taster Wärmebad nicht gedrückt -> ccw zum Motor
2
  if((PINC & (1 << PINC1)) && !(PINB & (1 << PINB1))){ PORTD |= (1<<PD1);}  //ins Wärmebad fahren
3
  //fals ccw vom Mainframe und Taster Wärmebad gedrückt       -> nichts machen
4
  if((PINC & (1 << PINC1)) && !(PINB & (1 << PINB1))){ PORTD &= ~(1<<PD1);}  //nichts tun
In den Kommentaren stehen unterschiedliche Bedingungen, die 
if-Bedingungen sind aber identisch. Wie passt das zusammen?

1
  //fals cw vom Mainframe und Taster Kältebad nicht gedrückt -> cw zum Motor
2
  if((PINC & (1 << PINC0)) && !(PINB & (1 << PINB0))){ PORTD |= (1<<PD0);}  //ins Kältebad fahren
3
  //fals cw vom Mainframe und Taster Kältebad gedrückt       -> nichts machen
4
  if((PINC & (1 << PINC0)) && !(PINB & (1 << PINB0))){ PORTD &= ~(1<<PD0);}  //nichts tun
Dito.

von Rocco L. (kaufparkangucker)


Lesenswert?

ok, habe das mal so weit umgesetzt. das mit dem if und else und dem 
break verstehe ich auch.
Blöd ist nur das Zeile 27 doch dazu führen müste das der Motor erst mal 
in eine Richtung los dreht so lange der Positionstatster nicht erreicht 
wurde..aber er dreht gar nicht erst los:
1
//Initialiserung - ins Kältebad fahren
2
  PORTD |= (1<<PD0);  <<<<<<<<<<<DAS HIER FUNKTIONIERT NICHT
3
// Prüfen ob das Kältebad erreicht wurde
4
    if(PINB & (1 << PINB0)){  //fals Taster am Kältebad gedrückt ist
5
      PORTD &= ~(1<<PB0);    //cw off -> Motor aus
6
      PORTD |= (1<<PD2);    //LED ein
7
      //break;
8
    }
9
    else{
10
    //if (!(PINB & (1 << PINB0))){
11
      PORTD &= ~(1<<PD2);    //LED aus
12
      //break;
13
    }
14
//end if
15
}  //Ende while

Den 2ten Teil von Stefan verstehe ich nicht so ganz... es sind doch 
unterschiedliche dinge die ich in den if Bedingungen möchte...
Kanst Du mir das genauer erklären wo ich da falsch denke.

von Karl H. (kbuchegg)


Lesenswert?

Wie Stefan schon schrieb.

Bei dem 2.ten Teil des Programms hast du dich durch übermässige 
unübersichtliche Vergleiche mächtig selbst ausgetrickst. Das würde ich 
dir empfehlen: SChmeiss es weg und schreib es nochmal neu. Aber trenne 
diesmal die Dinge. In deinen Abfragen kommt immer wieder der Teil (falls 
ccw vom Mainframe vor). Daskann man auch durchaus herausziehen
1
  while( Endlos ) {
2
3
    if( ccw vom Mainframe ) {
4
       if( Taster Kältbad gedrückt )
5
         mach was
6
       else   // Taster nicht gedrückt
7
         mach was anderes
8
    }
9
10
    if( cw vom Mainframe ) {
11
       if( Taster Kältebad gedrückt )
12
         mach was
13
       else
14
         mach was anderes
15
    }
16
  }
tricks dich nicht selber mit übermässig komplexen Abfragen aus! Ein 
gutes Programm ist nicht eines, bei dem möglichst viel in einer Zeile 
steht und die man erst 2 Minuten studieren muss um sie zu verstehen und 
zu entschlüsseln!
Ein gutes Programm liest sich wie eine Geschichte und ist leicht zu 
verstehen.

von Karl H. (kbuchegg)


Lesenswert?

Rocco L. schrieb:

> Blöd ist nur das Zeile 27 doch dazu führen müste das der Motor erst mal
> in eine Richtung los dreht so lange der Positionstatster nicht erreicht
> wurde..aber er d reht gar nicht erst los:

zeig bitte alles!

hast du die SChleife noch? WIe sieht die jetzt aus.
Wie ich weiter oben schon gesagt habe: Formuliere das alles um! Dein 
Programm ist viel zu kompliziert und unübersichtlich und die Komplexität 
erschlägt dich im Moment noch
1
...
2
3
int main()
4
{
5
  ....
6
7
  //Initialiserung - ins Kältebad fahren
8
9
  PORTD |= (1<<PD0);     // Motor ein
10
  PORTD &= ~(1<<PD2);    // Led aus
11
12
  while( !(PINB & (1 << PINB0)) )    // solange Endposition nicht erreicht
13
    ;                                // nichts tun und den Motor fahren lassen
14
15
  PORTD &= ~(1<<PD0);    // Motor aus
16
  PORTD |= (1<<PD2);     // Led ein
17
18
  while( 1 ) {
19
     .... die eigentliche Steuerung
20
  }
21
}

von Rocco L. (kaufparkangucker)


Lesenswert?

Ich werde dem Ratschlag folgen und es noch mal neu probieren.
Übung macht je den Meister - und mir kann sie ja nicht schaden.

Danke für die Hilfe und bis dann.

fG Rocco

von Rocco L. (kaufparkangucker)


Lesenswert?

Karl heinz Buchegger schrieb:
> ;                                // nichts tun und den Motor fahren lassen

^^das geht? ich meine, ist das C?

Möchte noch sagen das ich mir alles selber angelesen habe und es nicht 
gelernt habe... es soll also keine Verbesserung sein sondern wirklich 
eine interessierte Frage

von Karl H. (kbuchegg)


Lesenswert?

Rocco L. schrieb:
> Karl heinz Buchegger schrieb:
>> ;                                // nichts tun und den Motor fahren lassen
>
> ^^das geht? ich meine, ist das C?

Ja klar.
C kennt die leere Anweisung, also einen einzelnen ;

Den Fehler macht wohl jeder mal
1
  if( Bedingung ) ;
2
    Anweisung die von der Bedingung abhängen soll
und der einzelne Strichpunkt am Zeilenende vom if verändert die logische 
Struktur :-)

wenn es dir mehr hilft, dann schreibs halt so
1
  while( !(PINB & (1 << PINB0)) ) {  // solange Endposition nicht erreicht
2
                                     // nichts tun und den Motor fahren lassen
3
  }

von Rolf Magnus (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> wenn es dir mehr hilft, dann schreibs halt so
1
>   while( !(PINB & (1 << PINB0)) ) {  // solange Endposition nicht erreicht
2
>                                      // nichts tun und den Motor fahren lassen
3
>   }

Ggf. hilft es auch dem Compiler. Bei neueren GCC-Versionen bekommt man 
bei der Variante mit dem Semikolon eine (meiner Meinung nach unsinnige) 
Warnung, die einem vorschlägt, stattdessen die Klammern zu verwenden.

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.