Forum: Mikrocontroller und Digitale Elektronik Interrupts für PIC16F887 programmieren


von Bastian (Gast)


Lesenswert?

Hallo,

ich möchte ein Interrupt am Pin RB1 auslösen, verwende den PIC16F887.
Hier mein Programm:
1
#include <htc.h>
2
3
4
__CONFIG (LVP_OFF & WDTE_OFF);              //Low Voltage Programming OFF
5
                                            // Watch dog timer off
6
void interrupt ISR();
7
8
void main ()
9
{
10
    
11
    
12
13
    TRISB=1;
14
    TRISD=0;
15
    ANSEL  = 0;
16
    ANSELH = 0;
17
    ANS10 = 0;
18
    IOCB = 0b00000010;
19
    INTCON=0b10001000;              //GIE Global Interrupt Enable
20
                                    //PEIE
21
                                    //T0IE
22
                                    //INTE
23
                                    //RBIE PORTB Change Interrupt
24
                                    //T0IF
25
                                    //INTF
26
                                    //RB0IF
27
28
    
29
30
    INTEDG = 0;
31
    while (1)
32
    {
33
        PORTD= 0b01010101;
34
    }
35
}
36
37
void interrupt ISR(void)
38
{
39
if (RBIF)
40
{
41
    PORTD = ~PORTD;
42
    RBIF = 0;
43
}
44
45
46
47
}
Nur irgendwie kommt das Programm nie in die ISR. Könnt ihr mir sagen was 
ich falsch mache?

Gruß

Bastian

von B. S. (bestucki)


Lesenswert?

Könnte es sein, dass su es nur nicht bemerkst? Du erwartest, dass in der 
Interruptroutine PORTD invertiert wird. Das tut es wahrscheinlich auch 
(hab die Registereinstellungen nicht kontrolliert), aber im 
Hauptprogramm setzt du PORTD immer gleich wieder auf den Wert 
0b01010101. Daher wirst du von Auge (z.B. bei LEDs) keine Veränderung 
feststellen können.

von Bastian (Gast)


Lesenswert?

glaub ich weniger, ich habe mit dem Oszi gemessen.
Habe natürlich auch andere Bitkombinationen für den Port versucht, hat 
aber nicht funktioniert.

von B. S. (bestucki)


Lesenswert?

Da ich nicht weiss, wie du gemessen hast, behaupte ich immer noch das 
selbe.

Versuch mal folgendes:
1
void main(void){
2
  /* Registereinstellungen usw. einfuegen */
3
4
  PORTD=0;
5
  while(1);
6
}
7
8
void interrupt_ISR(void){
9
  PORTD|=1;
10
  if(RBIF){
11
    PORTD|=2;
12
    RBIF=0;
13
  }
14
}

Dann siehst du, ob überhaupt ein Interrupt ausgelöst wird und ob es dann 
auch richtig erkannt wird.

von B. S. (bestucki)


Lesenswert?

Gerade gesehen:
1
TRISB=1;
2
IOCB = 0b00000010;

Das geht natürlich nicht. RB0 ist ein Eingang, alle anderen Ausgänge. 
Anschliessend aktiviertst du aber das Interrput-on-change für RB1, der 
ist aber als Ausgang definiert.

von Bastian (Gast)


Lesenswert?

be stucki schrieb:
> Da ich nicht weiss, wie du gemessen hast, behaupte ich immer noch das
> selbe.
Ich habe einfach mit dem Oszi den kompletten PORTD durchgemessen.

Hab deinen Code mal getestet, geht leider immer noch nicht
1
#include <htc.h>
2
3
4
__CONFIG (LVP_OFF & WDTE_OFF);              //Low Voltage Programming OFF
5
                                            // Watch dog timer off
6
void interrupt_ISR(void);
7
8
void main (void)
9
{      
10
    TRISB=1;
11
    TRISD=0;
12
    ANSEL  = 0;
13
    ANSELH = 0;
14
    ANS10 = 0;
15
    IOCB = 0b00000010;
16
    INTCON=0b10001000;              //GIE Global Interrupt Enable
17
                                    //PEIE
18
                                    //T0IE
19
                                    //INTE
20
                                    //RBIE PORTB Change Interrupt
21
                                    //T0IF
22
                                    //INTF
23
                                    //RB0IF
24
25
    
26
27
    INTEDG = 0;
28
29
 PORTD=0;
30
  while(1);
31
}
32
33
34
void interrupt_ISR(void)
35
{
36
  PORTD|=1;
37
  if(RBIF){
38
    PORTD|=2;
39
    RBIF=0;
40
  }
41
}


be stucki schrieb:
> Das geht natürlich nicht. RB0 ist ein Eingang, alle anderen Ausgänge.
> Anschliessend aktiviertst du aber das Interrput-on-change für RB1, der
> ist aber als Ausgang definiert.

Wieso, ich habe doch mit TRISB=1 den kompletten PortB als Eingang 
geschalten, und ich möchte nur interrupt on change für RB1 aktivieren

von Chris B. (dekatz)


Lesenswert?

Ähhmm TRISB = 1 und 1 ist Binär (auf 8-Bit Breite gezogen) 0b00000001.

von Andreas G. (beastyk)


Lesenswert?

Versuch mal zuerst den PORTB zu lesen.
und ich weiß nicht ob RBIF langt, dachte an sowas:
1
unsigned char buff;
2
3
void Interrupt_ISR (void)
4
{
5
if (INTCON.RBIF == 1)        //oder nur (INTCON.RBIF)
6
   {
7
     buff = PORTB;           //PORTB lesen
8
     PORTD |= 2;             //invertiere 2 an PORTD
9
     INTCON.RBIF = 0;        //interrupt softwareseitig zurücksetzen
10
   }
11
}

Gruß
dat Beast

Achso: Irgendwas sollte zwischen RB4:RB7 deinen Interrupt auch auslösen, 
oder?

von IchLechzeNachEurerErfahrung (Gast)


Lesenswert?

Was

Bastian schrieb:
>> Das geht natürlich nicht. RB0 ist ein Eingang, alle anderen Ausgänge.
>> Anschliessend aktiviertst du aber das Interrput-on-change für RB1, der
>> ist aber als Ausgang definiert.
>
> Wieso, ich habe doch mit TRISB=1 den kompletten PortB als Eingang
> geschalten, und ich möchte nur interrupt on change für RB1 aktivieren

Nein hast du nicht. Das hättest du mit TRISB = 0xFF; oder TRISB = 255;.

von Lukas D. (lukas_d)


Lesenswert?

1
GIE     = 1;                                                                //Global Interrupts
2
PEIE    = 1;                                                                //Peripheral Interrupts
3
T0IE    = 0;                                                                //Timer0 Interrupt Enable
4
INTE    = 0;                                                                //External Interrupt on RB0/INT0 Enable
5
RBIE    = 1;                                                                //RBPort Interrupt Enable
6
T0IF    = 0;                                                                //Timer0 Interrupt FLAG
7
INTF    = 0;                                                                //External Interrupt FLAG RB0/INT0
8
RBIF    = 0;                                                                //RBPort Interrupt FLAG
9
10
TRISB1 = 1;
11
12
if(RBIF && PORTBbits.RB1)
13
{
14
    PORTD = !PORTD;
15
    RBIF = 0;
16
}

von bastian (Gast)


Lesenswert?

also, ich habe jetzt eure Beispiele wie z.B.:
1
unsigned char buff;
2
3
void Interrupt_ISR (void)
4
{
5
if (INTCON.RBIF == 1)        //oder nur (INTCON.RBIF)
6
   {
7
     buff = PORTB;           //PORTB lesen
8
     PORTD |= 2;             //invertiere 2 an PORTD
9
     INTCON.RBIF = 0;        //interrupt softwareseitig zurücksetzen
10
   }
11
}
Mit INTCON.RBIF kann mein Compiler (HITECH-C) nichts anfangen, es wird 
immer ein Fehler gemeldet.
1
GIE     = 1;                                                                //Global Interrupts
2
PEIE    = 1;                                                                //Peripheral Interrupts
3
T0IE    = 0;                                                                //Timer0 Interrupt Enable
4
INTE    = 0;                                                                //External Interrupt on RB0/INT0 Enable
5
RBIE    = 1;                                                                //RBPort Interrupt Enable
6
T0IF    = 0;                                                                //Timer0 Interrupt FLAG
7
INTF    = 0;                                                                //External Interrupt FLAG RB0/INT0
8
RBIF    = 0;                                                                //RBPort Interrupt FLAG
9
10
TRISB1 = 1;
11
12
if(RBIF && PORTBbits.RB1)
13
{
14
    PORTD = !PORTD;
15
    RBIF = 0;
16
}
Habe ich auf RB4 abgeändert, da nur Interrupts zwischen RB4 und RB7 
erkannt werden, jedoch springt er nicht in die ISR rein.

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.