- Reichelt Elektronik    Werbung      
Ergebnis 1 bis 10 von 12

Thema: Probleme mit IF-Abfrage / Timer

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Benutzer Stammmitglied
    Registriert seit
    17.12.2005
    Ort
    Untermain
    Beiträge
    58
    Du hast offenbar etwas übersehen. Die von dir erwähnte abfrage TRIFTT dummerweise zu, wie du dem Screenshot entnehmen kannst. Bild  
    Dass
    Code:
    if (g_msec < 1000) {}
    nach
    Code:
    if (g_msec > 999) {}
    nicht zutreffen DARF, ist mir schon auch klar...
    die Zeile entsprang nur meiner verzweiflung; und da die inkrementierung leider mehr als einmal aufgeführt wurde, versuche ich jetzt herauszufinden, wie es dazu kommen kann...
    vielleicht flackert ja ein Bit im RAM, aber ich halte das für ehr unwahrscheinlich...

    nachdem ich den ganzen µC jetzt noch einmal komplett gelöscht und auch die Fuses einmal (bis auf SPIEN) nicht gesetzt programmiert habe, bevor ich wieder zurück gewechselt habe, scheint der Fehler nicht mehr sehr häufig aufzutreten...
    ich habe die "debug-Prüfung" etwas angepasst:
    Code:
            if (g_msec < 1000){
            g_fail++; // volatile, int16
            }
    g_fail wird jetzt außerdem mit ausgegeben, die entsprechende Zeile (in main.c) ist:
    Code:
    sprintf(buffer, "\nT: %02d:%02d:%02d.%04d   %04d\n", g_h, g_min, g_sec, g_msec, g_fail);
    der Wert ist bei Laufzeit 00:01:04 (hh, mm, ss) des Programms auf 1 gesprungen (ja, wird immer mit 0 initialisiert) und mehr als eine Stunde so geblieben... scheint also ein (mittlerweile) ehr seltenes Phänomen zu sein... (das ist so auch reproduzierbar, er macht das immer wieder zu dem Zeitpunkt und dann geht es zumindest bisher ohne diesen Fehler weiter, bis ich neustarte)

    Der Code der Timerroutine ist übrigens im Anhang dabei, ist aber auch nix weltbewegendes:
    Code:
    ISR(TIMER0_COMP_vect)
    {
       // hier wird der msec-zähler gesetzt. Die übrigen
       // Programmteile müssen diese Aenderung "sehen":
       // volatile -> aktuellen Wert immer in den Speicher schreiben
       g_msec++;
    }
    zu früh gefreut:
    00:01:43.-232 0003
    Geändert von sammler (23.04.2011 um 17:56 Uhr)

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.04.2010
    Beiträge
    1.249
    Nein, das habe ich nicht übersehen.

    Und wieso ignorierst du alles was ich zum Typ von g_msec und der Möglichkeit das es negativ sein kann geschrieben hab?

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    17.12.2005
    Ort
    Untermain
    Beiträge
    58
    Hi Tobi Bild  

    Dass g_msec signed ist, stammt daher, dass die Variable zum teil (weil die Abfrage mal wieder gesponnen hat) in den Bereich 65xxx gejagt wurde, als sie noch unsigned war.
    Und DA gab es dann natürlich Probleme, weil die Abfrage ständig zutraf, was zu einer ehr ungünstigen dauerinkrementierung der g_sec Variablen geführt hat, wodurch die "Uhr" erstmal gründlich vorging.
    Aufgrund der (derzeitigen) Auslastung des µC bekomme ich mit der aktuellen Version faktisch keine Probleme, weil die Routine mehr als 1x in der Sekunde aufgerufen wird...
    negative Zahlen sind für die Abfrage grundsätzlich unproblematisch - es dauert nur länger, bis sie wieder zuschlägt (bei mir meist 232 ms, wenn die vorherige Runde wieder einmal schiefging).

  4. #4
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    if (g_msec > 999)
    ...
    PS: der Wert von g_msec, wenn er fälschlich reinspringt, ist offenbar immer 768 (dez.)
    Du hast schlicht ein Atomizitäts-Problem. g_msec ist größer als ein Byte, und damit kann der Vergleich nicht atomar sein. Er besteht aus mehreren Maschinenbefehlen und der Interrupt kann da mitten rein fallen. Was ganz genau passiert, ist folgendes:
    - g_msec ist 767 (0x02ff) wenn der Vergleich beginnt.
    - Zuerst wird das Low-Byte genommen (0xff).
    - Jetzt kommt der Interrupt und ändert g_msec von 767 (0x02ff) auf 768 (0x0300).
    - Der Vergleich macht weiter mit dem High-Byte (0x03).
    - Ergebnis des Vergleichs: True, weil 1023 (0x03ff) größer ist als 999.
    Geändert von sternst (24.04.2011 um 00:04 Uhr)
    MfG
    Stefan

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.04.2010
    Beiträge
    1.249
    Du meinst also das cli(); sollte besser noch eine Zeile früher kommen?

  6. #6
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Zitat Zitat von TobiKa Beitrag anzeigen
    Du meinst also das cli(); sollte besser noch eine Zeile früher kommen?
    Könnte man so machen, aber dann muss man auch das sei() aus dem if raus ziehen, weil ja sonst die Interrupts im False-Fall abgeschaltet blieben. Ich persönlich würde das nicht machen, weil dann nämlich im True-Fall die Interrupts viel länger abgeschaltet wären, als nötig. Das muss keine Auswirkungen haben (hätte es in diesem einfachen Fall auch nicht), aber besser man gewöhnt sich gleich an, Interrupts immer nur so kurz wie möglich abzuschalten. Bei mir sähe es in etwa so aus:
    Code:
    #include <util/atomic.h>
       
     
    void make_time (void) {
    
        int16_t tmp_msec;
    
        ATOMIC_BLOCK (ATOMIC_RESTORESTATE) {
            tmp_msec = g_msec;
        }
    
        if (tmp_msec > 999) {
    
            ATOMIC_BLOCK (ATOMIC_RESTORESTATE) {
                g_msec -= 1000;
            }
    
            g_sec++;
            g_send=1;
            PORTA ^= (1 << PINA0);
            if (g_sec > 59){
                g_sec = 0;
                g_min++;
                PORTA ^= (1 << PINA1);
                if (g_min > 59){
                    g_min = 0;
                    g_h++;
                    PORTA ^= (1 << PINA2);
                    if (g_h > 23){
                        g_h = 0;
                        g_d++;
                   }
                }
            }
        }
    }
    MfG
    Stefan

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    25.04.2010
    Beiträge
    1.249
    Ja, das ist schon klar.

    Aber wie gesagt, ich würde alles in den Interrupt rein packen.
    Geändert von TobiKa (24.04.2011 um 13:42 Uhr)

Ähnliche Themen

  1. interne pull up widerstand/ probleme mit der tasten abfrage
    Von Asuro91 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 06.06.2010, 14:36
  2. problem mit button-abfrage im timer (c#)
    Von Roboman93 im Forum Open Source Software Projekte
    Antworten: 4
    Letzter Beitrag: 29.12.2008, 17:40
  3. Probleme mit Timer und ATMega 32
    Von steffen21m im Forum C - Programmierung (GCC u.a.)
    Antworten: 4
    Letzter Beitrag: 07.01.2008, 19:17
  4. Radencoder- und Timer-Probleme
    Von Speedking im Forum C - Programmierung (GCC u.a.)
    Antworten: 0
    Letzter Beitrag: 26.07.2006, 22:18
  5. Anfängerfrage: Timer-Abfrage beim PIC 10F206???
    Von JayCool im Forum PIC Controller
    Antworten: 2
    Letzter Beitrag: 07.06.2006, 10:23

Berechtigungen

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

    Werbung      fchao-Sinus-Wechselrichter AliExpress