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ß
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.
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.
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ß
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ß
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 ;)
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.
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.
> 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"
> 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.
> 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.
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).
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...
> 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.