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.
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.
Hier einmal der Gesamtcode, der Controller läuft mit 1MHz Gruß
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.
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?
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ß
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
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.
@ Peter Das verstehe ich jetzt nicht ganz! Hast du vielleicht ein Bsp.
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.
... 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.