Forum: Mikrocontroller und Digitale Elektronik PIC24 timer / clock Frage


von Stefan_L_01 (Gast)


Lesenswert?

Hallo

Ich programmiere mir gerade eine BusPirate mit einem PIC24FJ um.

Bei der Timerprogrammierung bin ich ziemlich genau um den Faktor 4 zu 
langsam (verdächtig), ich finde aber den Fehler nicht. Vielleicht kann 
mir jemand helfen?

Ich habe das LED BLINK DEMO als Ausgangscode verwendet, benutze jetzt 
aber in der Config (MPLAB X) das FNOSC_FRCDIV keyword, Clock sollte also 
intern 8Mhz sein.
Alle PostScaler sind auf 1 bzw. aus.
Das sollte ein Fcy von 4Mhz ergeben (Cyclus)

Dann berechnet sich doch der Startup für einen Timer (16Bit) zu:
0xffff - 4000
wenn der Interrupt beim Overflow jede Millisekund kommen soll, oder?

Ich dekrementiere in der ISR einen Counter der mit 1000 initialisiert 
ist, also müsste ich ja alle Sekunde einen Event haben, dann wenn der 
Counter 0 wird. Dann reinitialisiere ich ihn auf 1000 und mache eine 
Ausgabe über die UART. Die kommt im Terminalprogramm aber 15-16x pro 
Minute, also ziemlich genau alle 4sek.

Wo kann der Fehler liegen?
Für jeden Tip dankbar
Gruß
Stefan

von Max H. (hartl192)


Lesenswert?

Poste mal deinen Code...

von Michael S. (rbs_phoenix)


Lesenswert?

Interessant wäre ein Code, um zu gucken, wie der Timer konfiguriert ist. 
Außerdem wäre es gut zu wissen, welchen PIC24 du meinst, am besten mit 
Link zum Datenblatt. Vielleicht hast du doch irgendwo nen Fehler bei der 
Timerkonfig. Zur kontrolle würde ich beim Sekundentakt auch eine LED 
blinken lassen, nicht das der Fehler irgenwo beim UART liegt. Denke aber 
eher nicht.

Zur Not nimmste nen PLLx4

von Stefan_L_01 (Gast)


Lesenswert?

Hallo
Also ich bin relativ neu hier, mal sehen ob das mit code klappt

Die Baseconfig Macros sind:
1
_CONFIG1(JTAGEN_OFF &   //JTAG port is disabled
2
    GCP_OFF &     //GSP Memory Code Protection OFF
3
    GWRP_OFF &     //GCC Flash Write Protection OFF
4
      COE_OFF &     //
5
      FWDTEN_OFF &   //Watchdog Timer OFF
6
      ICS_PGx1)     //debug over PGD1 and PGC1
7
  
8
_CONFIG2(FNOSC_FRCDIV & //Internal FRC 8Mhz without PLL, divider option
9
    OSCIOFNC_ON &  //RA3 is clk out (fosc/2)
10
    POSCMOD_NONE &   //Primary oscillator disabled
11
    I2C1SEL_PRI)    //Use default SCL1/SDA1 Pins

weitere clock init ist
1
void    Clock_Init(void)
2
{
3
   CLKDIVbits.RCDIV=0;    // RC Divider Postscaler (0 = 1:1)
4
   CLKDIVbits.DOZEN=0;    // disable pre-cpu clock divider postscaler
5
   CLKDIVbits.DOZE=0;     // no pre-cpu clock divider (1:1)
6
   OSCCONbits.SOSCEN=0;   // Enable/Disable the secondary oscilator
7
}

die timers
1
// extern impl
2
TSR  TSR1 = 0;
3
4
void SetTimer(int id, int ms, TSR T)
5
{
6
    switch (id)
7
    {
8
        case 1:
9
            TSR1 = T;
10
            T1CONbits.TON   = 1;   // Enable Timer
11
            T1CONbits.TSIDL = 0; // continue in idle mode
12
            T1CONbits.TGATE = 0; // no accu
13
            T1CONbits.TCKPS = 0;// scale 1:
14
            T1CONbits.TSYNC = 0; // no sync ext clock, if TCS = 1
15
            T1CONbits.TCS   = 0; // 0 internal clock; 1 ext clock on T1CK pin (rising
16
17
            // clock 8mhz o. pll -> div/2 für fcy ->  4mhz ohne weitere divs
18
            PR1 = 0xffff - 4000;
19
20
            IPC0bits.T1IP   = 5;  // high prio ( no use without nested)
21
            IFS0bits.T1IF   = 0;  // cleared ir flag
22
            IEC0bits.T1IE   = 1;  // enable interrup
23
            break;
24
    }         
25
}
26
27
void KillTimer(int id)
28
{
29
    switch (id)
30
    {
31
        case 1: 
32
            IEC0bits.T1IE   = 0;
33
            T1CON           = 0;
34
            TSR1            = 0;
35
            break;
36
    }
37
}
38
39
40
void __attribute__((__interrupt__, auto_psv)) _T1Interrupt(void)
41
{
42
   IFS0bits.T1IF=0; // cleared ir flag
43
   if (TSR1)
44
       TSR1();
45
}


TSR1() ist ein poiter auf eine applikationsabhängige ISR-Funktion
1
void Timer1()
2
{
3
    if ( XT) XT--;
4
5
}

und im Mainloop eine einfache Ausgabe
1
if (!XT)
2
      {
3
         SerOutString("XT",true);
4
         XT = 1000; // reload 1sec
5
      }

müsste eigentlich ok sein. Ist ja schon ein Erfolg bei diesem µC das 
überhaupt hinzubekommen, jetzt fehlt halt nur noch der Faktor
Gruß
Stefan

von Stefan_L_01 (Gast)


Lesenswert?

Nachtrag
Es ist ein PIC24FJ64GA002

von Max H. (hartl192)


Lesenswert?

Versuchs mal mit
1
PR1=0xF9F;

Da die Kommunikation über UART funktioniert, sollte der Oszillator 
richtig eingestellt sein.

Stefan_L_01 schrieb:
> und im Mainloop eine einfache Ausgabe
Nur das oder noch mehr? Kann es sein, dass eine unterlauf von XT 
verpasst wird weil sonst noch etwas in der Main passiert?

von Stefan_L_01 (Gast)


Lesenswert?

Hallo Max
0xf9f (praktisch dez4000) hat (jetzt wo ich noch im main Loop einen 
Event Counter inkrementiere) genau 240 Events pro Minute ausgelöst, was 
4 pro Sekunde entspricht.
Davor 4 zu langsam, jetzt 4 zu schnell...evtl. läuft doch noch pll mit?
Das ist ein Faktor 16 gegenüber vorher
4000*16 = 64000, liegt nahe an dem xFFFF-4000.
Nun gut zuvor war es "etwa" 4x zu langsam, kann auch nicht ganz 4x 
gewesen sein.

Aber ich dachte die Timer inkrementieren und nicht andersrum? Hmm 
vielleicht waren das PIC16 samples wo ich das her habe, hat sich was 
geändert? Im Manual sehe ich jetzt steht ja auch nur nüchtern für den 
PIC24 "Load the period value into PRx", das muss ja dann eigentlich 
dekremntierend sein.

Underflow von XT passiert nicht durch die logische if (XT) Anweisung im 
ISR. Deswegen habe ich im Mainloop alle Zeit der Welt auf das Event zu 
reagieren, kann beliebig viele Software Timer einbauen usw. .

Danke für die Hinweise & n8
Stefan

von Max H. (hartl192)


Lesenswert?

Stefan_L_01 schrieb:
> 0xf9f (praktisch dez4000)
nicht ganz, 3999dez. Der Timer teilt den Eingangstakt durch 
(Prescaler*(PRx+1))

> genau 240 Events pro Minute ausgelöst, was
> 4 pro Sekunde entspricht.
Im Simulator mit 4MHz instruction Frequency funktionierts mit PR1=0xF7F.

> Aber ich dachte die Timer inkrementieren und nicht andersrum?
Er wird inkrementiert und sobald TMR1==PR1 wird TMR1 auf null gesetzt 
und das Interrupt ausgelöst.

> Davor 4 zu langsam, jetzt 4 zu schnell...evtl. läuft doch noch pll mit?
Das wäre komisch, wenn die Taktquelle nicht 4MHz ist, sollte die 
Übertragung über UART nicht funktionieren.

Für mal diese Zeilen ein und miss die Frequenz die an RA0 ausgegeben 
wird, bei 4MHz sollte sie 666kHz sein:
1
  _TRISA0=0;
2
  asm("loop: btg LATA,#0");
3
  asm("bra loop");

: Bearbeitet durch User
von Stefan_L_01 (Gast)


Lesenswert?

Ich habe im Lauf mir einfach mal das
OSSCONbits.COSC (current oscii)

angeschaut, es ist 001 was PPL entspricht, also x4 des Taktes. Das 
entspricht genau meinem Verhalten.
Trotz FNOSC_FRCDIV Anweisung im Base config word (ist ja auch Default 
für power up wenn ich richtig lese).
Kann es sein dass der bootloader der noch in der Firmware sitzt den 
Modus vor meiner Software bestimmt?

Gruß
Stefan

von Stefan_L_01 (Gast)


Lesenswert?

Nachtrag: Ursprünglich war auch PPL defiert in dem UR-Demo, mit dem ich 
"lernen" anfing.
Die UART Divider aus der Firmware vom BP sind wahrscheinlich auch darauf 
abgestimmt. Mich hat eh gewundert dass nach der Umstellung auf FRCDIV 
die Ausgabe noch gelaufen ist.
Klar kann ich das jetzt einfach so lassen und mich freuen dass alles 4x 
so schnell geht, aber ich würde schon gerne das Teil auch kontrollieren 
können...

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
Noch kein Account? Hier anmelden.