PDA

View Full Version : calling subroutine triggers interrupt



Alexey
- 19th May 2011, 03:12
Hello All,

Please advise if this is a known issue: I programmed PIC16F688 for interrupt on A2/INT on dropping edge which works fine, but I got a problem - every time I call any subroutine, it triggers the interrupt, even if the subroutine is empty like this:

SBRTN:
RETURN

every call to any subroutine (gosub ...) results execution of my interrupt handler subroutine.

Is this something known and caused by a common mistake?

Thank you,
Alexey

mister_e
- 19th May 2011, 03:20
don't post any code just in case we could find the mistake in ;)

Alexey
- 19th May 2011, 04:00
Hi Steve,

I thought this may be a known thing - did not want to bother gurus with long garbage code some pieces of which do not make sense until the rest is written. The line GOSUB VOLTMTR IS A PROBLEM - causes interrupt and execution of code of interrupt handler BTN_CHECK before code of VOLTMTR is executed :(


@ DEVICE pic16F688, WDT_OFF, INTOSCIO, PWRT_ON, MCLR_ON, BOD_OFF
@ DEVICE CPD_OFF, PROTECT_OFF 'DATA AND CODE MEMORY PROTECTION
INTCON = 0
DISABLE
define OSC 4

clear

;---------INPUTS AND OUTPUTS-------------
'PORTA.0 ICSPDAT, CONF AS OUTPUT
'PORTA.1 ICSPCLK, CONF AS OUTPUT
'PORTA.2 ON/OFF BUTTON INPUT, WEAK PULL UP
'PORTA.3 VPP, CONF AS MCLR, CONF AS MCLR, WEAK PULL-UP
'PORTA.4 AN2 VOLTAGE METER INPUT, NO WEAK PULL UP

'PORTA.5 EXT ACTIVATION INPUT, WEAK PULL UP

'PORTC.0 DIAG OUT OUTPUT
'PORTC.1 DIAGNOSTIC INPUT INPUT
'PORTC.2 YELLOW WIRE OUTPUT

'PORTC.3 NOT USED OUTPUT, ZERO
'PORTC.4 RED LED OUTPUT
'PORTC.5 GREEN LED OUTPUT


;---------VARIABLES----------------------

BTN VAR PORTA.2
YW VAR PORTC.2
REDLED VAR PORTC.4
GREENLED VAR PORTC.5


FCODE VAR BYTE
COUNTER VAR byte
COUNTER2 VAR BYTE
COUNTER3 VAR BYTE
N VAR BYTE
CALC VAR BYTE
NF VAR BYTE
F VAR BYTE[5] 'AF,F1,F2,F3,F4,F5
POWER VAR BIT
VOLT VAR BYTE 'VOLTAGE IN 0.1294 V UNITS
LVCOUNT VAR BYTE 'COUNTER FOR LOW TIME
VTR VAR BYTE 'VOLTAGE TRESHOLD

'--------------------DEFINITIONS-----------
'FOR SERIAL INPUT:
dEFINE DEBUGIN_REG PORTC 'GPIO ' Debugin pin port
DEFINE DEBUGIN_BIT 1 ' Debugin pin bit
DEFINE DEBUGIN_MODE 0 ' Debugin mode: 0 = True, 1 = Inverted
DEFINE DEBUG_BAUD 1200 ' Debug baud rate
'-----------PORTS CONFIGURATION------------
CMCON0 = 7 'TURN COMPARATORS OFF
VRCON = 0 'VOLTAGE REFERENCE OFF TO SAVE POWER OPTION_REG.7 = 0
OPTION_REG = 0
ANSEL = %1000 'PORTA4/AN3 IS ANALOG
WPUA = %100100 'PULL UPS ON A.2 AND A.5 (BUTTON AND EXT SWITCH)
PORTA = 0 'OUTPUTS ON PORTA LOW (ALL UNUSED)
TRISA = %111100 'SET PORT A FOR OUTPUTS ON PINS 0,1 (UNUSED) ALL OTHER INPUTS
PORTC=0 'yellow wire low, LEDs OFF, DIAG WIRE UP
TRISC = %000010 'SET PORT C FOR INPUT ON PIN 1 (DIAG IN) ALL OTHER OUTPUTS

'-----DETECTING IF THE SYSTEM IS 12 OR 24 VOLTS----

ADCON0=%00001101 'LEFT JUSTIFIED(0),VDD ref(0),not used,AN3 USED(011),NO START NOW,STAY ON
ADCON1=%00010000 'CONVERSION CLOCK SELECT FOSC/32
ANSEL=%1000 'USE AN3

GOSUB VOLTMTR 'THIS CALL TRIGGERS INTERRUPT EVEN WHEN SUBROUTINE VOLTMTR IS EMPTY
'ADCIN 3,VOLT 'this option works OK

IF VOLT < 124 THEN 'IF VOLTAGE < 16 V
GREENLED = 1
VTR = 97

ELSE
VTR = 210
REDLED = 1
ENDIF

PAUSE 1000 'TO DEBUG
PORTC = 0 'TO DEBUG
PAUSE 1000
FCODE = VOLT

ENABLE
'---------INTERRUPTS CONFIG-----------
OPTION_REG.6 = 0 'INTERRUPTS ON FAILING EDGE (BUTTON PRESSED)
INTCON = %10000 'ENABLES RA2 (1,) OTHER INTERRUPTS ON PORTA ARE OFF (BIT 3)
IOCA = %100 'ENABLES INTERRUPT ON PORTA.2

ON INTERRUPT GOTO BTN_CHECK ' CHECK ON/OFF BUTTON

START: if yw = 0 then NAP 7 'THIS REDUCES CURRENT FROM 6 TO 4 mA
GOSUB PAUSE_60
IF YW = 1 THEN GOSUB VOLTAGE
GOTO START 'WAIT HERE TILL INTERRUPTED

''''--------------SUBROUTINES--------------------------
'----------READ VOLTAGE---------------
VOLTAGE:
GOSUB VOLTMTR

IF VOLT < VTR THEN
LVCOUNT = LVCOUNT +1
REDLED = 1 'TURN RED ON SO THE LIGHT BECOMES YELLOW
ELSE
IF LVCOUNT > 0 THEN LVCOUNT = LVCOUNT - 1
IF LVCOUNT = 0 THEN REDLED = 0
ENDIF

IF LVCOUNT = 5 THEN
PORTC=0
lvcount = 0
endif
RETURN

'-----------PAUSE 60 sec--------------
N2 VAR BYTE
PAUSE_60:
FOR N2 = 1 TO 60
PAUSE 100'0
NEXT N2
RETURN

TEST:
N = PORTA 'READ PORT A TO CLEAR MISMUTCH, NOTHING ELSE
' INTCON.0=0 'CLEAR INTERRUPT FLAG AFTER READING PORT (RAIF FLAG) not needed
INTCON.1 = 0 'CLEAR INTF FLAG FOR PORT RA2
RETURN

'---------VOLTMETER ROUTINE----------
VOLTMTR:
ADCON0=%00001101 'LEFT JUSTIFIED(0),VDD ref(0),not used,AN3 USED(011),NO START NOW,STAY ON
ADCON1=%00010000 'CONVERSION CLOCK SELECT FOSC/32
ANSEL=%1000 'USE AN3
PAUSE 1
ADCON0 = %1111 'LEFT JUSTIFIED,VDD ref,not used,not used,AN3 USED(011),STARTS IMMEDIATELY,STAY ON
ADCONV:
pauseus 50 'allow time for ADC calculation
IF ADCON0.1 = 1 THEN GOTO ADCONV
volt = ADRESH

RETURN

'---------------------------------------------------
SHOW_RESULT:
IF FCODE =0 THEN
GREENLED = 1 'IF AF=0 -> GREEN LED ON REDLED OFF
REDLED = 0
PAUSE 10000 'STAY ON 10 SEC
GREENLED = 0 'GPIO = 0 'TURN LED OFF
ELSE
CALC = FCODE/10 'CALCULATE BLINKS
GOSUB BLINKING 'BLINK 10S
GREENLED = 1
PAUSE 50
GREENLED = 0
PAUSE 1500
CALC=FCODE//10
GOSUB BLINKING 'BLINK 1S
ENDIF
RETURN
'---------------------------------------------------
BLINKING:
for COUNTER3 = 1 TO CALC
REDLED = 1
PAUSE 1000
REDLED = 0
PAUSE 350
NEXT COUNTER3
PAUSE 1500 'DIVIDER BETWEEN 10s, 1s AND CONTINUING
RETURN

DISABLE 'INTERRUPT
BTN_CHECK:
IF YW = 0 THEN
GREENLED = 1
yw = 1
ELSE
PORTC=0
ENDIF
PAUSE 1000 'ANTI VIBRATION
N = PORTA 'READ PORT A TO CLEAR MISMUTCH, NOTHING ELSE
' INTCON.0=0 'CLEAR INTERRUPT FLAG AFTER READING PORT (RAIF FLAG)
INTCON.1 = 0 'CLEAR INTF FLAG FOR PORT RA2
RESUME
ENABLE 'INTERRUPT


Thanks again,

Alexey

mister_e
- 19th May 2011, 05:59
weird, may need to sleep on that one, what if you clear the INT flag before that gosub?
INTCON.1 = 0

Alexey
- 19th May 2011, 14:10
Hi Mister_E,

Unfortunately this does not help. I removed all irrelevant code from the program to make it more clear, sorry for not doing this before. The code I have now for test is below. When it starts, calling empty Test subroutine always triggers interrupt so the GREENLED is ON. If I disable the GOSUB TEST, then it starts with GREENLED OFF (interrupt handler did not run)

This is the first time I play with interrupt - most likely do something wrong. The MCU is PIC16F688

@ DEVICE pic16F688, WDT_OFF, INTOSCIO, PWRT_ON, MCLR_ON, BOD_OFF

define OSC 4
clear
'---------INTERRUPTS CONFIG-----------
INTCON = %10000 'ENABLES RA2 (1,) OTHER INTERRUPTS ON PORTA ARE OFF (BIT 3)
IOCA = %100 'ENABLES INTERRUPT ON PORTA.2
;---------VARIABLES----------------------

BTN VAR PORTA.2
YW VAR PORTC.2
REDLED VAR PORTC.4
GREENLED VAR PORTC.5
N VAR BYTE


'-----------PORTS CONFIGURATION------------
OPTION_REG = 0
ANSEL = %1000 'PORTA4/AN3 IS ANALOG
TRISA = %111100 'SET PORT A FOR OUTPUTS ON PINS 0,1 (UNUSED) ALL OTHER INPUTS
TRISC = %000010 'SET PORT C FOR INPUT ON PIN 1 (DIAG IN) ALL OTHER OUTPUTS
'THE FOLLOWING DID NOT HELP
N=PORTA 'JUST TO READ PORTA
INTCON.0=0 'CLEAR INTERRUPT FLAG AFTER READING PORT (RAIF FLAG)
INTCON.1=0 'CLEAR INTF FLAG FOR PORT RA2
PORTC=0 'GREENLED SHOULD STAY OFF

GOSUB TEST 'THIS SUBROUTINE ALWAYS CAUSES INTERRUPT!!!
'NOW GREENLED ON PORT C5 IS ON !!!



'THE FOLLOWING DID NOT HELP
N = PORTA 'READ PORT A TO CLEAR MISMUTCH, NOTHING ELSE
INTCON.0=0 'CLEAR INTERRUPT FLAG AFTER READING PORT
INTCON.1=0

ON INTERRUPT GOTO BTN_CHECK ' CHECK ON/OFF BUTTON

START:
GOTO START 'WAIT HERE TILL INTERRUPTED


TEST: 'NO CODE IN THIS SUBROUTINE

RETURN

DISABLE
BTN_CHECK:
IF GREENLED = 0 THEN
GREENLED = 1
ELSE
PORTC=0
ENDIF
'' PAUSE 1000 'ANTI VIBRATION
N = PORTA 'READ PORT A TO CLEAR MISMUTCH, NOTHING ELSE
INTCON.0=0 'CLEAR INTERRUPT FLAG AFTER READING PORT (RAIF FLAG)
INTCON.1 = 0 'CLEAR INTF FLAG FOR PORT RA2
RESUME
ENABLE

Darrel Taylor
- 19th May 2011, 14:40
I think Steve meant to clear the flag before the GOSUB TEST, not before the ON INTERRUPT GOTO.

It GOSUB's from an area that is DISABLEd to one that is ENABLED.
If the flag is set, it will jump to the ISR.
It may jump, even if it's not set.

The ISR should verify that the flag is set before doing anything.

Bruce
- 19th May 2011, 16:49
Without INTCON.7 set before ON INTERRUPT, it's going to jump to your interrupt vector all the time in any code section where interrupt code is inserted. If you just set INTCON.7 it should never jump there until the hardware interrupt clears INTCON.7 automatically.

INTCON = %10000 doesn't set INTCON.7 - so the ON INTERRUPT code inserted always assumes an interrupt condition exists.

Alexey
- 20th May 2011, 03:50
Darrel, Bruce,

Thank you!

I tried to move "On interrupt goto" to the very top and also check flag in the interrupt handler, either one works just fine.

Will play with INTCON.7 tomorrow morning.

Thanks again, the problem seems to be solved

Alexey