Forum: Mikrocontroller und Digitale Elektronik Pic24FJ256GB Problem mit Timer1 Interrupt


von Casi (Gast)


Lesenswert?

Hallo Zusammen,

ich beginne gerade mit der µP Programmierung und habe mir für den Anfang 
ein PIC24 Starterkit mit einem PIC24FJ256GB106 kontroller gekauft. Auch 
was die Programmiersprache C angeht habe ich noch kein Vorwissen.
Ich habe es mir zur Aufgabe gemacht eine LED auf dem Developmentboard im 
Sekundentakt blinken zu lassen. Hierzu möchte ich einen Timer1 einsetzen 
der sekündliche einen Interrupt auslöst und dabei den Zustand der LEDs 
wechselt. Den Timer möchte ich mit einem externen 32kHz Oszillator 
ansteuern. Ich vermute, dass das Oszillator Enable Bit (SOSCEN) nicht 
eingeschaltet ist. Doch jedes Mal wenn ich das entsprechede Register 
OSCCON konfiguriere ist zu sehen, dass sich das Register wie von 
Zauberhand selber umkonfiguriert. Nachfolgend der Quellcode meines 
Programmes. Hat jemand eine Idee was ich falsch mache?

Vielen Dank.

Gruß
Carsten

#include <p24FJ256GB106.h>


int R = 0;
int GB =0;



void __attribute__((_interrupt_, _shadow_)) _T1Interrupt(void)
{
  GB^=0x1111;
  R^=0x1111;
  IFS0bits.T1IF = 0; //Reset Timer1 interrupt flag and Return from ISR
}



int main()
{
  T1CON        = 0x00;    //Stops the Timer1 and reset control reg.
  TMR1         = 0x00;    //Clear contents of the timer register
  PR1          = 32700;   //Load the Period register with the value 
0x8CFF
  IPC0bits.T1IP = 0x01;   //Setup Timer1 interrupt for desired priority 
level
                // (this example assigns level 1 priority)
  IFS0bits.T1IF = 0;       //Clear the Timer1 interrupt status flag
  IEC0bits.T1IE = 1;       //Enable Timer1 interrupts
  T1CON = 0x8002;       //Start Timer1 with prescaler settings at 1:1 
and
                //clock source set to the external clock in the
                //asynchronous mode
  OSCCON =0x0402;
  PORTG=GB;
  PORTB=R;
  TRISG=0b1111110000111111;
  TRISF=0b1111111111001111;

  while (1)
    {
      PORTG=GB;
      PORTF=R;
    };

}

von Lehrmann M. (ubimbo)


Lesenswert?

Ich habe eher die Vermutung, dass du gar keinen Output schaltest.

Casi schrieb:
> Doch jedes Mal wenn ich das entsprechede Register
> OSCCON konfiguriere ist zu sehen, dass sich das Register wie von
> Zauberhand selber umkonfiguriert.

Wie siehst du das? ICD ?

Wie sieht's mit Config-Bits aus ? (bitte mal reiposten)

Bitte poste deinen C Code nochmal und versuch es zu Formatieren (hier im 
Forum) d.h. in eckigen Klammern davor avrasm und danach wiederin eckigen 
Klammern /avrasm zu posten. Sonst ist's nicht schön zu lesen

Bist du denn sicher, dass der PIC anläuft ?

von Manuel (Gast)


Lesenswert?

Hallo

Soweit ich weiss nutzt das Starterkit den internen Oszillator für den
Systemclock.

Versuch mal folgenden Code:
1
#include <p24FJ256GB106.h>
2
3
_CONFIG2(IESO_OFF & PLL_96MHZ_ON & PLLDIV_DIV2 & FNOSC_FRCPLL & POSCMOD_NONE) // Primary osc disabled, FRC OSC with PLL, USBPLL /2
4
_CONFIG1(JTAGEN_OFF & ICS_PGx2 & FWDTEN_OFF)        // JTAG off, watchdog timer off
5
6
int main( void )
7
{
8
9
  OSCCON = 0x1102;    // Enable secondary oscillator, use FRC oscillator
10
  CLKDIV = 0x0000;    // FRC post-scaler (1:1), USB postscaler (1:1), CPU postscaler (1:1)
11
12
  RPINR2bits.T1CKR = 37;  // Timer1 Externer Clock an RPI 37
13
14
  // Timer 1 init
15
  TMR1 = 0;                   // Timer1 Register löschen
16
  PR1 = 32700;                // Interruptintervall für Timer1 setzen 
17
  IFS0bits.T1IF = 0;          // Timer1 Interrupt Flag löschen
18
  T1CONbits.TCS = 1;          // Externer Clock
19
  T1CONbits.TCKPS = 0;        // Timer1 Input Clock Teilverhältnis 1:1
20
  IEC0bits.T1IE = 1;          // Timer1 Interrupt aktivieren
21
  T1CONbits.TON = 1; 
22
23
  // LED Init
24
  TRISFbits.TRISF4 = 0;      // PIN auf Output schalten
25
  TRISFbits.TRISF5 = 0;      // PIN auf Output schalten
26
27
  while(1)      // main loop
28
  {
29
    Nop();
30
    Nop();
31
  }
32
}
33
34
void __attribute__((__interrupt__, no_auto_psv)) _T1Interrupt(void)
35
  {               
36
  
37
  LATFbits.LATF4 = LATFbits.LATF4 ^ 1;
38
  LATFbits.LATF5 = LATFbits.LATF5 ^ 1;
39
  
40
  IFS0bits.T1IF = 0;                 // Timer1 Interrupt Flag löschen 
41
  return;
42
  }

Gruss Manuel

von Casi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Zusammen,

erstmal danke für Eure Hilfe.

Zu Michael:
Doch ich hatte die Outputs geschaltet. Es war auch möglich die Diode an 
oder auszuschalten (abhängig von PORTF, PORTG). Nur blinken war nicht 
möglich. Was meinst Du mit ICD?

Zu Manuel:
Ich habe jetzt mal Deinen Quellcode übernommen, aber auch damit blinkt 
die LED nicht. Eine LED (die rote) ist dauerhaft an. Ich habe mir das 
Ganze mal mit dem Debugger angeschaut. Die Interrupt Service Routine 
wird nicht aufgerufen. Für mich sieht es so aus als wenn der Timer nicht 
läuft. TMR1 ist permanent 0x0000. Bei meinem Code hat der Timer 
gearbeitet. Bei Deinem Code lässt sich allerdings das OSCCON Register 
ändern. Das hat bei mir nicht funktioniert. Kann das an den ersten 
beiden Code Zeilen liegen, dass sich das OSCCON Register ändern lässt?

Anbei ein Screenshot von den Registern.

Gruß
Carsten

von Casi (Gast)


Lesenswert?

Hallo Zusammen,

ich habe jetzt mal den internen Timer eingeschaltet. Ist das korrekt?

T1CONbits.TCS = 0;

Der Timer läuft jetzt, aber ein Interrupt kommt immer noch nicht.

Gruß
Carsten

von Casi (Gast)


Lesenswert?

Hat niemand mehr eine Idee?

von Dirk (Gast)


Lesenswert?

Man benötigt eine spezielle Befehlsfolge, um das OSCCON-Register zu 
beschreiben. Microchip stellt diese in einem Macro zur Verfügung. 
Versuche mal

__builtin_write_OSCCONL(0b1100010);

danach sollte das SOSCEN Bit auch gesetzt sein.

Gruß, Dirk

von Master S. (snowman)


Lesenswert?

ich habe nicht gründlich alle zeilen von oben durchgedacht, und auch 
habe ich noch nie gehört, dass es ein procedere zum beschreiben von 
OSCCON gibt (jedoch können gewisse bits in einem register nicht immer 
geschrieben sondern nur gelesen werden, da sie sich immer mal wider 
verändern, weil sie über den status der hardware aufschluss geben). 
anyway, was ich oft bei problemen bei anderen feststelle, ist, dass sie 
versuchen alle register manuell zu beschreiben und irgendwo, dann was 
nicht richtig ist (widersprüchliche konfiguration etc.). da den fehler 
zu suchen ist zeitraubend. statt der manuellen konfiguration verwendet 
man besser in einem ersten schritt die von Microchip gegebenen 
funktionen wie OpenTimer1() etc., damit ersparst du dir viele 
fehlerquellen und leserlicher ist's auch.

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.