Forum: Mikrocontroller und Digitale Elektronik dsPic33F - Timer/Interrupts


von Bollwing (Gast)


Lesenswert?

Hallo

Wieder mal das (leidige) Thema dsPIC + Timer/Interrupts.
Ich bekomme es leider nicht hin mit dem dsPIC33FJ64GS610 mit einem Timer 
einen Interrupt auszulösen, wobei ich nun strikt nach Datenblatt und den 
einzelen Manuals (Sections 1 bis ∞ :D ) vorgehe und versuche die 
einzelnen Register so korrekt wie möglich zu konfigurieren bzw. 
vollständig zu verstehen. Ich arbeite mit der C30 Bibliothek in MPLAB 
und einem ICD3.
Konfigurationsbits setze ich im Code.

Nun der Source-Code:
1
#include <p33FJ64GS606.h>
2
#include <stdlib.h>    
3
#include <delay.h>    
4
5
// Select Internal FRC at POR
6
_FOSCSEL(FNOSC_FRC & IESO_OFF);
7
// Enable Clock Switching and Configure Primary Oscillator in XT mode
8
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_NONE);
9
10
_FWDT(FWDTEN_OFF)  //disable the watchdog timer
11
_FICD(JTAGEN_OFF & ICS_PGD1);//disable JTAG, enable debugging on PGx1 pins
12
13
void configureOscillator(void);
14
void initTimer1(void);
15
void __attribute__((__interrupt__, no_auto_psv)) _T1Interrupt(void);
16
void enableInterrupts(void);
17
void disableInterrupts(void);
18
19
20
int main(void) {
21
configureOscillator();
22
initTimer1();
23
enableInterrupts();
24
25
  //outputs to 0
26
  _LATB12 = 0;
27
  _LATB13 = 0;  
28
  _LATB14 = 0;
29
30
  //  led outputs
31
  _TRISB12 = 0;
32
  _TRISB13 = 0;
33
  _TRISB14 = 0;
34
35
36
  while (1) {
37
38
    _LATB12 = 1;
39
    _LATB13 = 0;  
40
41
                //Warteschleife
42
    int i = 0;
43
    for(i=0; i<30;i++)
44
    {
45
      int o = 0;
46
      for(o=0; o<10000;o++) {}
47
       
48
      }
49
    _LATB12 = 1;
50
    _LATB13 = 1;  
51
52
                //Warteschleife
53
    for(i=0; i<30;i++) 
54
    {
55
      int o = 0;
56
      for(o=0; o<10000;o++) {}
57
      } 
58
  
59
  }
60
}
61
62
63
void configureOscillator(void)
64
{
65
  // Configure PLL prescaler, PLL postscaler, PLL divisor 
66
  PLLFBD=150; // M=152
67
  CLKDIVbits.PLLPOST=0; // N2=2 
68
  CLKDIVbits.PLLPRE=5; // N1=7 
69
  
70
  // Initiate Clock Switch to Primary Oscillator with PLL (NOSC=0b011)
71
  __builtin_write_OSCCONH(0x01);
72
  __builtin_write_OSCCONL(OSCCON | 0x01);
73
  
74
  // Wait for Clock switch to occur
75
  while (OSCCONbits.COSC!= 0b001);
76
  // Wait for PLL to lock
77
  while (OSCCONbits.LOCK!= 1);
78
  return;
79
}
80
81
void initTimer1(void)
82
{
83
T1CONbits.TON = 0;// Disable Timer
84
T1CONbits.TCS = 0;// Select internal instruction cycle clock 
85
T1CONbits.TGATE = 0;// Disable Gated Timer mode
86
T1CONbits.TCKPS = 0b11;// Select 1:256 Prescaler
87
//11 = 1:256 prescale value
88
//10 = 1:64 prescale value
89
//01 = 1:8 prescale value
90
//00 = 1:1 prescale value
91
92
TMR1 = 0x00; // Clear timer register
93
PR1 = 20000; // Load the period value
94
95
IPC0bits.T1IP = 1;// Set Timer1 Interrupt Priority Level
96
IFS0bits.T1IF = 0;// Clear Timer1 Interrupt Flag
97
IEC0bits.T1IE = 1;// Enable Timer1 interrupt
98
T1CONbits.TON = 1;// Start Timer
99
return;
100
}
101
102
103
void __attribute__((__interrupt__, no_auto_psv)) _T1Interrupt(void)
104
{
105
/* Clear Timer1 interrupt */
106
IFS0bits.T1IF = 0;
107
108
LATBbits.LATB14 = ~LATBbits.LATB14;
109
}
110
111
void enableInterrupts(void)
112
{
113
/* Set CPU IPL to 0, enable level 1-7 interrupts */
114
/* No restoring of previous CPU IPL state performed here */
115
SRbits.IPL = 0;  
116
//SRbits.IPL = 0 funktioniert nur in Release .... in Debug wird bei einem Wert von 0 der PIC "halted"
117
//SRbits.IPL = 1 (=IPC0bits.T1IP) funktioniert sowohl im Debug als auch im Release
118
return;
119
}
120
121
122
void disableInterrupts(void)
123
{
124
/* Set CPU IPL to 7, disable level 1-7 interrupts */
125
/* No saving of current CPU IPL setting performed here */
126
SRbits.IPL = 7;
127
return;
128
}

lg und Danke ;)
Gerald

von Bollwing (Gast)


Lesenswert?

Ich habe im text geschrieben: [...] mit dem dsPIC33FJ64GS610 mit einem 
Timer[...]
Natürlich ist es ein dsPIC33FJ64GS606 wie im Sourcecode.

von Florian V. (Gast)


Lesenswert?

Zwei allgemeine Hinweise zu dsPICs/PIC24 bei solchen hardwarenahen 
Problemen:

- lieber mit realer Hardware testen. Der Simulator hat seine Grenzen. 
Ich musste z.B. feststellen, dass ein PWM-Modus im Simulator zum 
Verrecken nicht funktioniert. Das war nirgends dokumentiert.

- beim Debuggen von Interruptroutinen kann der PIC im Single-Step 
Verhalten zeigen, dass real nicht existiert. Wenn man z.B. das Programm 
durchsteppt und wartet "Jetzt muss das Flag doch jeden Zyklus 
kommen...". Also lieber Breakpoints setzen und "Run" klicken.

von Bollwing (Gast)


Lesenswert?

Hallo Florian!

Erstmal Danke für deine Antwort!

zu 1.
Ich entwickle schon seit Anfang an auf realer Hardware. Dies ist durch 
die Applikationvorgegeben. Der dsPIC (Automotive-Version) ist Teil einer 
komplexen Hardware-Struktur welche unter Stressbedingungen eingesetzt 
wird. Es geht darum eine konfigurierbare Ansteuerung für eine 
Bauteilgruppe zu entwickeln und auch diverse Schutzfunktionen zu 
implementieren. Mehr darf ich dazu nicht sagen.
Ich komme selbst aus der Atmel-Welt und habe mich zuvor nur an einem 
kleien 16F877 etwas in Assembler probiert. Aufgrund der genannten 
Anforderungen wurde es der genannte dsPic in möglicht Hardwarenaher 
Programmierung - Assembler kam aufgrund der Wartbarkeit nicht in Frage.
Die von dir genannten Probleme in Simulationen kenne ich ...

zu 2.
Das Debugging zeigte, dass er nun gar nicht in die ISR rein kommt.
Die Konfiguration scheint richtig (zumindest laut meinem Verständnis für 
die Funktionsweise der einzelnen Stellen in den Registern abzulaufen.
Weiters ist das zuvor gepostet Testprogramm zum Beispielprogramm in der 
Dokumentation sehr ähnlich. (laut dsPIC33F/PIC24H Family Reference 
Manual, Section 11. Timers, DS70205D, 11.4.1 Timer Mode, Example 
11-1:Initialization Code for 16-bit Timer Mode).

Auch das Dokument "dsPIC33F/PIC24H Family Reference Manual, Section 32. 
Interrupts, 70214C" bin ich durchgegangen und habe mir möglicht viel 
davon angeeignet.

Zurzeit bin ich eigentlich total Ratlos, da ich meiner Einschätzung nach 
genau nach Datenblatt vorgegangen bin und es eigentlich stimmen müsste. 
Das Auslösen eines Interrupts mittels eines Timers ist nun doch nicht 
wirklich eine so komplexe Aufgabe. Jedoch vermute ich etwas übersehen zu 
haben - wie sagt man so schön: Man sieht den Wald vorlauter Bäumen 
nicht.
Morgen werde ich das Ding erneut debuggen.

In diesem Sinne ....

lg
Gerald

von Frank K. (fchk)


Lesenswert?

Ich verwende immer SET_CPU_IPL(ipl) anstelle SRbits.IPL direkt zu 
modifizieren.

fchk

von Bollwing (Gast)


Lesenswert?

Frank K. schrieb:
> SET_CPU_IPL(ipl) anstelle SRbits.IPL
Ok ... danke das werd ich mal probieren ...

lg
Gerald

von Florian V. (florianv)


Lesenswert?

Bollwing schrieb:
> Frank K. schrieb:
>> SET_CPU_IPL(ipl) anstelle SRbits.IPL
> Ok ... danke das werd ich mal probieren ...

Also notwendig ist es nicht, den IPL überhaupt zu modifizieren. Ich 
mache es zumindest nicht und es geht auch so.

Läuft der Timer denn überhaupt?

Du benutzt PortB - konfigurierst ihn aber nirgendwo als Digital (ADPCFG 
und ADPCFG2). Obwohl das bei einem Ausgang wohl keine Probleme 
verursacht, nur das Einlesen klappt bei einem Analogpin nicht.

von Bollwing (Gast)


Lesenswert?

Hallo

Florian V. schrieb:
> Also notwendig ist es nicht, den IPL überhaupt zu modifizieren. Ich
> mache es zumindest nicht und es geht auch so.
Es macht in meinem Fall keinen Unterschied.

Florian V. schrieb:
> Läuft der Timer denn überhaupt?
Ja .... definitiv, da ich im Fall von einer Änderung von T1CONbits.TCKPS 
sowie TMR1 einstellen kann, wann er abstürzt.

Florian V. schrieb:
> Du benutzt PortB - konfigurierst ihn aber nirgendwo als Digital (ADPCFG
> und ADPCFG2). Obwohl das bei einem Ausgang wohl keine Probleme
> verursacht, nur das Einlesen klappt bei einem Analogpin nicht.
Ja ... auch eine Kofiguration von ADPCFGbits.PCFG14 = 0 (0 ... 
digitaleingang an Port B14.

Ich werde am Nachmittag mal mit Timer 2 + INterrupt mein Glück versuchen 
;)

lg und im Voraus Danke!
Gerald

von Bollwing (Gast)


Lesenswert?

Timer 2 brachte auch keine Änderung.

Sobald ein Interrupt ausgelöst wird, ist der Pic nach wie vor halted 
....
Auch eine Änderung der restlichen Config brachte nichts.

lg
Gerald

von nevis (Gast)


Lesenswert?

Bollwing schrieb:
> Ja .... definitiv, da ich im Fall von einer Änderung von T1CONbits.TCKPS
> sowie TMR1 einstellen kann, wann er abstürzt.

Ist es so, dass der dsPIC läuft und dann wenn der Interrupt eigentlich 
auslöst werden sollte der Status auf "halted" wechselt? Falls ja, so 
wird "wahrscheinlich" irgendein Trap ausgelöst, evtl. ein StackError? 
Prüfen kannst du diesen Fall in dem du einen Handler für den StackError 
hinzufügst:
1
void __attribute__((interrupt, no_auto_psv)) _StackError(void)
2
{
3
  INTCON1bits.STKERR = 0;         //Clear the trap flag
4
  while (1);
5
}
Zu Traps siehe auch:
http://www.embeddedcodesource.com/developer/microchip_technology_59/ce107__stack_error_traps_for_easy_debugging

Die Traps haben eine Priorität > 7 und können nicht deaktiviert werden.

von morph1 (Gast)


Lesenswert?

Bollwing schrieb:
> Sobald ein Interrupt ausgelöst wird, ist der Pic nach wie vor halted

??? das irritiert jetzt etwas, der sollte vorher auf run sein und nach 
dem interrupt auf halted...

von Bollwing (Gast)


Lesenswert?

Hallo und Danke für die Zahlreichen Antworten.
Es gibt News zum Thema. Das Auslösen von Interrupts am dsPIC 
funktioniert. Der von mir gepostete Code ist lauffähig.
Allerdings nur wenn man ein Beispielprojekt von Microchip herunterladet 
und den Code reinkopiert.

Welche Einstellung in MPLAB nun dazu führte, dass der Code nicht 
lauffähig war, ist mir noch immer nicht bekannt. Es liegt auch nicht an 
den include-Dateien oder Bibliotheken.

In einem neuen, selbst aufgesetzten, Projekt läuft der von Microchip für 
einen größerem dsPIC vorgegebene Code nicht.

Soweit der aktuelle Erkenntnissstand.

lg
Gerald

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.