Timer0
Montag, 21. Mai 2012
 
 

PIC Mikrocontroller Forum  |  PIC Mikrocontroller  |  CCS Compiler  |  Timer (CCS)  |  Timer0 « vorheriges nächstes »
Seiten: [1] Nach unten Drucken
Autor Thema: Timer0  (Gelesen 2873 mal)
 
Sascha
Newbie
*
Offline Offline

Beiträge: 46


Profil anzeigen
« am: August 09, 2007, 16:29:23 »

Hallo zusammen,
ich hab ein Problem mit der Berechnung von Timer0. Soweit ich das raus gelesen habe, berechnet man den Timer so: Zeit = (1/ Frequenz) * Set_timer0 * Teiler. Ich versuche alle 100ms also 0,1 sec Timer0 zu starten Berechnung: (0,1sec/(0,000001MHz) )/ 256 = 390,65
geht also nicht weil, er ja nur bis 256 zählt? Was könnte ich da machen? Einen Zähler laufen lassen ? Ach so, ich benutze einen 12F629 und den internen 4MHz Oszillator.   
 :-x
Gespeichert
cooloola
Jr. Member
**
Offline Offline

Beiträge: 52



Profil anzeigen
« Antworten #1 am: August 09, 2007, 20:54:53 »

Hallo,

ich habe mir mal das Datenblatt angeschaut. Dieser PIC hat auch den 16 Bit Timer "Timer1".
Damit lassen sich 100ms problemlos erzeugen? Wird der Timer1 anderweitig verwendet?

Wenn wir mal davon ausgehen, dass nur der Timer0 zur Verfügung steht, würde ich folgendermaßen vorgehen:


  • Ein Takt des internen Oszillators benötigt 1µs (Fosc/4) -> das entspricht der Ausführungszeit von einem Befehl

  • Wird der Vorteiler auf 32 gestellt, dann werden 32 Takte benötigt, bevor der TMR0 einmal hochzählt

  • Wird der TMR0 auf 130(dezimal) voreingestellt, dann kann er 125 mal hochgezählt werden, bevor er überläuft.
    Er würde also nach genau 4ms überlaufen und einen Interrupt auslösen.

  • In der Interrupt Routine müsste dann ein Zählregister 25mal hochgezählt werden, damit die 100ms erreicht werden.


Jetzt kommen die Haken:

Wenn der Interrupt ausgelöst wurde, dann zählt der Vorteiler natürlich weiter.
Das bedeutet, dass nach 32 Takten / 32 µs / 32 Befehlen der TMR0 wieder erhöht wird.
Also muss der TMR0 bis dahin erneut auf 130(dezimal) eingestellt werden, damit er die nächsten 4ms zählen kann.

Es stehen also nur 32 Befehle für die Interrupt Sevice Routine (ISR) zur Verfügung.

Darin muss das Zählregister erhöht und mit dem Endwert 25 verglichen werden, der TMR0 muss neu geladen werden und vielleicht muss das W und das Status Register gesichert und wiederhergestellt werden. Nach meiner Rechnung dürfte das ausreichen (in Assembler).

Wenn die ISR verlassen wurde, stehen 4 ms (4000 Befehle) für das Hauptprogramm zur Verfügung, bevor der TMR0 die nächste Unterbrechung anfordert.


Letztendlich ist die Frage, was passieren soll, wenn die 100ms erreicht sind.
Falls gleich die nächsten 100ms loslaufen sollen, dann darf der weitere Programmablauf nicht
in der ISR stattfinden.


Gruß,
Cooloola
Gespeichert
Sascha
Newbie
*
Offline Offline

Beiträge: 46


Profil anzeigen
« Antworten #2 am: August 10, 2007, 06:28:38 »

Vielen dank für die ausführliche Antwort. Ich werde mich gleich mal ans Werk machen  :mrgreen:
Gespeichert
Sascha
Newbie
*
Offline Offline

Beiträge: 46


Profil anzeigen
« Antworten #3 am: August 10, 2007, 09:16:52 »

Ich habe mal probiert, das folgender maßen zu lösen. In der ISR habe ich einen Zähler den ich jedes Mal beim Aufruf um einen erhöhe. Außerhalb der ISR frage ich dann ab, ob der Zähler den Wert 25 erreicht hat. Ist das der Fall, setze ich den Zähler wieder auf Null. Jetzt wollte ich in der festlegten Zeit, den int_ext beim L_H Übergang benutzen, um bei einer bestimmten Anzahl von Impulsen Pin_A1 zu setzen. Doch irgendwie gelinkt es mir noch nicht richtig. Außerdem habe ich noch Probleme mit Set_tris. Könnte ich da noch ein wenig Hilfe bekommen. 

Code:
long int count;
int zaehler;

#int_ext
Hundemist()
{
count++;
}



#int_RTCC
RTCC_isr()
{
zaehler++;
}
   
   
void main()
{

   int i;
   set_timer0(130);
   set_tris_a(1);
   setup_timer_1(T1_DISABLED);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_RTCC);
   
   setup_timer_0 (RTCC_INTERNAL|RTCC_DIV_32);

   setup_counters(RTCC_INTERNAL,RTCC_DIV_1);
   ext_int_edge(L_TO_H);
   enable_interrupts(INT_EXT);
   enable_interrupts(global);

   count =0;
   zaehler = 0;
   

   while (1)
   {


      if (zaehler >= 25)
            {
               disable_interrupts(INT_EXT);
               disable_interrupts(INT_RTCC);
               disable_interrupts(global);
               delay_ms(1);
               
                             
               if (count >= 100)
                  {
                     output_high (Pin_A1);
                     delay_ms (500); delay_ms (500);
                     output_low (Pin_A1);
                   }

               zaehler =0;
               count =0;
               enable_interrupts(INT_RTCC);
               enable_interrupts(global);
               enable_interrupts(INT_EXT);
               delay_ms(1);
               set_timer0(130);
             }


 

   }
}

« Letzte Änderung: August 10, 2007, 10:48:52 von Sascha » Gespeichert
Seiten: [1] Nach oben Drucken 
« vorheriges nächstes »
Gehe zu:  

Powered by MySQL Powered by PHP Made for Mozilla (Firefox) Made for Internet Explorer
Seite erstellt in 0.034 Sekunden mit 18 Zugriffen.
 
Top! Top!