While-Befehl macht nicht, was ich möchte



  • Die folgende Programmsequenz funktioniert leider nicht. Was mache ich als Anfänger falsch?
    Alle Änderungen in der Schreibweise, die ich durchgeführt habe, führen nicht zum Erfolg.
    Der MPLAB-Debugger bleibt ausserdem in Zeile 4 stehen.

    while(PORTAbits.RA1 != 0);       // Warte solange RA1 = 1   
         T0_RES(); 			 // Wenn RA1 = 0 dann führe Funktion T0_RES() aus	
    
    while(PORTAbits.RA1 != 1) {}     // Warte, solange RA1 = 0 
        T0CON0bits.T0EN = 0;         // Wenn RA1 = 1, dann setze T0EN-Bit auf 0
    


  • Warum sollte sich der Wert jemals ändern?


  • Mod

    while führt die darauf folgende Anweisung aus. Eine Anweisung ist etwas, das von {} eingeschlossen ist oder mit ; endet. In Zeile 1 wird folglich alles bis zum Semikolon ausgeführt, also nichts. Mach es weg. In Zeile 4 wird folglich alles zwischen den {} ausgeführt, also nichts. Mach was du ausführen möchtest in die {}.

    Du solltest auch stark überlegen, einen Editor mit automatischer Einrückung zu benutzen, dann würdest du solche Fehler sofort bemerken.

    PS: Du solltest dir auch angewöhnen immer genau das zu prüfen, was du prüfen möchtest. Du schreibst beispielsweise, du möchtest "solange RA1 = 1", aber du machst "RA1 != 0" . Das ist nicht das gleiche.

    PPS: Da sieht man mal, was komische Kommentare und Einrückung anrichten, denn ich habe deine vermutlichen Absichten wohl missverstanden. Aber nach 3x Lesen schließe ich mich Bashars Interpretation deines Beitrags an.



  • An PORTA,RA1 ist ein Sensor angeschlossen, der alle 100 MS einen Messwert abgibt. Somit ändert sich der Zustand an RA1 laufend.



  • Ich sehe keinen Fehler, es ist nur komisch aufgeschrieben. Wenn die Bedingung "solange RA=1" ist, dann schreib das doch auch so und lass den Kommentar weg. Und es sollte klargestellt werden, dass der Schleifenkörper leer ist.

    while (PORTAbits.RA1 == 1)
      ;
    T0_RES();
    
    while (PORTAbits.RA1 == 0)
      ;
    T0CON0bits.T0EN = 0;
    

    Unter der Voraussetzung, dass RA nur die Werte 0 und 1 annehmen kann, macht das das gleiche wie dein Code und entspricht deiner Beschreibung. Es muss irgendwoanders dran liegen. Der Debugger bleibt in Zeile 4 hängen, weil PORTAbits.RA1 die ganze Zeit einen Wert ungleich 1 hat. Ich nehme mal an, dass das ganze auf einem Microcontroller passiert und PORTAbits.RA1 von vornherein mit volatile markiert ist, denn sonst kann das natürlich nicht funktionieren.



  • Herzlichen Dank für die schnellen Hilfen!
    Bashar:
    Danke für die übersichtliche Schreibweise, denn ich hatte mich schon gewundert, wieso ich zwei unterschiedliche Schreibweisen verwenden musste, damit der Compiler nicht meckert...
    PORTAbits.RA1 ist ein Controller-Eingang, der von einem Sensor laufend serielle Signale (High und Low) bekommt. "PORTAbits.RA1" habe ich nicht definiert, sondern diese Bezeichnung ist vom Hersteller dieses Controllers vordefiniert. Daher kann ich" PORTAbits.RA1" nicht als "volatile" markieren und ich hoffe, dass dies bereits vom Hersteller gemacht wurde.
    Der MPLAB-Debugger scheint auf Änderungen an einem Porteingang, die erwiesenermaßen stattfinden (gemessen), nicht reagieren zu können.



  • Ich kenn mich damit wirklich nicht aus, aber hast du schonmal erfolgreich von diesem Eingang gelesen? Vielleicht muss man den ja erst irgendwie konfigurieren, bevor man ihn lesen kann.



  • Oder einfach

    while(PORTAbits.RA1);
    T0_RES();
    while(!PORTAbits.RA1);
    T0CON0bits.T0EN = 0;
    

    das ist zumindest die gängige Variante, schließlich wird die 0, der LOW Value, als falsch interpretiert und alles andere, eben auch der HIGH Value als wahr.

    Bzw. oft liest man auch den ganzen Port ein, dein Framework da scheint da wohl das ganze etwas aufzuhübschen ... da muss man nur auf Effizienz etwas achten, sobald man mehrere Pins einliest am selben Port.

    while(PORTA & (1 << RA1); // Solange RA1 HIGH
    while(!(PORTA & (1 << RA1)); //Solange RA1 LOW
    while(PORTA & (1 << RA1 | 1 << RA4 | 1 << RA5)); //Solange RA1, RA4, RA5 HIGH
    

    Oder so in der Art, abhängig davon was für einen Microcontroller du da hast.

    Wird PORTAbits.RA1 sowohl für Ausgang als auch Eingang genommen? Zumindest bei avr microcontrollern, kann man mit PORTX nur Ausgänge setzen, während man mit PINX Eingänge einliesr.

    Weiterführende Frage: IST RA1 ein digitaler Eingang? Könnte es ggf. auch ein analoger Eingang sein, sodass du Werte zwischen 0 und 1024 oder so bekommst?



  • Hallo Bashar,
    vielen Dank für Deine Hilfe!
    Ich verwende den PIC16F18313 und programmiere ihn mit dem MPLAB über PICKit von Microchip. Ich versuche, den Temperaturfühler TSIC151 auszulesen. Es zeigte sich, dass PicKid den Ausgang des TSIC so stark beeinflusst, dass das Signal undefiniert wird. Insoweit hattest Du mit Deiner Annahme Recht, dass der PIC-Eingang nicht in den notwendigen Zustand gelangen kann. Ich habe die Schaltung geändert und jetzt funktioniert die Software (dank Deiner Hilfe), worüber ich mich als Anfänger sehr freue. Es ist mein erstes C-Programm!

    Wie das immer so ist, stößt man als Anfänger ständig auf neue Probleme.
    Jetzt grübele ich, wie ich zwei 8- Bit Werte zu einer 16 Bit Zahl machen kann.
    Beispiel:
    8-Bit-Wert 1 : 0x02 (das ist das High-Nibbel der 16 Bit Zahl)
    8-Bit-Wert 2 Low: 0xEB(das ist das Low-Nibbel der 16 Bit Zahl)
    Da ich damit rechnen muss, benötige ich hieraus die folgende 16 Bit-Zahl: 0x02EB.
    Vermutlich muss ich 0x02 mit 256 multiplizieren und dann 0xEB addieren.
    Habe ich aber noch nicht ausprobiert.



  • @Leon0402
    vielen Dank für Deine Erläuterungen!
    Ich verwende den PIC16F18313 und programmiere ihn mit dem MPLAB über PICKit von Microchip. Ich versuche, den Temperaturfühler TSIC151 auszulesen. Es zeigte sich, dass PicKit den Ausgang des TSIC so stark beeinflusst, dass das Signal undefiniert wird. Nach Änderungen der Schaltung funktioniert die Software zu meiner Überraschung. Es ist mein allererstes C-Programm!

    Stimmt es, dass

    while(PORTAbits.RA1);
    dasselbe ist, wie
    while(PORTAbits.RA1 == 1);```
    ```cpp
    
    

    Ich finde die erste Schreibweise eher undurchsichtig und es verwirrt mich, wenn ich lese, wieviel abgekürzte Schreibweisen es bei C gibt.



  • @buschi sagte in While-Befehl macht nicht, was ich möchte:

    8-Bit-Wert 1 : 0x02 (das ist das High-Nibbel der 16 Bit Zahl)
    8-Bit-Wert 2 Low: 0xEB(das ist das Low-Nibbel der 16 Bit Zahl)

    Nibble sind nur 4 Bit (also eine Hex-Ziffer)

    Dein Problem wird mit binären Operatoren (& l << >>) gelöst.

    wert = (0x02 << 8) & 0xEB

    Das kannst du so schreiben. Der Compiler kann das optimieren.
    Du musst aber etwas bei unsigned Typen aufpassen.



  • @buschi sagte in While-Befehl macht nicht, was ich möchte:

    Stimmt es, dass
    while(PORTAbits.RA1);
    dasselbe ist, wie
    while(PORTAbits.RA1 == 1);

    Nein.
    Es ist dasselbe wie
    while(PORTAbits.RA1 != 0);

    Jeder Wert ungleich 0 gilt als wahr.

    Allerdings hängt das auch davon ab, welche Werte PORTAbits.RA1 annehmen kann. Wenn es nur 0 und 1 sind, stimmt deine Aussage.



  • Vielen Dank!
    Ich dachte, man kann den Begriff "Nibbel" bei einer 16-Bit-Zahl für das High-Byte bzw. Low-Byte verwenden. Wie heissen diese Teile in der Fachsprache richtig?
    Vielen Dank für die einfache Lösung. Ich werde es morgen ausprobieren.
    Allerdings weiss ich als Anfänger leider nicht, worauf man bei unsigned Typen hier aufpassen muss.



  • @DirkB
    Ja, das ist nur ein Port-Pin, der nur 0 oder 1 sein kann.



  • @buschi sagte in While-Befehl macht nicht, was ich möchte:

    Ich dachte, man kann den Begriff "Nibbel" bei einer 16-Bit-Zahl für das High-Byte bzw. Low-Byte verwenden. Wie heissen diese Teile in der Fachsprache richtig?

    High-Byte und Low-Byte.
    Manchmal wird auch (fälschlicherweise) MSB und LSB (Most bzw. Least Significant Byte) obwohl das für Bits steht.

    Vielen Dank für die einfache Lösung. Ich werde es morgen ausprobieren.
    Allerdings weiss ich als Anfänger leider nicht, worauf man bei unsigned Typen hier aufpassen muss.

    Die Werte sind ja nicht fix (sonst würdest du 0x02eb schreiben) sondern sind in Variablen.

    Wenn 0xEB in einer 8-Bit Variablen mit Vorzeichen gespeichert ist, ist der Wert negativ und bei der Erweiterung zu int gibt das 0xFFEB.

    wert = ((HighByte & 0xff) << 😎 & (LowByte & 0xff)



  • @buschi sagte in While-Befehl macht nicht, was ich möchte:

    Ja, das ist nur ein Port-Pin, der nur 0 oder 1 sein kann.

    Auf anderen Mikrocontrollern kann aber auch der Wert des Bits zurück kommen (bei PA1 0 und 2)



  • @buschi sagte in While-Befehl macht nicht, was ich möchte:

    Ich finde die erste Schreibweise eher undurchsichtig und es verwirrt mich, wenn ich lese, wieviel abgekürzte Schreibweisen es bei C gibt.

    Das legt sich ganz schnell und das ist wirklich einer der Dinge, die deinen Code aus meiner Sicht wesentlich lesbarer machen.
    Du muss dir das ein bisschen wie einen bool vorstellen in C++, eine Variable vom typ bool kann nur den Wert true oder false annehmen (1 oder 0) . Also im Prinzip wie deine digitalen Pins.

    bool bitHigh = true;
    while(bitHigh == true);
    

    Das ist irgendwie einfach doppelt ^^ Und grade wenn die Bedingungen etwas komplexer werden, wird es lesbarer, wenn du es weg lässt.


Log in to reply