Forum: Mikrocontroller und Digitale Elektronik Problem mit PIC-interrupts


von Frank M. (aktenasche)


Angehängte Dateien:

Lesenswert?

ich hab gerade mit der programmierung von einem PIC18F4550 begonnen.

IDE: mplab + proteus/isis
compiler: C18
vorkenntnisse: 8051, AVRs

ich bin durch ein wenig googeln nun darauf gekommen, dass der pic18f 
generell nur 2 interruptvektoren kennt, 0x08 für high priority und bei 
0x18 für high priority.
so gut so weit.

leider wird meine ISR (Timer1_ISR()) nie ausgeführt? code ist copypasta.

gibt es denn keine möglichkeit dem compiler zu sagen: die funktion soll 
meine timer1 isr sein? ausser über die flagunterscheidung.

der timer1 interrupt tritt jedenfalls auf, sagt isis (siehe screenshot). 
vielleicht kann man der simulation auch nicht ganz trauen.
1
//main insterrupt handler
2
#pragma interruptlow MainISR
3
void MainISR(void)
4
{
5
  Timer1_ISR();
6
}  
7
8
//high ISR routine
9
#pragma code _HIGH_INTERRUPT_VECTOR = 0x000008
10
void ISR_high(void)
11
{
12
     _asm
13
       goto MainISR      // Sprung zur Interruptroutine
14
    _endasm
15
}  
16
//low ISR routine
17
#pragma code _LOW_INTERRUPT_VECTOR = 0x000018
18
void ISR_low(void)
19
{
20
  _asm
21
       goto MainISR       // Sprung zur Interruptroutine
22
    _endasm
23
}
1
void InitializeRTC(void)
2
{
3
  T1CONbits.RD16 = 1;    //16 bit mode
4
  T1CONbits.T1CKPS1 = 1;  //prescaler: 1:8
5
  T1CONbits.T1CKPS0 = 1;
6
  T1CONbits.T1OSCEN = 1;  //enable oscillator circuit
7
  T1CONbits.TMR1CS = 0;  //use internal clock
8
  T1CONbits.T1SYNC = 0;  //synchronize timer with external clock
9
  
10
  TMR1L = 0x00;
11
  TMR1H = 0x00;
12
  
13
  T1CONbits.TMR1ON = 1;  //enable timer 1
14
}  
15
16
void Timer1_ISR(void)
17
{
18
  T1CONbits.TMR1ON = 0;  //disable timer 1
19
  PIR1bits.TMR1IF = 0;  //reset flag
20
  TMR1L = 0x00;    //reset timer registers
21
  TMR1H = 0x00;
22
  MAX7219_DisplayChar(3,'A');
23
  T1CONbits.TMR1ON = 1;  //enable timer 1
24
}
1
//initialize interrupts
2
void ConfigureInterrupts()
3
{
4
  RCONbits.IPEN = 0;    //no interrupt priority
5
  RCONbits.SBOREN = 0;  //no brownout detection
6
    
7
  //timer
8
  PIE1bits.TMR1IE = 1;    //enable timer 1 interrupt
9
  INTCONbits.GIE = 1;      //global interrupt enable
10
}

von slow (Gast)


Lesenswert?

>0x08 für high priority und bei
>0x18 für high priority.


???????????

von Frank M. (aktenasche)


Lesenswert?

0x18 low, sorry ^^

von Meister E. (edson)


Lesenswert?

Du musst auch die Interrupts der Peripherie zulassen:
1
//timer
2
   PIE1bits.TMR1IE = 1;    //enable timer 1 interrupt
3
   INTCONbits.PEIE = 1;// <- hier Peripherie-Ints erlauben
4
   INTCONbits.GIE = 1;      //global interrupt enable

Gruß,
Edson

von Frank M. (aktenasche)


Lesenswert?

danke, jetzt funktioniert es!

von Marcus (Gast)


Lesenswert?

Hallo Frank,


>>gibt es denn keine möglichkeit dem compiler zu sagen: die funktion soll
>>meine timer1 isr sein? ausser über die flagunterscheidung.

Nein. Ist halt so. Geh' halt in den Interrrupt-Handlern die jeweiligen 
Flags durch und gut.
In der Praxis wirst Du es ohnehin so gestaltem, daß Du das _wirklich_ 
zeitkritische in den Handler mit der hohen Prio legen wirst. Der Rest 
ist eh' egal. D kommt es auf die paar Zyklen zur Fallunterscheidung 
nicht an.

BTW: Wenn Du GENAUE Timerzyklen haben willst: Schalt' den Timer in der 
Interruptroutine nicht ab. Never. Einfach laufen lassen.

Schau Dir mal im Datenblatt die Interruptlogik an; Du musst noch 
Pheeripheral Interupts einschalten, dann sollte es funktionieren.

Viele Grüße,
Marcus

von Frank M. (aktenasche)


Lesenswert?

Marcus schrieb:
> BTW: Wenn Du GENAUE Timerzyklen haben willst: Schalt' den Timer in der
> Interruptroutine nicht ab. Never. Einfach laufen lassen.

ja, eigentlich brauch ich sehr genaue timerzyklen da ich eine RTC 
implementieren will (mit quarz versteht sich)

damit das timerregister nach genau einer sekunde überläuft muss ich 
allerdings das high register bei jedem interrupt auf 0x80 setzen und das 
dürfte doch unvorhersehbare ergebnisse liefern wenn ich den timer 
weiterlaufen lasse?

oder ist das egal, wenn man davon ausgeht dass die ISR innerhalb von 255 
(also vor dem überlauf von low->high) abgeschlossen ist?

eine autoreload funktionalität scheint es ja nicht zu geben...

p.s.: was ist denn peripheral und was nicht?

von holger (Gast)


Lesenswert?

>ja, eigentlich brauch ich sehr genaue timerzyklen da ich eine RTC
>implementieren will (mit quarz versteht sich)

Da wirst du mit Overflow aber nichts. Bei jedem Overflow
verlierst du Zeit. Nimm CCP.

von Frank M. (aktenasche)


Lesenswert?

ist auch ne möglichkeit, danke für den tipp

von Dieter W. (dds5)


Lesenswert?

Frank Meier schrieb:
> eine autoreload funktionalität scheint es ja nicht zu geben...

Gibt es, aber nur mit 8Bit Timer 2.

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.