Forum: Mikrocontroller und Digitale Elektronik Probleme mit ISR- TimerO OVF ( Uhr )


von Socke (Gast)


Lesenswert?

Sorry, mal wieder eine Uhr, habe jedoch bereits das Forum durchforstet 
und keine Lösungsidee finden können.
Ich möchte hiermit echte Zeiten erzeugen, welche ich dann in der Main 
weiter verwenden kann. Durch Berechnung des Reload-Wertes, wird die ISR 
jetzt jede ms ausgelöst.

//Anlegen der erforderlichen Globalen Variablen

volatile uint16_t ms;
volatile uint8_t sek,min,std;

//Interrupt Service Routine zur Erzeugung der Zeiten
ISR(TIMER0_OVF_vect){
  TCNT0=131;

  ms++;      //ms um einen erhöhen

  if(ms==1000){  //Wenn ms den Wert 1000 hat,
    sek++;    //sek. um einen erhöhen,
    ms=0;    //und ms auf Null setzten.
  }

  if(sek==60){  //Wenn sek den Wert 60 hat,
    min++;    //min. um einen erhöhen,
    sek=0;    //und sek. auf Null setzen.
  }

  if(min==60){  //Wenn min den Wert 60 hat,
    std++;    //std. um einen erhöhen,
    min=0;    //und min. auf NUll setzen.
  }
}

In Hauptprogramm habe ich eine Variable"Restzeit" wovon die Gesamtzeit 
der ISR abgezogen und weiter verwendet werden soll. Problem er wird nix 
von der Gesamtzeit abgezogen, und auf dem Display steht dauerhaft 
Restzeit 105.


in der main

//GESAMTZEIT  1,45 STD ( 105min)
  unsigned char restzeit_str[8];
  uint8_t restzeit=105-((std*60)+min);


  sprintf(restzeit_str,"%d",restzeit); //Schreiben der Temperatur in 
String

  lcd_setcursor( 0, 3 ); // setze Courser in die erste Zeile auf Platz 
Null

  lcd_string(restzeit_str); // Ausgabe der Restzeit auf dem Display



Hoffe ich habe mich nicht zu kompliziert Ausgedrückt, und jemand hat 
eine Idee zur Lösung meines Problems. Verwenden tue ich einen ATmega und 
Atmel Studio 6

Gruß

von Peter M. (Gast)


Lesenswert?

1. Mit welcher Taktfrequenz läuft Dein µC?
2. Hast Du schon einmal den Inhalt der Variablen std und min überprüft?
   Gib diese Werte einmal auf dem Display aus, damit Du kontrollieren
   kannst, ob sich diese Wert verändern.
   Ich glaube, dass Deine ISR nicht funktioniert!

3. Poste einmal den kompletten Code, sonst sieht man nicht wie Du was
   initialisierst.

von holger (Gast)


Lesenswert?

Overflow Interrupt mit neusetzen des Timers im
Interrupt ist für eine Uhr völlig ungeeignet.
Dafür nimmt man den CTC Modus des Timers.

von Socke (Gast)


Angehängte Dateien:

Lesenswert?

Hier einmal der Gesamtcode, der Controller läuft mit 1MHz

Gruß

von Peter M. (Gast)


Lesenswert?

Ich gehe einmal davon aus, dass Du einen Mega32 verwendest.?

Das,
1
TCCR0=(0<<WGM01)|(0<<WGM00)|(0<<COM01)|(0<<COM00)|(0<<CS02)|(1<<CS01)|(0<<CS00);
musst Du nicht machen. Es reicht, wenn Du nur die Bits angibst, die Du 
für Deine Konfiguration brauchst.

Besser ist allerdings der CTC-Mode, d.h. der Timer läuft ohne Dein zutun
mit dem voreingestellten Wert weiter
Hier ein Beispiel:
1
#define PRESCALER0      (1 << CS01)   // 8
2
3
TIMSK  |= (1 << OCIE0);  // OCIE0 
4
5
TCCR0 |= PRESCALER0| (1 << WGM01);  // Prescaler and CTC Mode WGM01 
6
    TCNT0  = 0;         
7
  OCR0 = 131;
8
       sei();
Entferne das *sei()* aus der while-Schleife. Es reicht, wenn Du es 
einmal aufrufst.

Deine ISR änderst Du dahin gehend:
1
ISR(TIMER0_COMP_vect)
Baue Dir in die ISR eine Portausgabe rein, die Dir mittels LED anzeigt, 
ob die ISR überhaupt läuft. Also eine blinkende LED an irgend einem 
Port.
Mit ein Scope kann man dann auch schön sehen, ob die Zeiten stimmen.

von Peter M. (Gast)


Lesenswert?

In Deinem Source steht:
1
 //einschalten der ISR Timer0 Overflow
2
  TIMSK |(1<<TOIE0);

Da fehlt das *=* Zeichen.

Kann nicht funktionieren!!!

Meckert der Compiler nicht?

von Socke (Gast)


Angehängte Dateien:

Lesenswert?

Vielen Dank Peter für deine Mühe, kann mir aber auch bitte jemand sagen 
warum der CTC Mode besser ist als der Overflow? Möchte es ja auch 
verstehen.

Aber HILFE

Jetzt habe ich allerdings ein weiteres Problem, die Verwendung des 
Timers scheint mir mein 1-Wire Bus zu zerstören. Hierüber lese ich eine 
Temperatur ein. Fängt der Timer an zu "zählen" zeigt das Display nur 
noch Mist an ( s. Foto Anhang). Ist die ISR zu schnell mit jeder ms?

Gruß

von mikel (Gast)


Lesenswert?

Socke schrieb:
> Sorry, mal wieder eine Uhr, habe jedoch bereits das Forum durchforstet
> und keine Lösungsidee finden können.

Hab mir schon gedacht, daß da nichts Vernünftiges drin stehen kann:
http://www.mikrocontroller.net/topic/156661?goto=new#new

von Socke (Gast)


Lesenswert?

Die falsche Anzeige der Temperatur habe ich in Griff bekommen, indem ich 
die ISR vor der Temperaturwandlung mit cli() angehalten und hinterher 
wieder eingeschaltet habe sei(). Jedoch dauert die ganze 
Temperaturwandlung ja auch ein wenig, so das die Zeit verfälscht wird. 
soll heißen 1 echte Minute dauert im Programm 4,03 Minuten.

@Mikel, du wolltest mir sicherlich damit durch die Blume etwas sagen, 
jedoch ist es als Anfänger einfach teilweise schwer zu verstehen was 
hier so steht. Auch wenn die Uhr echt Hammer ist, die sie da gebaut 
haben.


Gruß

von Sascha (Gast)


Lesenswert?

Peter M. schrieb:
> In Deinem Source steht: //einschalten der ISR Timer0 Overflow
>   TIMSK |(1<<TOIE0);
>
> Da fehlt das *=* Zeichen.
>
> Kann nicht funktionieren!!!
>
> Meckert der Compiler nicht?

Ist doch valider Code, Da wird Timsk mit einem Bit verodert und das 
Ergebnis davon dann nach /dev/null geschoben ;)

von Peter D. (peda)


Lesenswert?

Socke schrieb:
> Jedoch dauert die ganze
> Temperaturwandlung ja auch ein wenig

Deshalb sperrt man die Interrupts ja auch nur eine Bitzeit (60µs) lang. 
Zwischen den Bits können beliebig lange Abstände liegen, es gibt keine 
Maximalzeit.

von Socke (Gast)


Lesenswert?

@ Peter
Das verstehe ich jetzt nicht ganz! Hast du vielleicht ein Bsp.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Socke schrieb:
> Vielen Dank Peter für deine Mühe, kann mir aber auch bitte jemand sagen
> warum der CTC Mode besser ist als der Overflow? Möchte es ja auch
> verstehen.

 Weil CTC eben genau einzustellen ist.
 Wenn z.B. 250 nicht genau 1us ist, dann kann man mit 249 oder 251 noch
 feiner nachstellen.
 Und da der Timer automatisch auf Null gesetzt wird, braucht man auch
 nichts abzuziehen.
 Overflow benutzt man meistens um main() darauf aufmerksam zu machen,
 dass eine gewisse Zeitspanne verstrichen ist, ohne das es jetzt um
 us genau sein muss, z.B. Taste nicht gedruckt, Temp. nicht erreicht...
 Also, Overflow startet man wenn irgendein Prozess startet, CTC ist
 eben fur deinen Fall gedacht - einen Wert in genau bestimmten Zeit-
 abstanden erhohen oder erniedrigen.

von Carl D. (jcw2)


Lesenswert?

> warum ist CTC besser

Weil bei CTC der Zähler unabhängig von 0..OCR0A zählt.

Ob der COMP0A_vect dann sofort oder wegen gerade gesperrten Int's erst 
in 100µs läuft, beeinflußt zwar den aktuellen Zeitpunkt, aber dieser 
Fehler summiert sich nicht auf.

wenn also Clock=1MHZ
          Timer0: Prescaler=1 CTC-Mode OCR0A=100 TIMSK0.OCIE0A=1

dann wird alle 1ms das Bit TIFR0.OCF0A gesetzt und wenn man nicht länger 
als "1ms - Interrupt-Laufzeit" die Interrupts gesperrt hatte, geht kein 
Tick verloren. Und im Rahmen der Quarz-Genauigkeit stimmt das auch noch 
nach Wochen.

Für "Uhr" gibt es aber auch folgendes Standardwerk von PeDa:
Beitrag "Die genaue Sekunde / RTC"

von Stefan F. (Gast)


Lesenswert?

> kann mir aber auch bitte jemand sagen
> warum der CTC Mode besser ist als der Overflow?

Interruptroutinen werden nicht "sofort" ausgeführt, wenn das Ereignis 
auftritt, sondern einige Takte später. Wenn in diesem Moment die 
Interrupts gerade durch cli() gesperrt waren, dann kann die Verzögerung 
sogar beliebig lange ausfallen.

Jedenfalls weist du nie genau, wie lange es vom Zeitereignis 
(millisekunde) bis zum Aufrufen der ISR dauert. Deine Uhr wird also zu 
langsam laufen. mal mehr, mal weniger. Wieviel genau, ist schwer 
vorhersehbar.

Im CTC Modus wir der Timer durch einen Schaltkreis in Hardware bei 
Erreichen des Compare-Werte zurück auf 0 gestellt. Und zwar sofort, ohne 
Verzögerung. Egal, was sonst noch so los ist.

Abgesehen davon: Die üblichen µC Quarze sind für Uhren nicht sehr gut 
geeignet. Da musst du schon mit mehreren Minuten Abweichung pro Monat 
rechnen. Wenn es genau sein soll, synchronisiere mit einem Funksignal 
(z.B. DCF-77) oder mit einem separaten Echzeituhren-IC. Diese IC's 
liefern schon ohne manuelle Kalibrierung erstaunlich genaue Zeiten. 
Typischerweise weniger als 1 Minute Abweichung pro Monat.

von Stefan F. (Gast)


Lesenswert?

> wenn also Clock=1MHZ
>         Timer0: Prescaler=1 CTC-Mode OCR0A=100 TIMSK0.OCIE0A=1
> dann wird alle 1ms das Bit TIFR0.OCF0A gesetzt

Hö? Nach genau 100 Takten wird der Compare-Wert erreicht und der Zähler 
auf 0 zurück gesetzt. 100 Takte bei 1Mhz ergeben in meinem Kopf 0,1ms.

von Peter D. (peda)


Lesenswert?

Stefan U. schrieb:
> Die üblichen µC Quarze sind für Uhren nicht sehr gut
> geeignet.

Gerade die MHZ-Quarze sind sehr stabil. Allerdings muß man sie einmal 
kalibrieren, dann sind wenige Sekunden/Jahr erreichbar.

Ich hatte mal 2 DS1994 (32kHz RTC mit interner Batterie) Sample 
bekommen, die waren ohne Korrekturrechnung unbrauchbar (Abweichung 
einige Sekunden/Tag).

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Peter D. schrieb:
> Gerade die MHZ-Quarze sind sehr stabil. Allerdings muß man sie einmal
> kalibrieren, dann sind wenige Sekunden/Jahr erreichbar.

 Genau.
 Abweichung (Fehler) ist unwichtig, Stabilität ist wichtig.Wir hatten
 sogar DS1307 mit Korrekturen auf weniger als 1 Sekunde/Monat gekriegt.

> Ich hatte mal 2 DS1994 (32kHz RTC mit interner Batterie) Sample
> bekommen, die waren ohne Korrekturrechnung unbrauchbar (Abweichung
> einige Sekunden/Tag).

 Unsere letzte Bestellung (30 St. DS3231) war eine Enttäuschung.
 8 Stück hatten Abweichung von mehreren Sekunden pro Minute (!),
 Temperatur-Register lieferten zuffälige Werte, Aging Offset kann nicht
 verändert werden...

von Stefan F. (Gast)


Lesenswert?

> Abweichung von mehreren Sekunden pro Minute

Das ist ja enttäuschend, da muss man sich schon fragen, warum man 
überhaupt einen Uhren-IC verwendet hat. Ich hatte wohl bisher immer 
Glück, meine (ca 7) Uhren IC's liefen immer so genau, dass sie nicht 
negativ auffielen. Also verglauchbar mit allen anderen Uhren im Haus.

von Bernd (Gast)


Lesenswert?

... 8 Stück hatten Abweichung von mehreren Sekunden pro Minute ...

Glaube ich nicht.

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.