www.mikrocontroller.net

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


Autor: Rocco L. (kaufparkangucker)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: cde (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
an PINB1 ein low
umformulierst in
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'
   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.

Autor: Rocco L. (kaufparkangucker)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rocco L. (kaufparkangucker)
Datum:

Bewertung
0 lesenswert
nicht 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.

//C0 cw in vom Mainframe
//C1 ccw in vom Mainframe
//
//B0 Taster Kältebad
//B1 Taster Wärmebad
//
//D0 cw out zum Motor  -> Richtung Kältebad
//D1 ccw out zum Motor  -> Richtung Wärmebad
//D2 LED on als Anzeige das mit dem Beladen begonnen werden kann

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
//#define F_CPU 1000000UL
//#include <util/delay.h>
#include <stdint.h>


int main(void){

DDRB = 0xff;    //Ausgänge
DDRD = 0xff;    //Ausgänge
DDRC = 0x00;    //Eingänge

while(1){
//Initialiserung - ins Kältebad fahren
  PORTD |= (1<<PD0);
// Prüfen ob das Kältebad erreicht wurde
    if(PINB & (1 << PINB0)){  //fals Taster am Kältebad gedrückt ist
      PORTD &= ~(1<<PB0);    //cw off -> Motor aus
      PORTD |= (1<<PD2);    //LED ein
      break;
    }
    if (!(PINB & (1 << PINB0))){
      PORTD &= ~(1<<PD2);    //LED aus
      break;
    }
//end if
}  //Ende while

// Hauptroutine###############################################################
while(1){
  
  //Start des Programms an sich mit einem C1 = logisch 1 vom Mainframe
  //und PINB1 = logisch 0
  //fals ccw vom Mainframe und Taster Wärmebad nicht gedrückt -> ccw zum Motor
  if((PINC & (1 << PINC1)) && !(PINB & (1 << PINB1))){ PORTD |= (1<<PD1);}  //ins Wärmebad fahren
  //fals ccw vom Mainframe und Taster Wärmebad gedrückt       -> nichts machen
  if((PINC & (1 << PINC1)) && !(PINB & (1 << PINB1))){ PORTD &= ~(1<<PD1);}  //nichts tun

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

} // Ende while

return 0;

}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
while(1){
//Initialiserung - ins Kältebad fahren
  PORTD |= (1<<PD0);
// Prüfen ob das Kältebad erreicht wurde
    if(PINB & (1 << PINB0)){  //fals Taster am Kältebad gedrückt ist
      PORTD &= ~(1<<PB0);    //cw off -> Motor aus
      PORTD |= (1<<PD2);    //LED ein
      break;
    }
    if (!(PINB & (1 << PINB0))){
      PORTD &= ~(1<<PD2);    //LED aus
      break;
    }
//end if
}  //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.
while(1){
//Initialiserung - ins Kältebad fahren
  PORTD |= (1<<PD0);
// Prüfen ob das Kältebad erreicht wurde
    if(PINB & (1 << PINB0)){  //fals Taster am Kältebad gedrückt ist
      PORTD &= ~(1<<PB0);    //cw off -> Motor aus
      PORTD |= (1<<PD2);    //LED ein
      break;
    }
    else {
      PORTD &= ~(1<<PD2);    //LED aus
      break;
    }
//end if
}  //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
  LED ein
  Motor ein

  while( Endposition nicht erricht )
    Nichts tun (abwarten und Tee trinken)

  Motor aus
  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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
    if(PINB & (1 << PINB0)){  //fals Taster am Kältebad gedrückt ist
      PORTD &= ~(1<<PB0);    //cw off -> Motor aus
      PORTD |= (1<<PD2);    //LED ein
      break;
    }
    if (!(PINB & (1 << PINB0))){
      PORTD &= ~(1<<PD2);    //LED aus
      break;
    }
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.

  //fals ccw vom Mainframe und Taster Wärmebad nicht gedrückt -> ccw zum Motor
  if((PINC & (1 << PINC1)) && !(PINB & (1 << PINB1))){ PORTD |= (1<<PD1);}  //ins Wärmebad fahren
  //fals ccw vom Mainframe und Taster Wärmebad gedrückt       -> nichts machen
  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?

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

Autor: Rocco L. (kaufparkangucker)
Datum:

Bewertung
0 lesenswert
nicht 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:
//Initialiserung - ins Kältebad fahren
  PORTD |= (1<<PD0);  <<<<<<<<<<<DAS HIER FUNKTIONIERT NICHT
// Prüfen ob das Kältebad erreicht wurde
    if(PINB & (1 << PINB0)){  //fals Taster am Kältebad gedrückt ist
      PORTD &= ~(1<<PB0);    //cw off -> Motor aus
      PORTD |= (1<<PD2);    //LED ein
      //break;
    }
    else{
    //if (!(PINB & (1 << PINB0))){
      PORTD &= ~(1<<PD2);    //LED aus
      //break;
    }
//end if
}  //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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
  while( Endlos ) {

    if( ccw vom Mainframe ) {
       if( Taster Kältbad gedrückt )
         mach was
       else   // Taster nicht gedrückt
         mach was anderes
    }

    if( cw vom Mainframe ) {
       if( Taster Kältebad gedrückt )
         mach was
       else
         mach was anderes
    }
  }
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
...

int main()
{
  ....

  //Initialiserung - ins Kältebad fahren

  PORTD |= (1<<PD0);     // Motor ein
  PORTD &= ~(1<<PD2);    // Led aus

  while( !(PINB & (1 << PINB0)) )    // solange Endposition nicht erreicht
    ;                                // nichts tun und den Motor fahren lassen

  PORTD &= ~(1<<PD0);    // Motor aus
  PORTD |= (1<<PD2);     // Led ein

  while( 1 ) {
     .... die eigentliche Steuerung
  }
}

Autor: Rocco L. (kaufparkangucker)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rocco L. (kaufparkangucker)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
  if( Bedingung ) ;
    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
  while( !(PINB & (1 << PINB0)) ) {  // solange Endposition nicht erreicht
                                     // nichts tun und den Motor fahren lassen
  }

Autor: Rolf Magnus (Gast)
Datum:

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

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.

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.