Diskussion:Uhr

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche

--Sternst 19:33, 11. Sep. 2009 (CEST)

Ich möchte ja nicht unbedingt den Miesmacher spielen, aber der Code ist nicht gerade ein Musterbeispiel. Vielleicht hättest du ihn vor Veröffentlichung als Artikel mal im Forum zur Diskussion stellen sollen.

1) <c> switch (Hunderter) //Hier wird der jeweilige Zahlenwert in PORTB geschrieben { case 0: PORTB=Zahl[0];break; case 1: PORTB=Zahl[1];break; case 2: PORTB=Zahl[2];break; case 3: PORTB=Zahl[3];break; case 4: PORTB=Zahl[4];break; case 5: PORTB=Zahl[5];break; case 6: PORTB=Zahl[6];break; case 7: PORTB=Zahl[7];break; case 8: PORTB=Zahl[8];break; case 9: PORTB=Zahl[9];break; } </c> Soll das etwa irgendeinen Vorteil gegenüber einem simplen<c>PORTB = Zahl[Hunderter];</c>haben?
2) <c>OCR1A = 31250; //genau eine Sekunde (8000000Hz / 256 / 31250 = 1); </c> Für genau eine Sekunde im CTC-Modus müsste man 31250 - 1 (also 31249) ins Register laden.

3) <c>TCCR1B = 0b00001100;</c> Warum benutzt du nicht wie üblich die symbolischen Namen? Diese Zahlenkonstanten erschweren nur unnötig das Portieren auf einen anderen Controller.

4)
Etwas mehr Sorgfalt beim Formatieren (Einrückungen) wäre auch nicht schlecht.


1 und 2: das ist gut, korrigier ich sofort. 3: Ich finde die 0bxxxxxxxx Schreibweise übersichtlicher, ich denke das ist Geschmackssache. 4: Die Einrückungen hab ich im Code ja auch richtig, aber hier im Wiki ist das etwas komisch
Danke nochmal für die Anregungen. Sind jetztf umgesetzt. Die Version mit den Defines hab ich rausgenommen, macht ja nun wirklich keinen Sinn.

Sekunden ist nicht ISR-sicher

So wie das Programm momentan aufgebaut ist müsste auf "Sekunden" atomar zugegriffen werden. Ansonsten hat x bei

x = Sekunden;

u.U keinen sinnvollen Wert! Dito für die Ausdrücke im Programm. (zumindest wenn long int nicht in einer Maschineninstruktion gelesen oder geschrieben werden kann.)

Zudem ist es wesentlich einfacher (und in dieser ISR absolut unkritisch) die Sekunden bei 60 überlaufen zu lassen und dabei die Minuten um 1 zu erhöhen; die Minuten bei 60 überlaufen zu lassen und dabei die Stunden um 1 zu erhöhen; etc. --Gjlayde 19:54, 20. Sep. 2009 (CEST)

Etwa so

<c> //32Bit Variable; 24Bit würdens auch tun volatile long int Sekunden=86399; unsigned char Tausender; unsigned char Hunderter; unsigned char Zehner; unsigned char Einer; unsigned char sek;

//Bei Compare-Match mit OCR1A (31249) wird Sekunden um eins erhöht. ISR(TIMER1_COMPA_vect) {

   Sekunden++;
   if (++sek >= 60)
   {
       sek = 0;
       if (++Einer >= 10)
       {
           Einer = 0;

if (++Zehner >= 6 )

           {
               Zehner = 0;

Hunderter++;

               if ((Tausender >= 2) && (Hunderter == 4))
               {
                   Sekunden = 0;

Tausender = 0; Hunderter = 0;

               }
               else 
                   if (Hunderter >= 10)

{

                       Hunderter = 0;

Tausender++;

                   }
           }  
       }
   }

} </c>

Damit dauert ein ISR Aufruf zwischen 50 und maximal 100 Takten (23:59:59) Aber das Problem der ISR-Sicherheit bleibt. Auch hier kann sich alles durch einen Interrupt während der Abfrage ändern. Wie löst man das clever? ISR vor Abfrage mit CLI abschhalten, alle Daten kopieren und wieder einschalten mitttels SEI. Wird der mögliche Compare-Match mit OCR1A-Interrupt dann nachgeholt? Steht sicher in den PDF's

Ja, die ISR wird dann nachgeholt. --Gjlayde 18:35, 21. Sep. 2009 (CEST)
Wenn ich am Wochenende Zeit hab, werde ich das mal ausprobieren zu integrieren. Inox5 19:17, 21. Sep. 2009 (CEST)
Es genügt, in der ISR ein Flag zu setzen, daß eine neue Sekunde angefangen hat. Alles andere kann in der (möglichst blockierfreien) Hauptschleife abgehandelt werden. Aber auch dort ist dieses hochzählen einfacher als Division+Modulo. --Gjlayde 20:42, 21. Sep. 2009 (CEST)
Statt eines Flags vielleicht zur Sicherheit einen Zähler?

<c>unsigned char Tausender; unsigned char Hunderter; unsigned char Zehner; unsigned char Einer; unsigned char sek; volatile unsigned char DeltaSek;

ISR(TIMER1_COMPA_vect) //Bei Compare-Match mit OCR1A (31249) wird Sekunden um eins erhöht. {DeltaSek++;}


void Berechnung (void) {unsigned char temp;

cli();
temp = DeltaSek;   // deltaSek retten
DeltaSek = 0;      // und direkt löschen   
sei();
while (temp > 0 )
  {sek++;
   if (sek >= 60 )
     {sek = 0;
     Einer++;
     if ( Einer >= 10 )
       {Einer = 0;
        Zehner++;

if ( Zehner >= 6 )

          {Zehner = 0;

Hunderter++;

           if ((Hunderter == 4)&&(Tausender >= 2))
             {Tausender = 0;

Hunderter = 0;}

           else 
             if ( Hunderter >= 10 )

{Hunderter = 0; Tausender++;}

          }// Zehner
       }//if Einer
    }// if sek
  temp--;
  }//while

}</c> --Horha 11:59, 22. Sep. 2009 (CEST)