Electronic – PORTB Interrupt On Change changes state unintentionally

interruptsmicrocontrollerpic

I am running below code in a PIC16F887 that runs at 20 MHz. I feed PORTB.0 a signal of 1 KHz from my signal generator. However, whenever the signal is low, PORTC.1 toggles at a rate of either ~5usec or ~10usec. Also, I've connected an OP-AMP's output that gives 0V-4V, still the same.

I have tried enabling weak pull ups inside, didn't work.

The microcontroller is on an EasyPIC5 development board, so I can enable and disable either pull-up or pull-down resistors that are 10K. Didn't work, either.

Is this some kind of silicon problem(?) or is there a mistake in my code?

Here is a screenshot from the oscilloscope that probes PORTC.1:

enter image description here

enter image description here

Here is my code, please omit off-topic part of it:

volatile unsigned int fiftymicros=0;
volatile unsigned int milis=0;
volatile unsigned char fiftymicroscounter=0;
volatile unsigned int data_time=0;
volatile unsigned int milis_ctr=0;
unsigned long int data_bar[20]={0};
void interrupt()
{
     if(INTCON.T0IF)
     {
      TMR0=198;
      INTCON.T0IF=0;
      fiftymicros++;
      if(++fiftymicroscounter==40) { fiftymicroscounter=0; milis++; }
     }
     if(INTCON.RBIF)
     {
      PORTC.F1=~PORTC.F1;
      INTCON.RBIF=0;
     }
}
void main()
{
     ANSEL =0;
     ANSELH=0;
     TRISA=0; PORTA=0;
     TRISB=0x01; PORTB=0;
     TRISC=0; PORTC=0;
     TRISD=0; PORTD=0;
     TRISE=0; PORTE=0;
     OPTION_REG.INTEDG=1;
     OPTION_REG.T0CS=0;
     OPTION_REG.PSA=0;
     OPTION_REG.PS0=1;
     OPTION_REG.PS1=0;
     OPTION_REG.PS2=0;
     //OPTION_REG.B7=0;
     //WPUB=0x80;
     INTCON.TMR0IE=0;
     INTCON.RBIE=1;
     IOCB.B0=1;
     INTCON.GIE=1;
     UART1_Init(9600);
     Delay_ms(100);
     milis_ctr=milis;
     while(1)
     {
     }
}

Best Answer

You need to read PORTB before clearing the RBIF flag inside interrupt(), otherwise the mismatch will still exist and the RBIF flag won't be cleared. See section 3.4.3 INTERRUPT-ON-CHANGE in the PIC's datasheet:

For enabled interrupt-on-change pins, the present value is compared with the old value latched on the last read of PORTB to determine which bits have changed or mismatched the old value.