Stack over flow error occurred - PIC16F87XA

Discussion in 'Embedded Systems and Microcontrollers' started by walid el masry, Oct 13, 2009.

  1. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    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

    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

    Code ( (Unknown Language)):
    2.     LIST P=16F876
    3.     #INCLUDE<P16F876.INC>
    5. ;************declare variables************
    6.     CBLOCK 0X20
    7. W_TEMP
    10. TMR1_counter
    11.     ENDC
    12. ;************Reset vector************
    13.     ORG 0X00
    14.     GOTO INIT    
    15. ;*****************Interrupt vector**************************
    16.     ORG 0X04
    17. ;******************Interrup subrutine*****************
    18. ;***********************
    19. ; code from datasheet 14.12 Context Saving During Interrupts P154
    20. MOVWF W_TEMP ;Copy W to TEMP register
    21. SWAPF STATUS,W ;Swap status to be saved into W
    22. CLRF STATUS ;bank 0, regardless of current bank, Clears IRP,RP1,RP0
    23. MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP register
    24. MOVF PCLATH, W ;Only required if using pages 1, 2 and/or 3
    26. CLRF PCLATH ;Page zero, regardless of current page
    27. ;***********************
    28.     BTFSS   PIR1,TMR1IF; is the interrupt accured is for TIMER0 or not ?
    29.     GOTO    ENDI;NO
    30.     BCF     PIR1,TMR1IF;YES
    31.     DECF    TMR1_counter,f; decrement the counter
    32.     btfss   STATUS,Z; test if  counter reaches the end - 1 second have just passed
    33.     GOTO    ENDI;NO
    34.     MOVLW   D'1';YES
    35.     MOVWF   TMR1_counter; re-intiate counter value
    36. ;***********************Code Executed every second*************************
    37. ONE
    38.     MOVLW 0X00
    39.     XORWF PORTB,W
    40.     BTFSS STATUS,Z
    41.     GOTO ZERO;NO
    42.     MOVLW 0XFF;YES
    43.     MOVWF PORTB
    44.     GOTO ENDI
    45. ZERO
    46.     MOVLW 0X00
    47.     MOVWF PORTB
    48. ;***********************every time when leaving interrupt do this*************************
    49. ENDI
    50. ;***********************
    51. ; code from datasheet 14.12 Context Saving During Interrupts P154
    53. MOVWF PCLATH ;Move W into PCLATH
    54. SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register into W
    55. ;(sets bank to original state)
    56. MOVWF STATUS ;Move W into STATUS register
    57. SWAPF W_TEMP,F ;Swap W_TEMP
    58. SWAPF W_TEMP,W ;Swap W_TEMP into W
    59. ;***********************
    62. BSF STATUS,RP0
    63. BSF PIE1,TMR1IE
    64. BCF STATUS,RP0
    65.     RETFIE; end of interrupt subrutine
    66. ;*****************Chip initialize**************************
    67. INIT
    68. BSF STATUS,RP0;goto Bank1
    69. ;******************
    70. ;initialize PORTs type and direction
    71. MOVLW 0X06
    72. MOVWF ADCON1;PORTA is digital i/o
    73. MOVLW 0X00
    74. MOVWF TRISA;PORTA is output
    75. MOVWF TRISC;PORTC is output
    76. MOVLW 0X01
    77. MOVWF TRISB;PORTB is output exept 1st pin
    78. ;******************
    79. MOVLW B'01000111'
    80. ;MOVWF OPTION_REG;TMR0 Prescaler Rate 1 : 256 & External interrupt on rising edge
    81. ;******************
    82. MOVLW B'11110000';clear TMR0 & External flag
    83. MOVWF INTCON;Enables all unmasked interrupts & unmasked peripheral interrupts & TMR0 & External interrupts
    84. ;******************
    85. MOVLW B'00000001'
    86. MOVWF PIE1;Enables the TMR1 overflow interrupt
    87. ;******************
    88. BCF STATUS,RP0;goto Bank0
    89. ;******************
    90. CLRF TMR0
    91. CLRF TMR1L
    92. CLRF TMR1H
    93. ;******************
    94. MOVLW B'00000000'
    95. MOVWF PIR1;clear TMR1 flag
    96. ;******************
    97. MOVLW B'00110001'
    98. MOVWF T1CON;TMR1 Prescaler Rate 1 : 8 & Enables Timer1
    99. ;******************
    100. ;initialize PORTs and variables value
    101. CLRF PORTA
    102. CLRF PORTB
    103. CLRF PORTC
    104. MOVLW   D'1'
    105. MOVWF   TMR1_counter
    106. ;******************
    107. ;************************main program********************          
    108. START  
    109.     GOTO START
    110.     END
    note that ones i remove the ";" beside the "MOVWF OPTION_REG"
    the stack over flow occurs

    and this is the test circuit
  2. Markd77

    Senior Member

    Sep 7, 2009
    The line :
    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 :
    and get rid of the BSF INTCON,GIE
    No more stack overflows
  3. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    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

    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 ?

  4. blueroomelectronics

    AAC Fanatic!

    Jul 22, 2007
    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.
  5. Markd77

    Senior Member

    Sep 7, 2009
    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.
  6. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    @ 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 ?
  7. blueroomelectronics

    AAC Fanatic!

    Jul 22, 2007
    An interrupt sets a flag bit. That's why you have to clear it after you've serviced it.
  8. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    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 ?

  9. blueroomelectronics

    AAC Fanatic!

    Jul 22, 2007
    No GIE is cleared automatically when the interrupt occurs, it is set with retfie
  10. walid el masry

    Thread Starter Active Member

    Mar 31, 2009
    aha that is it

    thnx every body