-         

Ergebnis 1 bis 5 von 5

Thema: Timer Routine -- Ungenau

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    06.07.2004
    Beiträge
    122

    Timer Routine -- Ungenau

    Anzeige

    Bin wieder auf ein neues "Problemchen" gestossen.

    Ich hab mir eine Timer Routine geschrieben, bei der ich den Timer Initialisieren kann und danach die Zeit in ms angeben kann und eine Verzögerung mit der gewünschten Zeit bekomme. Ich habe fix meinen 4MHz Quarz eingestellt und den Prescaler 1024 gewählt. Nun habe ich das Problem, dass ich auf die ms etwa 1/2 ms abweichung habe. Das macht bei 10ms fast schon eine ganze ms aus.... und ich möchte irgendwann mal eine Uhr machen (jajaja, DCF77 wäre auch eine Möglichkeit). Aber ich will halt eine Timer-Routine, auf die ich immer wieder zurückgreifen kann....

    Hier mal mein Code. Ich könnte mir denken, dass die Abweichung von den vielen Rechenbefehlen kommt. Gäbe es eine andere Möglichkeit das alles zu programmieren oder wäre es besser in Assembler ein paar Stellen zu schreiben? Danke


    Code:
    /**************************************************************************************/
    * Erstelldatum: 31.01.2005
    * Programmname: timer-src.c
    * Funktion: Timer-Routine für ms-genaue Zeitschleifen
    ***************************************************************************************/
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    
    volatile float a,i,time;
    
    SIGNAL(SIG_OVERFLOW1)
    {
    	a=0;
    }
    
    void timer_init(void)
    {
    	TIMSK=0x80;
    	TCCR1B=0x05;
    }
    
    void timer_set(void)
    {
    	i=4000000/1024;
    	i=1/i;
    	i=time/i;
    	i=65536-i;
    	TCNT1=i;
    }
    
    void timer(float zeit_ms)
    {
    	i=0;
    	a=1;
    	time=zeit_ms/1000;
    	timer_set();
    	sei();
    	while(a);
    	cli();
    	TCNT1=i;
    	return;
    }
    
    
    
    /*---------------------- Testprogramm ------------------------------------------------*/
    
    int main(void)
    {
    	DDRC=0xFF;			// PORTC als Ausgang definieren
    	PORTC=0x00;			// Alle LED's aus
    	timer_init();		// Timer initialisieren
    	while(1)			// Endlosschleife
    	{
    		timer(10);		// 10ms warten
    		PORTC=0xFF;		// Alle LED's an
    		timer(10);		// 10ms warten
    		PORTC=0x00;		// Alle LED's aus
    	}
    }

  2. #2
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Hi Kollege.
    Ich hab deine Rechnung ins Excel eingetragen


    Code:
    T_ms	time	    I.1	     I.2	     I.3	TCNT1
    10	ms/1000	4Mhz/1024	  1 /  I.1     time/i.2	65536 - I.3
    10	0,01	3906,25	0,000256	39,0625	65496,9375
    Irgendwie wirst du dich mit den Dezimalstellen beschäftigen müssen, denn ohne Runden zwickt er die weg, und dann fehlt fast ein 1-er.
    mfg robert

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    06.07.2004
    Beiträge
    122
    Diese Frage habe ich mir beim programmieren des Rechnungsschrittes auch gefragt. Ich habe dann einfach ohne weiteres Vorgehen weitergemacht, weil ich schlicht nicht weiss wie ich runden soll.... Es gäbe sicher einen Standartbefehl in Stdio oder so... aber das braucht halt wieder enorm Speicher (hab schlechte Erfahrungen gemacht).

    Vorschläge zum runden?


    Nachtrag:
    Hab jetzt mal mit dem Rechner einen Wert ausgerechnet und gerundet.... dann manuell ins TCNT1 geschrieben... gibt mir einen für mich genug genauen Wert an. Wenn ich jedoch nebenbei auch noch meine Rechenschritte durchs Programm laufen lasse, gehen etwa (bei 10ms) .3-.4 ms verloren....
    Es liegt vielleicht doch an den Rechenschritten, die zuviel Zeit benötigen.....

  4. #4
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Ist sicher so, wie du sagst, Ich würd mal fix den Wert für EINE mS vorher ausrechenen und die function "timer()" auf Vielfache vom mS einschränken.
    Ein bißchen sparen kannst du auch:
    Statt
    i=4000000/1024;
    i=1/i;
    i = time / i
    schreib doch
    #define DIVISOR 1024 / 4000000

    i = time / DIVISOR

    is nicht viel, aber Kleinvieh mach auch mist. mfg robert

    und

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    06.07.2004
    Beiträge
    122
    Hab jetzt verschiedene Möglichkeiten durchprobiert und bin zum Schluss gekommen, dass ich das mit der Routine lieber lasse... die Unterprogramme fressen am meisten Zeit... ich lass es und schreibe die Befehle direkt ins Programm. Timer ist ja schnell reingeschrieben und dann habe ich auf 1ms eine Abweichung von 0.02ms und das sind genau noch ein paar Takte für die wenigen Befehle die es braucht... das genügt glaub auch für eine Uhr

Berechtigungen

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