External Interrupt on PIC16F887 not working // MPLABX XC8 C

Thread Starter

FrenchBaguette

Joined Aug 12, 2020
13
I would need some help with the external interrupt on pin 33 on the PIC16F887(PDIP). Basically I have tried everything, went by the datasheet, and the interrupt ended up not working. I'm 99% sure, that I have the hardware working because it worked with an Arduino. I am using an encoder, and both pins have pull-downs. I want to trigger the interrupt on the rising-edge. The code has some LCD code and functions in it, all of that works properly. Also take into account, that I'm fairly new to the whole Microcontroller thing. Here is the code, I hope somebody is able to help me:

C:
/ /PIC16F887 Configuration Bit Settings
// 'C' source line config statements

// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown Out Reset Selection bits (BOR disabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#pragma config LVP = OFF         // Low Voltage Programming Enable bit (RB3/PGM pin has PGM function, low voltage programming enabled)

// CONFIG2
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

#include <stdio.h>
#include <stdlib.h>

#define _XTAL_FREQ 8000000

char wbit;
int state = 0;

char vshift = 0;
char v1 = 5;
char v2 = 7;
char v3 = 5;

char osel = 3;

char aamp = 0;
char a1 = 1;
char a2 = 2;
char a3 = 5;

char sel[5] = {1,0,0,0,0};
char selmax[5] = {4,5,5,5,5}; 
char cursel = 0;

void writeByte(char data, char rs) {
    PORTDbits.RD1 = 0;                            // Chip Select LOW
    PORTDbits.RD0 = 0;                            // Chip Register Select LOW
    __delay_us(1);
    for (int sc = 7; sc > 0; sc--) {              // Main Data Loop
        wbit = 0b00000001 << sc;
        if (data & wbit) {
            PORTDbits.RD3 = 1;
        } else {
            PORTDbits.RD3 = 0;
        }
        PORTDbits.RD2 = 0;
        __delay_us(1);
        PORTDbits.RD2 = 1;
        __delay_us(1);
    }
    PORTDbits.RD2 = 0;
    if (data & 0b00000001) {
            PORTDbits.RD3 = 1;
        } else {
            PORTDbits.RD3 = 0;
        }
    if (rs == 't') {                              // Register Select SET
        PORTDbits.RD0 = 1;
    } else {
        PORTDbits.RD0 = 0;
    }
    __delay_us(1);
    PORTDbits.RD2 = 1;
    __delay_us(1);
    PORTDbits.RD1 = 1;                            // Chip Select HIGH
}

void sc(char x, char y) {           //Set Cursor
  if (y == 1) {
    writeByte(0b10000000 + 0b01000000 + x, 'c');
  } else {
    writeByte(0b10000000 + x, 'c');
  }
}

void cd(void) {          //Clear display
    writeByte(0b00000001, 'c');
    __delay_us(800);
}

void __interrupt() ISR() {
    if (INTCONbits.INTF == 1) {
        if (PORTDbits.RD6 == 1) {
            if (sel[cursel] == 0) {
                sel[cursel] = selmax[cursel];
            } else {
                sel[cursel] = sel[cursel] - 1;
            }
        } else {
            if (sel[cursel] == selmax[cursel]) {
                sel[cursel] = 0;
            } else {
                sel[cursel] = sel[cursel] + 1;
            }
        }
        INTCONbits.INTF = 0;
    }
    cd();
    __delay_ms(200);
}

void main(void) {
    TRISB = 0b00000001;
    TRISD = 0b01110000;
    
    ANSELH = 0;
    OPTION_REGbits.INTEDG = 1;
    INTCONbits.INTF = 0;
    INTCONbits.INTE = 1;
    INTCONbits.GIE = 1;
    
    PORTDbits.RD1 = 1;
    PORTDbits.RD2 = 1;
    
    writeByte(0b00111000, 'c');            // Function Set, 0b001[4-SPI][2-line][NR][X][X]
    writeByte(0b00001100, 'c');            // Display Mode, 0b00001[ON/OFF][Cursor][Blink]
    writeByte(0b00000001, 'c');            // Clear Display
    writeByte(0b00000110, 'c');            // Entry Mode Set 0b000001[L/R][Shift]
    
    while(1) {
        
        if (vshift == 0) {                          //Prints voltage
            writeByte(v1 + 48, 't');
            writeByte('.', 't');
            writeByte(v2 + 48, 't');
            writeByte(v3 + 48, 't');
            writeByte('V', 't');
        } else {
            writeByte((v1/10) + 48, 't');
            writeByte((v1 % 10) + 48, 't');
            writeByte('.', 't');
            writeByte(v2 + 48, 't');
            writeByte('V', 't');
        }
        
        writeByte(' ', 't');
        
        if (osel == 0) {                  //Prints connector type selected
            writeByte('P', 't');
            writeByte('L', 't');
            writeByte('U', 't');
            writeByte('G', 't');
        } else if (osel == 1) {
            writeByte('J', 't');
            writeByte('A', 't');
            writeByte('C', 't');
            writeByte('K', 't');
        } else if (osel == 2) {
            writeByte('U', 't');
            writeByte('S', 't');
            writeByte('B', 't');
            writeByte('A', 't');
        } else {
            writeByte('R', 't');
            writeByte('J', 't');
            writeByte('4', 't');
            writeByte('5', 't');
        }
        
        sc(0,1);
        
        if (aamp == 0) {                          //Prints amps
            writeByte(a1 + 48, 't');
            writeByte('.', 't');
            writeByte(a2 + 48, 't');
            writeByte(a3 + 48, 't');
            writeByte('A', 't');
        } else {
            writeByte('A', 't');
            writeByte('U', 't');
            writeByte('T', 't');
            writeByte('O', 't');
            writeByte('A', 't');
        }
        
        writeByte(' ', 't');
        writeByte('M', 't');
        writeByte('E', 't');
        writeByte('N', 't');
        writeByte('U', 't');
            
        while(1) {
            if (sel[0] == 0) {
                sc(5,0);
                writeByte(0b01111111, 't');
                sc(5,1);
                writeByte(' ', 't');
                sc(10,0);
                writeByte(' ', 't');
                sc(10,1);
                writeByte(' ', 't');
            } else if (sel[0] == 1) {
                sc(5,0);
                writeByte(' ', 't');
                sc(5,1);
                writeByte(0b01111111, 't');
                sc(10,0);
                writeByte(' ', 't');
                sc(10,1);
                writeByte(' ', 't');
            }
        }
    }
Mod edit: code tags - JohnInTX
 
Last edited by a moderator:

Thread Starter

FrenchBaguette

Joined Aug 12, 2020
13
What sort of encoder is it?
Have you checked pin 33 to see if it changes state properly?
I dont know the type (im not home) but it have worked with an Arduino, without a library, so probably there is no problem with the working principle.

Yes, as a normal digital input pin 33 changes state.
 

upand_at_them

Joined May 15, 2010
940
Do you have a pullup resistor on MCLR?
Did you disable analog functions?
Did you disable the comparator(s)?
Why did you leave PORTS A, C, and E as inputs? You can't leave pins as floating.
 

Thread Starter

FrenchBaguette

Joined Aug 12, 2020
13
Do you have a pullup resistor on MCLR?
Did you disable analog functions?
Did you disable the comparator(s)?
Why did you leave PORTS A, C, and E as inputs? You can't leave pins as floating.
MCLR is handled by my PicKit 4, and all other code works, so that's probably not the problem.
Analog function registers ANSEL, and ANSELH is both set to 0.
Comparators were disabled.
From what I've experienced leaving ports floating doesn't really make a difference, but I have set everything to output, that's not explicitly used as an input.

After all these measures still not working :/

But anyway thank you for the help.

UPDATE: also switched out the microcontroller, and the result is the same, so the microcontroller is fine.
 

djsfantasi

Joined Apr 11, 2010
9,156
Please edit and place your code between “code” tags. Like this...

[ code ]
// your code here
[/ code]

Without the spaces in the tags
 
Last edited:

trebla

Joined Jun 29, 2019
542
Simplest way to test interrupt triggering event is turn up a LED in interrupt routine. LCD routines may not work/indicate interrupt results correctly.
 

Thread Starter

FrenchBaguette

Joined Aug 12, 2020
13
Please edit and place your code between “code” tags. Like this...

Code:
// your code here
C:
/ PIC16F887 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF // Brown Out Reset Selection bits (BOR disabled)
#pragma config IESO = OFF // Internal External Switchover bit (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#pragma config LVP = OFF // Low Voltage Programming Enable bit (RB3/PGM pin has PGM function, low voltage programming enabled)

// CONFIG2
#pragma config BOR4V = BOR40V // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF // Flash Program Memory Self Write Enable bits (Write protection off)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

#include <stdio.h>
#include <stdlib.h>

#define _XTAL_FREQ 8000000

char wbit;
int state = 0;

char vshift = 0;
char v1 = 5;
char v2 = 7;
char v3 = 5;

char osel = 3;

char aamp = 0;
char a1 = 1;
char a2 = 2;
char a3 = 5;

char sel[5] = {1,0,0,0,0};
char selmax[5] = {4,5,5,5,5};
char cursel = 0;

void writeByte(char data, char rs) {
PORTDbits.RD1 = 0; // Chip Select LOW
PORTDbits.RD0 = 0; // Chip Register Select LOW
__delay_us(1);
for (int sc = 7; sc > 0; sc--) { // Main Data Loop
wbit = 0b00000001 << sc;
if (data & wbit) {
PORTDbits.RD3 = 1;
} else {
PORTDbits.RD3 = 0;
}
PORTDbits.RD2 = 0;
__delay_us(1);
PORTDbits.RD2 = 1;
__delay_us(1);
}
PORTDbits.RD2 = 0;
if (data & 0b00000001) {
PORTDbits.RD3 = 1;
} else {
PORTDbits.RD3 = 0;
}
if (rs == 't') { // Register Select SET
PORTDbits.RD0 = 1;
} else {
PORTDbits.RD0 = 0;
}
__delay_us(1);
PORTDbits.RD2 = 1;
__delay_us(1);
PORTDbits.RD1 = 1; // Chip Select HIGH
}

void sc(char x, char y) { //Set Cursor
if (y == 1) {
writeByte(0b10000000 + 0b01000000 + x, 'c');
} else {
writeByte(0b10000000 + x, 'c');
}
}

void cd(void) { //Clear display
writeByte(0b00000001, 'c');
__delay_us(800);
}

void __interrupt() ISR() {
if (INTCONbits.INTF == 1) {
if (PORTDbits.RD6 == 1) {
if (sel[cursel] == 0) {
sel[cursel] = selmax[cursel];
} else {
sel[cursel] = sel[cursel] - 1;
}
} else {
if (sel[cursel] == selmax[cursel]) {
sel[cursel] = 0;
} else {
sel[cursel] = sel[cursel] + 1;
}
}
INTCONbits.INTF = 0;
}
cd();
__delay_ms(200);
}

void main(void) {
TRISB = 0b00000001;
TRISD = 0b01110000;

ANSELH = 0;
OPTION_REGbits.INTEDG = 1;
INTCONbits.INTF = 0;
INTCONbits.INTE = 1;
INTCONbits.GIE = 1;

PORTDbits.RD1 = 1;
PORTDbits.RD2 = 1;

writeByte(0b00111000, 'c'); // Function Set, 0b001[4-SPI][2-line][NR][X][X]
writeByte(0b00001100, 'c'); // Display Mode, 0b00001[ON/OFF][Cursor][Blink]
writeByte(0b00000001, 'c'); // Clear Display
writeByte(0b00000110, 'c'); // Entry Mode Set 0b000001[L/R][Shift]

while(1) {

if (vshift == 0) { //Prints voltage
writeByte(v1 + 48, 't');
writeByte('.', 't');
writeByte(v2 + 48, 't');
writeByte(v3 + 48, 't');
writeByte('V', 't');
} else {
writeByte((v1/10) + 48, 't');
writeByte((v1 % 10) + 48, 't');
writeByte('.', 't');
writeByte(v2 + 48, 't');
writeByte('V', 't');
}

writeByte(' ', 't');

if (osel == 0) { //Prints connector type selected
writeByte('P', 't');
writeByte('L', 't');
writeByte('U', 't');
writeByte('G', 't');
} else if (osel == 1) {
writeByte('J', 't');
writeByte('A', 't');
writeByte('C', 't');
writeByte('K', 't');
} else if (osel == 2) {
writeByte('U', 't');
writeByte('S', 't');
writeByte('B', 't');
writeByte('A', 't');
} else {
writeByte('R', 't');
writeByte('J', 't');
writeByte('4', 't');
writeByte('5', 't');
}

sc(0,1);

if (aamp == 0) { //Prints amps
writeByte(a1 + 48, 't');
writeByte('.', 't');
writeByte(a2 + 48, 't');
writeByte(a3 + 48, 't');
writeByte('A', 't');
} else {
writeByte('A', 't');
writeByte('U', 't');
writeByte('T', 't');
writeByte('O', 't');
writeByte('A', 't');
}

writeByte(' ', 't');
writeByte('M', 't');
writeByte('E', 't');
writeByte('N', 't');
writeByte('U', 't');

while(1) {
if (sel[0] == 0) {
sc(5,0);
writeByte(0b01111111, 't');
sc(5,1);
writeByte(' ', 't');
sc(10,0);
writeByte(' ', 't');
sc(10,1);
writeByte(' ', 't');
} else if (sel[0] == 1) {
sc(5,0);
writeByte(' ', 't');
sc(5,1);
writeByte(0b01111111, 't');
sc(10,0);
writeByte(' ', 't');
sc(10,1);
writeByte(' ', 't');
}
}
}
}
 

Thread Starter

FrenchBaguette

Joined Aug 12, 2020
13
How often do edges from the sensor happen?
Are they brief positive or negative going, or about 50:50 mark.space ratio?
It's a rotary encoder, think about the input as a button! The main problem is actually not calling the ISR. Like if I use something else as an interrupt it still wont call.
 
Top