mikrocontroller.net

Forum: Compiler & IDEs genaue Uhrzeit?


Autor: Steffen T. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich habe ein Programm geschrieben und bin mir jetzt nciht sicher, ob das 
jetzt wirklich die genaue Uhrzeit ausgibt oder ob das noch fehlerhaft 
ist..
#include "lcd.c"
#include <avr/interrupt.h>

volatile unsigned long time_ist;   // globale Vergleichsvariable
unsigned char Buffer[30];          // globales Array für die Strings
unsigned int std = 0;              // globale Variable für die Sekunden
unsigned int min = 0;              // globale Variable für die Minuten
unsigned int sek = 0;              // globale Variable für die Stunden
unsigned int counter = 0;
unsigned int gestellt = 0;         // Uhr gestellt = 1; Uhr ist nicht gestellt = 0;

ISR (TIMER1_COMPA_vect  ) {
  time_ist++;                   //nach jedem Interrupt die Vergleichsvariable hochzählen
  if ( gestellt == 1){
    if(++counter >= 250){  
    counter = 0;         
      if(++sek == 60){          //nach einer Sekunde hochzählen der Variable für Sekunden                         
      sek = 0;                  //wenn diese 60 erreicht, dann wird sie auf null zurückgesetzt
        if(++min == 60){        //und die Variable für Minuten wird um eins hochgezählt
      min = 0;                //wenn diese 60 erreicht, dann wird sie auf null zurückgesetzt
          if(++std == 24){      //und die Variable für Stunden wird um eins hochgezählt
       std = 0;              //wenn diese 60 erreicht, dann wird sie auf null zurückgesetzt
      }
    }
      }
    }
  }
}

void timer (unsigned long time_soll) {
  time_ist = 0;                  // Vergleichsvariable wieder 0 setzen  
  while (time_soll >= time_ist) {}  // Abwarten bis die gewünschte Zeit abgelaufen ist
}

int zeit (int einheit, int umbruch,const char* name){ //übertragen des aktuellen Werts (leichter nachzustellen), der Zahl bis welche sie gehen darf (für Stunden 24, für Minuten 60 und für Sekunden ebenfalls 60) und der String welcher die Einheit angibt, welche abgegfragt wird
  lcd_clrscr ();                 // der Inhalt des Dispays wird gelöscht
  lcd_puts (name);               // der Name der abgefragten Zeiteinheit wird ausgegeben
  itoa( einheit, Buffer, 10 );   // wandelt die Integerzahl von einheit in einen String um, welcher im Array Buffer gespeichert wird (die 10 bedeutet, dass der Integerwert dezimal ist)
  lcd_puts (Buffer);             // String des aktuellen Werts der Zeiteinheit wird ausgegeben 
  timer(150);                      // kurzes Abwarten, da sonst wegen Prellung die Eingabe von Minuten und Sekunden übersprungen wird
  while(PIND & (1<<PIND4) )      // solange bis der rechte Taster gedrückt wird, kann der Wert der abgefragten Zeiteinheit geändert werden
    if(!(PIND & (1<<PIND3) )) {  // wenn der linke Taster gedrückt wird, dann soll folgendes gemacht werden
    if(++einheit == umbruch) einheit = 0; //der aktuelle Wert soll um eins erhöht werden, falls er größer ist als er sein darf, wird er wieder auf 0 gesetzt
    lcd_clrscr ();               // der Inhalt des Dispays wird gelöscht
    lcd_puts (name);             // der Name der abgefragten Zeiteinheit wird ausgegeben
      itoa( einheit, Buffer, 10 ); // wandelt die Integerzahl von einheit in einen String um, welcher im Array Buffer gespeichert wird (die 10 bedeutet, dass der Integerwert dezimal ist)
    lcd_puts (Buffer);           // String des aktuellen Werts der Zeiteinheit wird ausgegeben
    timer(50);                   // kurzes Abwarten, da sonst der Wert der Zeiteinheit aufgrund von Prellungen unkontrolliert inkrementiert werden würde
  }
  return einheit;                  // überträgt den Wert in die entsprechende Variable von std, min oder sek
};

void stellen(){
  gestellt = 0;                        // damit die Sekunden nicht weiterlaufen
  std = zeit(std,24,"Stunden: ");      // Aufrufen der Funktion zum Stellen der Stunden
  min = zeit(min,60,"Minuten: ");      // Aufrufen der Funktion zum Stellen der Minuten 
  sek = zeit(sek,60,"Sekunden: ");     // Aufrufen der Funktion zum Stellen der Sekunden
  gestellt = 1;                        // Uhr läuft ab sofort
}

int main (void) {          // Beginn des Hauptprogramms

  PORTD= 0x18;             // PULLUP-Widerstand von PORT D4 und D3 aktiviert
  DDRD = 0x00;             // PORTD auf Input setzen  
  lcd_init (LCD_DISP_ON);  // initialisiert das Dispay
  TCCR1A = 0;             // Timer arbeitet als Timer und nicht als PWM    
  TCCR1B = 1 <<CS10;      // Quelle ist der ungeteilte Quarztakt 
  TCCR1B |= 1 <<WGM12;     // Clear Timer on Compare Match
  OCR1A = 64000 ;        // Output Compare Register auf 64000 setzen entspricht 4 ms
  TIMSK = 1 << OCIE1A;      // Interrupt setzen bei Output Compare Match 
  sei();                   // Interrupts einschalten
  stellen();               // Aufrufen der Funktion zum Stellen
  timer(150);              // Abwarten, damit nicht sofort erneut in den Stellmodus gesprungen wird
               

  for (;;){                // Endlosschleife
  timer(150);                  // Abwarten, damit das Display was anzeigt, Uhrzeit läuft im Hintergrund weiter
    lcd_clrscr ();               // der Inhalt des Dispays wird gelöscht
  lcd_puts ("    ");           // leere Stellen werden auf dem Display ausgegeben um die Uhrzeit zentriert darzustellen
    if(std < 10) lcd_puts("0");  // gibt die Ziffer 0 aus, wenn die die "Stundenzahl" einstellig ist, damit die "Stundenzahl" immer zweistellig ist
  itoa( std, Buffer, 10 );     // wandelt die Integerzahl von std in einen String um, welcher im Array Buffer gespeichert wird (die 10 bedeutet, dass der Integerwert dezimal ist)
  lcd_puts (Buffer);           // String der aktuellen "Stundenzahl" wird ausgegeben
  lcd_puts(":");               // das Trennungszeichen wird ausgegeben
    if(min < 10) lcd_puts("0");  // gibt die Ziffer 0 aus, wenn die die "Minutenzahl" einstellig ist, damit die "Minutenzahl" immer zweistellig ist
    itoa( min, Buffer, 10 );     // wandelt die Integerzahl von min in einen String um, welcher im Array Buffer gespeichert wird (die 10 bedeutet, dass der Integerwert dezimal ist)
  lcd_puts (Buffer);           // String der aktuellen "Minutenzahl" wird ausgegeben
  lcd_puts(":");               // das Trennungszeichen wird ausgegeben
  if(sek < 10) lcd_puts("0");  // gibt die Ziffer 0 aus, wenn die die "Sekundenzahl" einstellig ist, damit die "Sekundenzahl" immer zweistellig ist
    itoa( sek, Buffer, 10 );     // wandelt die Integerzahl von min in einen String um, welcher im Array Buffer gespeichert wird (die 10 bedeutet, dass der Integerwert dezimal ist)
  lcd_puts (Buffer);           // String der aktuellen "Sekundenzahl" wird ausgegeben
    if(!(PIND & (1<<PIND4))) stellen();    // wenn der rechte Taster gedrückt wird, kann die Uhr erneut gestellt werden
  };
}

Für Verbesserungsvorschläge bin ich offen :)

Danke

Autor: Werner Hoch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier zwei Links zum Thema:
Beitrag "Die genaue Sekunde / RTC"
http://www.mikrocontroller.net/articles/AVR_-_Die_...

Ich denke dein Code müsste soweit funktionsieren.

Ich würde trotzdem die timer() Funktion entfernen und statdessen eine 
einfache Variable für das Neuzeichen des Displays verwenden:

for (;;) {
  if (redraw) {
    redraw = 0;
    LCD_.....     //alles neu zeichnen
  }
}


In der Timerfunktion, bzw. in jeder Funktion die den Inhalt der Anzeige 
verändert würde die (globale) Variable redraw auf 1 gesetzt werden.
Die Anzeige wird dann aktualisiert.

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.