-
        

Ergebnis 1 bis 10 von 10

Thema: Atmega 32 Uhr läuft zu schnell

  1. #1

    Idee Atmega 32 Uhr läuft zu schnell

    Anzeige

    Hallo liebe Forengemeinde. Ich frage mich nun schon seid einigen Tagen wie sich 2 Programmteile gegenseitig beeinflussen.

    Fakt ist: Die Uhr läuft erst seit der Einbindung der uart.c, uart.h und der dazugehörigen functions in der Main etwas zu schnell. (In 30 min ca. 2 Min abweichung. [Uhr geht vor])
    Jedoch verstehe ich leider nicht wodurch dies verursacht wird.
    Chip läuft mit einem 8MHz Quarz und ist richtig gefused.

    Jemand eine Idee? Bin für jeden noch so kleinen Tipp dankbar!
    Angehängte Dateien Angehängte Dateien

  2. #2
    Neuer Benutzer Öfters hier
    Registriert seit
    31.05.2005
    Beiträge
    16
    Hallo,

    2 Dinge fallen mir auf.

    1) Du rechnest 8000000 / 1024 in der clock.c. Dies ergibt 7812.5, also als integer passt es nicht genau in eine Sekunde -> deine Sekunden sind also 0.999 936 Sekunden lang (30 minuten wären aber auch nur 0,1152 Sekunden Fehler in einer halben Stunde)
    2) Du setzt bei jeden Overflow den Timer neu auf. Wenn aber gerade ein anderer Interrupt in diesem Moment bearbeitet wird, kann der entsprechende Interrupt verzögert werden. Ich würde eher vorschlagen den Timer Gleich so zu setzen dass man ihn nicht mehr anfassen muss (Clear Timer On Comparer Mode, 8000000 / 1024 -> OCR1A und statt Overflow Interrupt SIG_OUTPUT_COMPARE1A verwenden), Allerdings würde dies aber eher bedeuten dass Deine Uhr nach geht.

    Aber wo Deine 2 Minuten herkommen kann ich leider auch nicht sagen.

    -Andreas

  3. #3
    HI ich habe mal ein bisschen herumprobiert und verwende nun den Comparemode.
    Code:
           #ifndef OCR1A
    	#define OCR1A OCR1  // 2313 support
    	#endif
    	
    	#ifndef WGM12
    	#define WGM12 CTC1  // 2313 support
    	#endif
    	#define XTAL      8000000L   // nominal value
    	#define DEBOUNCE    256L        // debounce clock (256Hz = 4msec)
    	#define uchar unsigned char
    	#define uint unsigned int
    	
    	uchar prescaler;
    
            TCCR1B = (1<<WGM12) | (1<<CS10);	// divide by 1
    	// clear on compare
    	TCNT1 = 0;                          // Timmer startet mit 0
    	prescaler = (uchar)DEBOUNCE;        //software teiler
    	TIMSK = 1<<OCIE1A;  
    
           SIGNAL (SIG_OUTPUT_COMPARE1A) {
    	/************************************************************************/
    	/*      Insert Key Debouncing Here      */
    	/************************************************************************/
    	
    	if( --prescaler == 0 ){
    		prescaler = (uchar) DEBOUNCE;
    		ss++;//Addiere +1 zu Sekunden
    		LED_burned++;
    		ANALOG_ss++;
    		if (ss == 60)
    		{
    			ss = 0;
    			mm++;//Addiere +1 zu Minuten
    			if (mm == 60)
    			{
    				mm = 0;
    				hh++;//Addiere +1 zu Stunden
    				if (hh == 24)
    				{
    					hh = 0;
    				}
    			}
    		}
    	}
    	#if XTAL % DEBOUNCE
    	if (prescaler <= XTAL % DEBOUNCE)
    	OCR1A += XTAL / DEBOUNCE +1;   /* um 1 Takt längere Periode um den Rest abzutragen */
    	else
    	#endif
    	OCR1A += XTAL / DEBOUNCE;   /* kurze Periode */
    }
    Das Erfreuliche: Die Uhr Läuft nicht mehr zu schnell, dafür nun aber leider zu langsam. (Abweichung nach 5h laufzeit ca. 30 minuten. [Uhr geht zurück])

    Habe nun auch mal meine Fusesettings mitgepostet falls sich der Fehler vielleicht doch dort verbirgt.

    Grundsetzlich ist es aber schon möglich den Timer1 comparemode für eine SoftwareClock (ohne große Abweichungen) zu verwenden und gleichzeitig eine lauffähiges UART Programm zur Kommunikation mit dem PC zu haben?
    Weil großteils wird für den UART ja der Timer1 verwendet so wie ich das beurteilen kann...
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken Fusesettings.jpg  

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    31.05.2005
    Beiträge
    16
    Was willst Du mit OCR1A += XTAL / DEBOUNCE +1; bzw OCR1A += XTAL / DEBOUNCE; bezwecken?

    OCR1A sollte nur einmal beschrieben werden
    (also nicht im Interrupt) und nicht jedes mal neu. Im CTC zählt der Timer bis zu dem Wert, der im OCR1A steht und wenn er diesen Wert erreicht wird der counter automatisch auf 0 gesetzt und er fängt wieder von vorn an zu zählen (man muss also nichts von Hand wieder neu aufsetzen).

    Setze mal den Prescaler auf 256 (8Mhz / 256 = 31.25KHz). Das heißt Du benötigst 31250 Takte damit eine Sekunde vorbei ist. Also Schreibt man einmalig 31250 in das OCR1A. Jetzt sollte der Interrupt jede Sekunde aufgerufen werden.

    Die Timer sind komplett unabhängig von der UART und sollten sich nicht gegenseitig beeinflussen.

    Bei den Fuses sehe ich keine Probleme.

  5. #5
    OK ich hab den Debouncingpart weggemacht und Teste dann nun das Programm mit einem OCR1A Wert von 31250

    Bericht folgt.

    Vielen dank schonmal für die Hilfe.

  6. #6
    Leider rennt die Uhr nun übertrieben schnell hoch.

    Code:
    	#ifndef OCR1A
    	#define OCR1A OCR1  // 2313 support
    	#endif
    	
    	#ifndef WGM12
    	#define WGM12 CTC1  // 2313 support
    	#endif
    	#define XTAL      8000000L   // nominal value
    
    	TCCR1B = (1<<WGM12)| (1<<CS10);		// divide by 1						
    										// clear on compare
    	OCR1A = 31250;						// Output Compare Register
    	TCNT1 = 0;                          // Timmer startet mit 0
    	TIMSK = 1<<OCIE1A;                  // beim Vergleichswertes Compare Match
    	sei();
    
    SIGNAL (SIG_OUTPUT_COMPARE1A) {
    		ss++;//Addiere +1 zu Sekunden
    		LED_burned++;
    		ANALOG_ss++;
    		if (ss == 60)
    		{
    			ss = 0;
    			mm++;//Addiere +1 zu Minuten
    			if (mm == 60)
    			{
    				mm = 0;
    				hh++;//Addiere +1 zu Stunden
    				if (hh == 24)
    				{
    					hh = 0;
    				}
    			}
    		}
    	
    
    }
    Was mach ich denn nur falsch

  7. #7
    Erfahrener Benutzer Roboter Genie Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.410
    Blog-Einträge
    101
    Zitat Zitat von zschunky
    Setze mal den Prescaler auf 256 (8Mhz / 256 = 31.25KHz).
    zschunky hat den Prescaler schon vorgegeben, bei Dir steht was anderes.

    Code:
        TCCR1B = (1<<WGM12)| (1<<CS10);        // divide by 1                        
                                            // clear on compare
        OCR1A = 31250;                        // Output Compare Register
    Der genauere Wert für das OCR1A wäre 31249. (Formel im Datenblatt bei Timer1, Modes of Operation, CTC )

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  8. #8
    Also
    Code:
    TCCR1B = (1<<WGM12)| (1<<CS12);
    THX

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.186
    Wie wäre es mit

    TCCR1B = (1<<WGM12)| (1<<CS12);

    Dann wäre der Prescaler auf 256 gestellt.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

  10. #10
    JO dankeschön.

    Bin noch ein Noob was uC angeht nimmt Rücksicht.

Ähnliche Themen

  1. Atmega 32 mit 16 mhz quarz zu schnell ?
    Von bluePumpkin im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 5
    Letzter Beitrag: 25.01.2011, 00:15
  2. Antworten: 2
    Letzter Beitrag: 25.02.2009, 10:39
  3. Wie schnell läuft ein Schrittmotor
    Von Hellmut im Forum Motoren
    Antworten: 1
    Letzter Beitrag: 20.03.2008, 19:29
  4. Hilfe! Uhr läuft zu schnell?
    Von HPM im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 6
    Letzter Beitrag: 28.02.2007, 22:13
  5. PCF 8583 läuft zu schnell
    Von Zeroeightfifteen im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 5
    Letzter Beitrag: 02.04.2006, 17:54

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •