Stack over flow error occurred - PIC16F87XA

Thread Starter

walid el masry

Joined Mar 31, 2009
133
hi every body

i want to build a program which uses the external interrupt , TMR0 and TMR1 over flow interrupts
but unfortunately there is a stack over flow error occurred and i noted that

it didn't happen when i never initialize the value for the OPTION_REG
register

1st i tested the code of the TMR1 over flow interrupt to make a 1sec delay and it works, every 1 sec it invert the value of the PORTB so that LED flashes

then when trying to test initialization to use the TMR0 over flow interrupt the
stack over flow error occurred

here is the code i wrote and i hope i was clear

Rich (BB code):
    LIST P=16F876
    #INCLUDE<P16F876.INC>
    __CONFIG _CP_OFF&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_XT_OSC
;************declare variables************
    CBLOCK 0X20
W_TEMP
STATUS_TEMP
PCLATH_TEMP
TMR1_counter
    ENDC
;************Reset vector************
    ORG 0X00
    GOTO INIT     
;*****************Interrupt vector**************************
    ORG 0X04 
;******************Interrup subrutine*****************
;***********************
; code from datasheet 14.12 Context Saving During Interrupts P154
MOVWF W_TEMP ;Copy W to TEMP register
SWAPF STATUS,W ;Swap status to be saved into W
CLRF STATUS ;bank 0, regardless of current bank, Clears IRP,RP1,RP0
MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP register
MOVF PCLATH, W ;Only required if using pages 1, 2 and/or 3
MOVWF PCLATH_TEMP ;Save PCLATH into W
CLRF PCLATH ;Page zero, regardless of current page
;***********************
    BTFSS   PIR1,TMR1IF; is the interrupt accured is for TIMER0 or not ?
    GOTO    ENDI;NO
    BCF     PIR1,TMR1IF;YES
    DECF    TMR1_counter,f; decrement the counter
    btfss   STATUS,Z; test if  counter reaches the end - 1 second have just passed
    GOTO    ENDI;NO
    MOVLW   D'1';YES
    MOVWF   TMR1_counter; re-intiate counter value
;***********************Code Executed every second*************************
ONE
    MOVLW 0X00
    XORWF PORTB,W
    BTFSS STATUS,Z
    GOTO ZERO;NO
    MOVLW 0XFF;YES
    MOVWF PORTB
    GOTO ENDI
ZERO
    MOVLW 0X00
    MOVWF PORTB
;***********************every time when leaving interrupt do this*************************
ENDI
;***********************
; code from datasheet 14.12 Context Saving During Interrupts P154
MOVF PCLATH_TEMP, W ;Restore PCLATH
MOVWF PCLATH ;Move W into PCLATH
SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register into W
;(sets bank to original state)
MOVWF STATUS ;Move W into STATUS register
SWAPF W_TEMP,F ;Swap W_TEMP
SWAPF W_TEMP,W ;Swap W_TEMP into W
;***********************
BSF INTCON,GIE
BSF INTCON,PEIE
BSF STATUS,RP0
BSF PIE1,TMR1IE
BCF STATUS,RP0
    RETFIE; end of interrupt subrutine
;*****************Chip initialize**************************
INIT
BSF STATUS,RP0;goto Bank1
;******************
;initialize PORTs type and direction
MOVLW 0X06
MOVWF ADCON1;PORTA is digital i/o
MOVLW 0X00
MOVWF TRISA;PORTA is output
MOVWF TRISC;PORTC is output
MOVLW 0X01
MOVWF TRISB;PORTB is output exept 1st pin
;******************
MOVLW B'01000111'
;MOVWF OPTION_REG;TMR0 Prescaler Rate 1 : 256 & External interrupt on rising edge
;******************
MOVLW B'11110000';clear TMR0 & External flag
MOVWF INTCON;Enables all unmasked interrupts & unmasked peripheral interrupts & TMR0 & External interrupts
;******************
MOVLW B'00000001'
MOVWF PIE1;Enables the TMR1 overflow interrupt
;******************
BCF STATUS,RP0;goto Bank0
;******************
CLRF TMR0
CLRF TMR1L
CLRF TMR1H
;******************
MOVLW B'00000000'
MOVWF PIR1;clear TMR1 flag
;******************
MOVLW B'00110001'
MOVWF T1CON;TMR1 Prescaler Rate 1 : 8 & Enables Timer1
;******************
;initialize PORTs and variables value
CLRF PORTA
CLRF PORTB
CLRF PORTC
MOVLW   D'1'
MOVWF   TMR1_counter 
;******************
;************************main program********************           
START   
    GOTO START
    END
note that ones i remove the ";" beside the "MOVWF OPTION_REG"
the stack over flow occurs

and this is the test circuit
 

Markd77

Joined Sep 7, 2009
2,806
The line :
BSF INTCON,GIE
is a problem, you are enabling global interupts inside the interrupt which means that it never gets to the RETFIE instruction (which enables interrupts anyway)
You have also not cleared the bit in status that caused the interrupt which is what is causing it to be retriggered.
Use :
BCF INTCON,2
and get rid of the BSF INTCON,GIE
No more stack overflows
 

Thread Starter

walid el masry

Joined Mar 31, 2009
133
but RETFIE also makes INTCON,GIE = 1 but return to last destination in the code before the interrupt , how dose setting GIE bit before RETFIEaffect the interrupt subrutine , i tested to rmove the statement BSF INTCON,GIE before RETFIE and it works

BCF INTCON,2
and get rid of the BSF INTCON,GIE
No more stack overflows
do you mean when handling the interrupt from INTCON i must disable other interrupts so that no interrupts happens in the same time or what ?


 
The 16F have only one interrupt vector. If another interrupt occurs while your program is in the ISR it will get flagged and serviced as soon as the retfie is executed.
 

Markd77

Joined Sep 7, 2009
2,806
When the interrupt happens interrupts are automatically disabled (and the program counter is saved on the stack). When it gets to RETFIE they are automatically turned back on and code continues from where it was before the interrupt happened (and the stack is 1 smaller). If any interrupt flags are set at that point (not cleared in the interrupt routine or happened during the interrupt routine) then it will skip back to the interrupt again.
If you enable interrupts during the interrupt routine and a flag is set then it jumps immediately to the start of the interrupt, adding another item to the stack. When the stack is full you get the stack overflow problem.
Hope this helps.
 

Thread Starter

walid el masry

Joined Mar 31, 2009
133
@ Markd77 :

you very clear and what i get is that when handling an interrupt we must disable other interrupts so that we finish the current one correctly and avoid conflicting with other interrupts cause if iam handling an interrupt now and never disable other interrupts and another interrupt happened the mcu leaves the 1st one and go to handle the 2nd

that's what i get from you but

@ blueroomelectronics :

you said that in 16F core when handling an interrupt and another one occurred it finishes the 1st one then go to handle the 2nd one but how can it be when we in the same time we had disabled other interrupts so that we can handle the 1st one correctly like Markd77 said ?!?!

i guess in that case the interrupt loses it's meaning or what ??

what iam understand about the interrupts is that when the controller have an interrupt it leaves the main program and goes to execute another one written in the interrupt vector then return to the last position in the program and if interrupt happened then another one of another type happened it will leave the 1st an goes to handle the second

is that wright or what ?
 

Thread Starter

walid el masry

Joined Mar 31, 2009
133
i know that, we r talking about the bits of GIE & PEIE which we should clear them when interrupt happens , then how could the chip know that interrupt happens when handling an interrupt and these bits are cleared ?

is the flag of other interrupt are set in the same time these bits are cleared and the chip handling an interrupt ?

 
Top