- LiTime Speicher und Akkus         
Ergebnis 1 bis 6 von 6

Thema: Bit in einer Variable löschen geht nicht

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    12.07.2008
    Ort
    Villingen-Schwenningen
    Beiträge
    143

    Bit in einer Variable löschen geht nicht

    Anzeige

    Powerstation Test
    Hallo
    ich habe ein kleines Problem bei einem Bit löschen in einer Bytevariable, die in einer Klasse definiert ist. Ich verwende GCC in verbindung mit Arduino.

    Also ich habe eine Klasse geschrieben namens StateMachine. Diese wird im Hauptprogramm von Arduino in der Objekt-Variable Machine instanziert.
    Die Klasse enthält unter anderem eine Routine setState(), in der der der Zustand der Maschine gesetzt wird. In der Routine wird zusätzlich ein Flag gesetzt, welches anzeigt, dass sich der Zustand geändert hat.
    Eine Andere Routine stateChanged() liefert einen Booleanwert, ob das Flag gesetzt oder gelöscht ist. Weiterhin löscht diese Routine das Flag wieder, welches anzeigt, dass sich der Zustand geändert hat.

    Das Setzen des Flags funktioniert wunderbar, das löschen jedoch nicht.

    Hier die beiden Routinen:

    Code:
    /*
     *    Setzt den gewünschten Zustand der Statemaschine
     *    Zusätzlich wird Flag STATE_CHANGED gesetzt, um zu ermitteln, ob der Zustand sich geändert hat.
     */
    void StateMachine::setState(tagStates newState)
    {
       currentState = newState;         // Zustand setzen
       mFlags |= (1<<STATE_CHANGED);    // Flag setzen, dass Zustand geändert wurde
    }
    und die Flagabfrage

    Code:
    /*
     *    Gibt den Status des Flags STATE_CHANGED zurück und löscht das Flag
     */
    boolean StateMachine::stateChanged()
    {
       return boolean(mFlags and STATE_CHANGED);        // Flag zurück geben
       mFlags &= ~(1<<STATE_CHANGED);                   // Flag löschen, dass Zustand geändert wurde
    }
    hier noch die Header-Datei:
    Code:
    #ifndef statemachine_h
    #define statemachine_h
    
    #include <Arduino.h>
    
    /*
     *    Enumeration mit den zulässigen Maschinen-Zuständen
     */
    enum tagStates    // Zustände der Statemachine
       {
          STATE_MAIN=0,
          STATE_1
       };
    
    /*
     *    Klasse StateMachine
     */
    class StateMachine
    {
       public:
          
          void setState(tagStates newState);     // State setzen
          enum tagStates getState();             // State abrufen
          boolean stateChanged();                // State-Flag STATE_CHANGED prüfen
          byte getMFlags();                      // MaschineFlags abrufen
    
       private:
          enum tagStates currentState;           // Variable nimmt aktuellen Maschinen-Zustand auf
          byte mFlags=0;                         // Diverse Flags innerhalb der Zustands-Maschine
          byte const STATE_CHANGED=7;            // Flag-Definition (Bit-Nr)
    
    };
    
    #endif           // statemachine_h
    In der Hauptschleife habe ich im Augenblick folgenden Code:

    Code:
    // ------------------------------------
    // Hauptschleife
    // ------------------------------------
    void loop() {
       // put your main code here, to run repeatedly:
    
       Serial.println(Machine.getMFlags());
       
       switch (Machine.getState())
       {
          case STATE_MAIN:
             if (Machine.stateChanged()!=0)
             {
                Serial.println("Zustand in STATE_MAIN geändert");
                
                delay(1000);
             }
             else
             {
                Serial.println("Zustand STATE_MAIN stabil!");
                delay(1000);
             }
             break;
       }
    }
    Kann mir jemand sagen was ich falsch mache? Wieso kann ich das Bit STATE_CHANGED in der privaten Variable MFlags nicht löschen?
    Auch wenn ich in stateChanged() MFlags=0 angebe, wird das Flag nicht gelöscht.
    Stehe ich auf dem Schlauch?

    Micha.

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    66
    Beiträge
    2.435
    Hallo Micha,
    Code:
    /*
     *    Gibt den Status des Flags STATE_CHANGED zurück und löscht das Flag
     */
    boolean StateMachine::stateChanged()
    {
       return boolean(mFlags and STATE_CHANGED);        // Flag zurück geben
       mFlags &= ~(1<<STATE_CHANGED);                   // Flag löschen, dass Zustand geändert wurde
    }
    Tja, der Wald und die Bäume.

    Die Zeile nach dem return wird nie ausgeführt!

    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    12.07.2008
    Ort
    Villingen-Schwenningen
    Beiträge
    143
    Ja, jetzt wo du es sagst.
    Logisch!

    Danke

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    66
    Beiträge
    2.435
    Grundsätzlich hat es sich bewährt den Compiler auf maximale Empfindlichkeit bei Warnungen einzustellen.
    Hier hätte der Compile gewarnt, dass unerreichbarer Code existiert.

    Manchmal gibt es Situationen, welche nur so gelöst werden können, dass dann der Compiler meckert.
    Hier hat es sich bewährt mit "#pragma warn" vor der gewollten Stelle die spezifische Warnung aus- und danach wieder einzuschalten.
    Als netter Nebeneffekt ist dann aber auch dokumentiert, dass der Programmierer dies an dieser Stelle gewollt so gemacht hat.

    Vor 20-30 Jahren lieferten C-Compiler fast nur die groben Fehler. Damals hatte man ein spezielles Programm "lint", welches dann Unsauberkeiten gesucht hat. Heute ist "lint" fest im Compiler enthalten.

    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.04.2015
    Beiträge
    865
    Was ist denn der "and"-Ausdruck in
    return boolean(mFlags and STATE_CHANGED);

    Ist das 'nen Macro?
    Oder eine weitere potentielle Fehlerquelle (weiter oben beim Setzen wird ja geschoben)?

  6. #6
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    12.07.2008
    Ort
    Villingen-Schwenningen
    Beiträge
    143
    Cooler Tip!
    Habs in Ardiono gerade mal eingeschaltet und tatsächlich.

    Der hat sogar gemerkt, dass ich eine Enumeration verwende mit 2 Werten, davon aber nur eine in der switch Abfrage verwendet wird.

    Übrigens ich habs jetzt so gelöst:
    Code:
    /*
     *    Gibt den Status des Flags STATE_CHANGED zurück und löscht das Flag
     */
    boolean StateMachine::stateChanged()
    {
       byte ergebnis = boolean(mFlags and STATE_CHANGED);        // Flag zurück geben
       mFlags &= ~(1<<STATE_CHANGED);                   // Flag löschen, dass Zustand geändert wurde
       return ergebnis;
    }


    Noch ne kurze Frage wenn du schon dran bist.

    In einer Klassendefinition, wo legt man da genau eine Enumerations-Struktur an, die außerhalb der Klasse auch als Rückgabewert und/oder als Übergabewert dient?

    Ich habe versucht das:

    Code:
    /*
     *    Enumeration mit den zulässigen Maschinen-Zuständen
     */
    enum tagStates    // Zustände der Statemachine
       {
          STATE_MAIN=0,
          STATE_1
       };
    im Header StateMachine.h im Bereich 'public:' anzugeben.
    Beim Aufruf der Funktionen kam jedoch immer die Fehlermeldung, dass der Typ nicht bekannt sei.
    Wo legt man also in einer Klasse die Enumeration an?
    Vor der Klasse, so wie ich es ganz oben gezeigt habe in StateMachine.h?

    Micha

    - - - Aktualisiert - - -

    das 'and' sollte eigentlich ein bitweiser UND-Vergleich sein. Habs in && geändert.
    Ja und das mit dem Schieben, haste recht.
    Als ich den Fehler suchte hab ich rumprobiert, und die Stelle vergessen zu ändern.

    jetzt siehts so aus:
    Code:
    #include "StateMachine.h"
    
    /*
     *    Setzt den gewünschten Zustand der Statemaschine
     *    Zusätzlich wird Flag STATE_CHANGED gesetzt, um zu ermitteln, ob der Zustand sich geändert hat.
     */
    void StateMachine::setState(tagStates newState)
    {
       currentState = newState;         // Zustand setzen
       mFlags |= (1<<STATE_CHANGED);    // Flag setzen, dass Zustand geändert wurde
    }
    
    
    /*
     *    Gibt den aktuellen Zustand der Statemachine zurück
     */
    enum tagStates StateMachine::getState()
    {
       return currentState;
    }
    
    /*
     *    Gibt den Status des Flags STATE_CHANGED zurück und löscht das Flag
     */
    boolean StateMachine::stateChanged()
    {
       byte ergebnis = boolean(mFlags && (1<<STATE_CHANGED));        // Flag zurück geben
       mFlags &= ~(1<<STATE_CHANGED);                   // Flag löschen, dass Zustand geändert wurde
       return ergebnis;
    }

Ähnliche Themen

  1. Löschen einer Zeile LCD
    Von anfänger99 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 21.02.2011, 11:51
  2. setzen einer Variable nach ablauf einer bestimmten Zeit
    Von mat-sche im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 6
    Letzter Beitrag: 08.12.2008, 00:45
  3. STK500: löschen geht - schreiben nicht!
    Von Dolfo im Forum AVR Hardwarethemen
    Antworten: 2
    Letzter Beitrag: 09.10.2007, 07:35
  4. variable mit <cr><lf> löschen
    Von lanic im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 17.03.2006, 17:56

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test