Forum: Compiler & IDEs genaue Uhrzeit?


von Steffen T. (Gast)


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..
1
#include "lcd.c"
2
#include <avr/interrupt.h>
3
4
volatile unsigned long time_ist;   // globale Vergleichsvariable
5
unsigned char Buffer[30];          // globales Array für die Strings
6
unsigned int std = 0;              // globale Variable für die Sekunden
7
unsigned int min = 0;              // globale Variable für die Minuten
8
unsigned int sek = 0;              // globale Variable für die Stunden
9
unsigned int counter = 0;
10
unsigned int gestellt = 0;         // Uhr gestellt = 1; Uhr ist nicht gestellt = 0;
11
12
ISR (TIMER1_COMPA_vect  ) {
13
  time_ist++;                   //nach jedem Interrupt die Vergleichsvariable hochzählen
14
  if ( gestellt == 1){
15
    if(++counter >= 250){  
16
    counter = 0;         
17
      if(++sek == 60){          //nach einer Sekunde hochzählen der Variable für Sekunden                         
18
      sek = 0;                  //wenn diese 60 erreicht, dann wird sie auf null zurückgesetzt
19
        if(++min == 60){        //und die Variable für Minuten wird um eins hochgezählt
20
      min = 0;                //wenn diese 60 erreicht, dann wird sie auf null zurückgesetzt
21
          if(++std == 24){      //und die Variable für Stunden wird um eins hochgezählt
22
       std = 0;              //wenn diese 60 erreicht, dann wird sie auf null zurückgesetzt
23
      }
24
    }
25
      }
26
    }
27
  }
28
}
29
30
void timer (unsigned long time_soll) {
31
  time_ist = 0;                  // Vergleichsvariable wieder 0 setzen  
32
  while (time_soll >= time_ist) {}  // Abwarten bis die gewünschte Zeit abgelaufen ist
33
}
34
35
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
36
  lcd_clrscr ();                 // der Inhalt des Dispays wird gelöscht
37
  lcd_puts (name);               // der Name der abgefragten Zeiteinheit wird ausgegeben
38
  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)
39
  lcd_puts (Buffer);             // String des aktuellen Werts der Zeiteinheit wird ausgegeben 
40
  timer(150);                      // kurzes Abwarten, da sonst wegen Prellung die Eingabe von Minuten und Sekunden übersprungen wird
41
  while(PIND & (1<<PIND4) )      // solange bis der rechte Taster gedrückt wird, kann der Wert der abgefragten Zeiteinheit geändert werden
42
    if(!(PIND & (1<<PIND3) )) {  // wenn der linke Taster gedrückt wird, dann soll folgendes gemacht werden
43
    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
44
    lcd_clrscr ();               // der Inhalt des Dispays wird gelöscht
45
    lcd_puts (name);             // der Name der abgefragten Zeiteinheit wird ausgegeben
46
      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)
47
    lcd_puts (Buffer);           // String des aktuellen Werts der Zeiteinheit wird ausgegeben
48
    timer(50);                   // kurzes Abwarten, da sonst der Wert der Zeiteinheit aufgrund von Prellungen unkontrolliert inkrementiert werden würde
49
  }
50
  return einheit;                  // überträgt den Wert in die entsprechende Variable von std, min oder sek
51
};
52
53
void stellen(){
54
  gestellt = 0;                        // damit die Sekunden nicht weiterlaufen
55
  std = zeit(std,24,"Stunden: ");      // Aufrufen der Funktion zum Stellen der Stunden
56
  min = zeit(min,60,"Minuten: ");      // Aufrufen der Funktion zum Stellen der Minuten 
57
  sek = zeit(sek,60,"Sekunden: ");     // Aufrufen der Funktion zum Stellen der Sekunden
58
  gestellt = 1;                        // Uhr läuft ab sofort
59
}
60
61
int main (void) {          // Beginn des Hauptprogramms
62
63
  PORTD= 0x18;             // PULLUP-Widerstand von PORT D4 und D3 aktiviert
64
  DDRD = 0x00;             // PORTD auf Input setzen  
65
  lcd_init (LCD_DISP_ON);  // initialisiert das Dispay
66
  TCCR1A = 0;             // Timer arbeitet als Timer und nicht als PWM    
67
  TCCR1B = 1 <<CS10;      // Quelle ist der ungeteilte Quarztakt 
68
  TCCR1B |= 1 <<WGM12;     // Clear Timer on Compare Match
69
  OCR1A = 64000 ;        // Output Compare Register auf 64000 setzen entspricht 4 ms
70
  TIMSK = 1 << OCIE1A;      // Interrupt setzen bei Output Compare Match 
71
  sei();                   // Interrupts einschalten
72
  stellen();               // Aufrufen der Funktion zum Stellen
73
  timer(150);              // Abwarten, damit nicht sofort erneut in den Stellmodus gesprungen wird
74
               
75
76
  for (;;){                // Endlosschleife
77
  timer(150);                  // Abwarten, damit das Display was anzeigt, Uhrzeit läuft im Hintergrund weiter
78
    lcd_clrscr ();               // der Inhalt des Dispays wird gelöscht
79
  lcd_puts ("    ");           // leere Stellen werden auf dem Display ausgegeben um die Uhrzeit zentriert darzustellen
80
    if(std < 10) lcd_puts("0");  // gibt die Ziffer 0 aus, wenn die die "Stundenzahl" einstellig ist, damit die "Stundenzahl" immer zweistellig ist
81
  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)
82
  lcd_puts (Buffer);           // String der aktuellen "Stundenzahl" wird ausgegeben
83
  lcd_puts(":");               // das Trennungszeichen wird ausgegeben
84
    if(min < 10) lcd_puts("0");  // gibt die Ziffer 0 aus, wenn die die "Minutenzahl" einstellig ist, damit die "Minutenzahl" immer zweistellig ist
85
    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)
86
  lcd_puts (Buffer);           // String der aktuellen "Minutenzahl" wird ausgegeben
87
  lcd_puts(":");               // das Trennungszeichen wird ausgegeben
88
  if(sek < 10) lcd_puts("0");  // gibt die Ziffer 0 aus, wenn die die "Sekundenzahl" einstellig ist, damit die "Sekundenzahl" immer zweistellig ist
89
    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)
90
  lcd_puts (Buffer);           // String der aktuellen "Sekundenzahl" wird ausgegeben
91
    if(!(PIND & (1<<PIND4))) stellen();    // wenn der rechte Taster gedrückt wird, kann die Uhr erneut gestellt werden
92
  };
93
}

Für Verbesserungsvorschläge bin ich offen :)

Danke

von Werner Hoch (Gast)


Lesenswert?

Hier zwei Links zum Thema:
Beitrag "Die genaue Sekunde / RTC"
http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.