# Interrupt on falling edge PIC16F877

The PIC is supplied at 3.3V and clocked at 16kHz. For this part of the design I need the external interrupt to trigger on the falling edge of a 100Hz square wave signal on RB0 and toggle the state of RD7.

In the figure below we can see that the interrupt works as intended when I'm testing it with an SPST switch. The following image is the schematic when using the SPST switch (ignore the LM324 and attached components)

For Trace 1:

• Channel B (Blue) - SPST Input

For both traces:

• Channel C (pink) - RD7 Voltage Level

However in when I attach the square wave (shown in the figure below), it seems to be triggered on the rising edge of the square wave. For Trace 2:

• Channel B (Blue) - 100Hz Signal

At first I thought that for some reason the NE555 was loading the input of RB0 so I added a buffer but that didn't help. I also tried pulling up RB0 but that failed as well. I dug around in the manual and found this:

For external interrupt events, such as the INT pin or PORTB change interrupt, the latency will be three or four instruction cycles.

So it might be that the interrupt is being triggered too quickly? Even at 16kHz however 4 instruction cycles will be 0.001s and the signal period is 0.01s. Does anyone know what might be causing this and how to fix it?

Software used: Proteus Professional 8

                        LIST    p=16f877
INCLUDE <P16F877.INC>

W_TEMP              EQU     0x20
STATUS_TEMP         EQU     0x21
time_hi             EQU     0x22
time_lo             EQU     0x23
time_cp             EQU     0x24
timerCount          EQU     0x25

ORG     0x00
goto    main
ORG     0x04
goto    ISR
ORG     0x20

main
BANKSEL TRISD
bcf     TRISD,RD7
call    interruptSetup

loop
goto    loop

;--------------------------------Configure Interrupts-------------------------------

interruptSetup
call    rb0FallingEdgeInt

call    enableInterrupts

return

rb0FallingEdgeInt
bsf     STATUS,RP0
bcf     STATUS,RP1

bsf     TRISB,RB0
bcf     OPTION_REG,INTEDG
bsf     INTCON,INTE

return

enableInterrupts

bsf     INTCON,PEIE
bsf     INTCON,GIE

return

;------------------------------ISR---------------------------------
ISR
movwf   W_TEMP      ; SAVE  W AND STATUS REGISTERS
swapf   STATUS,W
movwf   STATUS_TEMP
bcf     INTCON,GIE

btfsc   INTCON,INTF
call    fallEdgeIntHandler

bsf     INTCON,GIE
swapf   STATUS_TEMP,W   ; RESTORE W AND STATUS REGISTERS
movwf   STATUS
swapf   W_TEMP,F
swapf   W_TEMP,W

retfie

;---------------------------ISR HANDLERS------------------------------
fallEdgeIntHandler
BANKSEL PORTD
movlw   B'10000000'
xorwf   PORTD,W
movwf   PORTD
bcf     INTCON,INTF
return

END

• A quick test would be to slow the 555 way down (e.g., 10 Hz) to see which input edge the output follows. Also, keep in mind that "interrupt latency" refers to how long it takes to fetch the first instruction of the ISR -- the number of instructions in the ISR determines how soon the pin toggles after that. Show us your code. – Dave Tweed Apr 6 '18 at 11:49
• @DaveTweed what do you mean by "...which input edge the output follows". Also made an edit to include the code. – Simeon R Apr 6 '18 at 15:18
• @S.Ramjit Your top trace has an inconsistency - the third rising edge of the red C trace isn't associated with an edge in B. I'd investigate that. – awjlogan Apr 6 '18 at 15:28
• @awjlogan if you're referring to the last image (10Hz) then it seems the third rising edge of the red C trace is associated with a falling edge in blue B trace. Which is the way it's supposed to work, just it doesn't do that at 100Hz – Simeon R Apr 6 '18 at 15:44
• @S.Ramjit No, your first image, which I think is with the switch. Apologies if I've misinterpreted something! – awjlogan Apr 6 '18 at 16:04