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