Hello All,
I'm having problems getting the external interrupt to trigger on my robot. The output of a 38kHz IR detector is fed into RB0 the signal is high unless a wave is detected, in which case it drops down to low. I have tried to set the interrupt to trigger on a falling edge. I've tried using the weak pull up resistor, I've added context save/restore even though my program doesn't need it, and I'm stuck.
The ASM is below:
I would greatly appreciate it if you could have a look through and see if there's anything obvious that I'm missing. I have verified that the signal is arriving nicely at the pin, and I've even manually applied high/low voltages to the pin, to no avail.
This is the first time I've used a hardware interrupt, I've only used TMR overflows before, so I may well have left out some obvious step.
Just for reference: The program constantly alternates between lighting two IREDs, and the interrupt should fire when a detector receives signal from one of them.
Thanks a lot,
Barnaby
I'm having problems getting the external interrupt to trigger on my robot. The output of a 38kHz IR detector is fed into RB0 the signal is high unless a wave is detected, in which case it drops down to low. I have tried to set the interrupt to trigger on a falling edge. I've tried using the weak pull up resistor, I've added context save/restore even though my program doesn't need it, and I'm stuck.
The ASM is below:
Rich (BB code):
;
; Author: Barnaby Walters
; Created: 27th March 2011
;
; For PIC: 16F886
; Default Radix: Hex
;
; Description: Contains the IR enable/detect loop. Lights different LEDs to indicate which direction an object is seen in
; Runs at 4MHz
;
; Currently: The interrupt handler is never called. The rest of the program seems to function fine, but no matter what I do
; I can't get the handler routine called.
;
; * * * * * * * * * * * * * * * *
list p=16f886
include p16f886.inc
; Set up 16F886 Config Registers
__CONFIG _CONFIG1, _MCLRE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _BOR_ON & _CP_OFF & _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _CPD_OFF
; For Config Bank 1: No MCLR Reset, no WDT, int. Osc no clkout, BOR On, Code protection, Low voltage protection â essectially, very few features.
__CONFIG _CONFIG2, _BOR40V
; Set the BOR voltage to 4v
; Reserve Variables
tmr1 equ 20h
tmr2 equ tmr1 + 1
tmr3 equ tmr2 + 1
IRData equ tmr3 + 1 ; IRData structure: 7:4 = N/A; 3 = Signal right; 2 = Signal Left; 1 = Right Lit; 0 = Left Lit
w_temp equ IRData + 1
status_temp equ w_temp + 1
;firstAvailableRegister equ 0x20
org 0h
nop ; Allows ICD2 Debugger to work - not that I'm using that.
goto main ; Start main program
nop
nop
; Interrupt Service Routine
movwf w_temp
movf STATUS,w
movwf status_temp ; Save context
; Actual ISR
movlw b'11111001'
movwf PORTC ; Light up most of PORTC, including the indicator LED @ RC3
bcf INTCON,INTF ; Clear ext. int. flag
movf status_temp,w ; Restore context
movwf STATUS
swapf w_temp,f
swapf w_temp,w
retfie ; Return
; * * * * * * * * * * * SUBROUTINES * * * * * * * * * * * * * * *
; Initalisation Routine
init
clrf PORTA
clrf PORTB
clrf PORTC
banksel OSCCON ; switches to bank 1. We need to be here to mess about with TRIS registers
movlw b'01100001' ;
movwf OSCCON ; Osc Config: 0 (un) , 110 (4Mhz) , 000 (Rd Only) , 1 (Use internal Clk)
movlw b'00000000' ;
movwf TRISA ; PORTA = all outputs. A0 = Right indicator A1 = Left Indicator
movlw b'00000001' ;
movwf TRISB ; PORTB 0:3 used. B1 = Right Enable B2 = Left Enable B0 = Sensor Input
movwf WPUB ; Weak pull-up on RB0
movlw b'00000000' ;
movwf TRISC ; PORTC = outputs. C3 = HB LED. Motors not used in this app (yet)
movlw b'1000'
movwf TRISE ; PORTE 3 (MCLR) = Input
banksel OPTION_REG
bcf OPTION_REG,NOT_RBPU ; Enable RB Pull Ups
bcf OPTION_REG,INTEDG ; Interrupt triggered on falling edge @ RB0
movlw b'10010000'
movwf INTCON ; Enable unmasked interrupts, Enable interrupt on RB0
banksel PORTA ; Switch to bank 0 so we can move on with the program
return ; Return to the program
; Delay Routines:
D30IRCycles ; Delays program flow for 30 cycles @ 38kHz 'On' time for IREDs
movlw d'2'
movwf tmr2
movlw d'195' ; 30 IR Cycles = 780 instruction cycles. GOTO = 2 instruction cycles
movwf tmr1 ; This timer will have to be completely decremented two times for the full 780 cycles
D30IR_Delay
decfsz tmr1,f
goto D30IR_Delay ; Cycle 195 times
movwf tmr1
decfsz tmr2,f
goto D30IR_Delay ; Go back and cycle twice
return
D15IRCycles ; Delays program flow for 15 cycles @ 38kHz 'Off' time for IREDs
movlw d'195' ; GOTO = 2 cycles. 2 * 195 = 390 instructions = 15 IR Cycles
movwf tmr1
D15IR_Delay
decfsz tmr1,f
goto D15IR_Delay
return
; * * * * * * * * * * Main Program * * * * * * * * * *
main
call init ; Set up ports, etc
; Program structure: Constantly alternate between IR LEDs. Each one on for 30 cycles, the off for 15 cycles as per datasheet
sensorPollLoop
clrf IRData ; Clear data from last sensor poll loop execution
call D15IRCycles ; Hold LEDs off for the required time
bsf PORTB, 2 ; Turn on the left IRED (Robot perspective)
bsf IRData, 0 ; Left IRED currently emitting.
call D30IRCycles ; Hold it on for a certain amount of time
bcf IRData, 2 ; Left IRED not currently emitting
bcf PORTB, 0 ; Turn off the left IRED
call D15IRCycles ; Hold LEDs off for the required time
bsf PORTB, 1 ; Turn on the right IRED (Robot perspective)
bsf IRData, 1 ; Right IRED currently emitting
call D30IRCycles ; Hold it on for a certain amount of time
bcf IRData, 1 ; Right IRED not currently emitting
bcf PORTB, 1 ; Turn off the right IRED
; One complete sensor poll finished
; Now: See what data we have. For the moment, that means copying the data in IRData 3:2 to PORTA 3:2. How convenient
movf IRData, w ; Pop value of IRData into the W. Reg
movwf PORTA ;
and copy it into PORTA. Sorted!
goto sensorPollLoop
end
This is the first time I've used a hardware interrupt, I've only used TMR overflows before, so I may well have left out some obvious step.
Just for reference: The program constantly alternates between lighting two IREDs, and the interrupt should fire when a detector receives signal from one of them.
Thanks a lot,
Barnaby