+ Reply to Thread
Results 1 to 6 of 6
  1. #1
    Join Date
    Jun 2017
    Posts
    39

    Post Interrupt issue with PIC16F18877 and DT-Ints...

    Hello everyone,

    I have a board that uses a PIC16F18877 to check the states of 16 inputs using IOC interrupts. Once one of the interrupts are triggered, I set a corresponding flag that is checked in the main loop. If the flag is set, I set 1 of 16 outputs until a user defined counter has reached its predetermined value, then I clear the flag and clear the output. This stage works well.

    Included in with my interrupts in a separate handler, I toggle an LED for my heart beat.

    My issue is that when I start the heart beat interrupt, sometimes the PIC will freeze and sometimes it doesn't. More often then not, the PIC will freeze with my heart beat LED always on.
    I would appreciate a second pair of eyes to look over this short bit of code and point out what I may be doing wrong.

    Code:
    ;*******************************************************************************
    ; Defines section.
    ;*******************************************************************************
        DEFINE OSC 32           ; Oscillator set to 32Mhz set by Config1 above.
    ;*******************************************************************************
    ; Timer 1 control registers.
    ;*******************************************************************************
        T1CON   = %00110110     ; Prescaler=8, Do not Synch, TMR1 OFF.
        T1GCON  = %00000000     ; Timer 1 Gate disabled.
        T1CLK   = %00000101     ; MFINTOSC Selected for Timer 1 clock source.
    
    
        PIR4.0 = 0
        TMR1L = $0A
        TMR1H = 0
    ;*******************************************************************************
    ; Interrupt control registers.    Not used.
    ;*******************************************************************************
        INTCON  = %11000000     ; 
    '    PIE0    = %00000000     ; 
    '    PIE1    = %00000000     ;  
    '    PIE2    = %00000000     ;
    '    PIE3    = %00000000     ;
        PIE4    = %00000001     ;
    '    PIE5    = %00000000     ;
    '    PIE6    = %00000000     ;
    '    PIE7    = %00000000     ;
    '    PIE8    = %00000000     ;
    ;*******************************************************************************
    ; Interrupt On Change for ports with IOC.  Ports A,B and C only apply.   
    ; 1 = enabled, 0 = diabled.
    ;*******************************************************************************
        IOCAF = %00000000       ; Interrupt-on-Change PORTA flags.
        IOCAP = %11111111       ; Interrupt-on-Change PORTA Positive Edge Enable bits.
        IOCAN = %00000000       ; Interrupt-on-Change PORTA Negative Edge Enable bits.
        
        IOCBF = %00000000       ; Interrupt-on-Change PORTB flags.
        IOCBP = %11111111       ; Interrupt-on-Change PORTB Positive Edge Enable bits.
        IOCBN = %00000000       ; Interrupt-on-Change PORTB Negative Edge Enable bits.
    ;*******************************************************************************
    ;ASM INTERRUPTS COURTESY OF DARREL TAYLOR.	
    ;*******************************************************************************
        ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR1_INT,         _ToggleLED1,  PBP,  yes 
            INT_Handler   IOC_INT,          _RelaySense,  PBP,  yes
    
    
        endm
        INT_CREATE              ; Creates the interrupt processor
        ENDASM
    
    
        PAUSE 500
        goto Start
    ;*******************************************************************************
    ; INTERRUPT SERVICE ROUTINES START HERE.
    ;*******************************************************************************
    ; IOC interrupt handler checks which interrupt flag has been set for PORTA and
    ; PORTB.  Each flag bit corresponds to an output. Example: IF IOCAF.1 is set,
    ; then we set TimerEnable.1, which then is checked in the Main loop, which then
    ; sets PORTC.1 Output high for the duration of the counter.
    ;*******************************************************************************
    RelaySense:  
        TempIOCFlgs.byte0 = IOCAF   ; Copy IOC Flags to a temp register.
        TempIOCFlgs.byte1 = IOCBF   ; Copy IOC Flags to a temp register.
        for GPCounter = 0 to 15     
            if TempIOCFlgs.0[GPCounter] = 1 then   ; Check each flag to see if it's set.
                TimerEnable.0[GPCounter] = 1       ; If so, set Timer enable flags to check in Main loop.
    '            TempPortS.0[GPCounter] = 1
            endif
        next GPCounter 
    
    
        TempIOCAF = IOCAF ^ $FF     ; Clear the individual interrupt flags.
        IOCAF = TempIOCAF & IOCAF 
    
    
        
        TempIOCBF = IOCBF ^ $FF     ; Clear the individual interrupt flags.
        IOCBF = TempIOCBF & IOCBF
    
    
    @ INT_RETURN 
    
    
    ;*******************************************************************************
    ; Timer 1 interrupt handler toggles StatLED1 as our heart beat. 
    ;*******************************************************************************
    ToggleLED1:
        toggle StatLED1     ; Toggle Heart Beat LED once per a little over 1 second.
    @ INT_RETURN 
    
    
    ;*******************************************************************************
    ; CODE STARTS HERE.
    ;******************************************************************************* 
    ; Start of program.  We clear all variables, initialize those that need to be
    ; and turn on our Status LEDs for half a second.
    ;******************************************************************************* 
    Start:
        clear
        IOCAF = $FF             ; Clear PortA IOC flag register. 
        IOCBF = $FF             ; Clear PortB IOC flag register. 
        TempPortS = $FFFF       ; Initialize variable.
        LATE = 0                ; Turn on Yellow Stat LEDs.   LED check and Version header.
        pause 800               ; Wait 1/2 Second.
        
        StatLED2 = 0            ; Turn on Yellow Stat LED.    Display binary number 1. 
        StatLED3 = 1            ; Turn off Yellow Stat LED.     
        StatLED4 = 1            ; Turn off Yellow Stat LED. 
        pause 800               ; Wait 1/2 Second.
        LATE = 7                ; Turn off Yellow Stat LEDs.
         
        StatLed1 = 1            ; Toggling the Blue led indicates sub-version or decimal point.
        pause 300
        StatLed1 = 0
        pause 300
        StatLed1 = 1
        pause 300
       
        StatLED2 = 0            ; Turn on Yellow Stat LED.    Display binary number 3.  
        StatLED3 = 0            ; Turn on Yellow Stat LED.      
        StatLED4 = 1            ; Turn off Yellow Stat LED.   
        pause 800               ; Wait 1/2 Second.
        LATE = 7                ; Turn off Yellow Stat LEDs.
    
    
        T1CON.0 = 1             ; Enable Timer 1
    
    
    @ INT_ENABLE  TMR1_INT      ; Enable Timer 1 interrupts    
    @ INT_ENABLE  IOC_INT       ; Enable Interrupts On Change interrupts
    
    
    ;*******************************************************************************
    ;*******************************************************************************
    ; Main loop where we check the TimerEnable flag bits to see if they are set.
    ; If set, then we set the SurgeCntX output high, decrement the SCCounter until
    ; it reaches ZERO, and then clear the output and our TimerEnableX flag bit. 
    ; Output pulse is 300mS long.
    ;******************************************************************************* 
    Main: ...
    The code below shows what I do and when I start to use the heart beat.

  2. #2
    Join Date
    Jan 2006
    Location
    Istanbul
    Posts
    1,235

    Default Re: Interrupt issue with PIC16F18877 and DT-Ints...

    What is main loop?

    If you are calling a subroutine within from main loop, it may be the issue.
    "If the Earth were a single state, Istanbul would be its capital." Napoleon Bonaparte

  3. #3
    Join Date
    Jun 2017
    Posts
    39

    Post Re: Interrupt issue with PIC16F18877 and DT-Ints...

    Quote Originally Posted by sayzer View Post
    What is main loop?

    If you are calling a subroutine within from main loop, it may be the issue.
    Here is the main loop. Nothing fancy, just setting and clearing outputs based on flags that are set at the ISR and corresponding variable counters...
    Code:
    ;*******************************************************************************
    ; Main loop code now begins here.
    ;*******************************************************************************
    Main:
        if TimerEnable.1 = 1 then               ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter1 = 0 then              ; Check if counter has timed out.
                SCCounter1 = TimerCounts        ; Reset counter.
                SurgeCnt1 = 0                   ; Clear the Surge control pin output. 
                TimerEnable.1 = 0               ; Clear the timer enable flag.
            else
                SurgeCnt1 = 1                   ; Set the Surge control pin output.
                SCCounter1 = SCCounter1 - 1     ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.2 = 1 then               ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter2 = 0 then              ; Check if counter has timed out.
                SCCounter2 = TimerCounts        ; Reset counter.
                SurgeCnt2 = 0                   ; Clear the Surge control pin output. 
                TimerEnable.2 = 0               ; Clear the timer enable flag.
            else
                SurgeCnt2 = 1                   ; Set the Surge control pin output.
                SCCounter2 = SCCounter2 - 1     ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.3 = 1 then               ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter3 = 0 then              ; Check if counter has timed out.
                SCCounter3 = TimerCounts        ; Reset counter.
                SurgeCnt3 = 0                   ; Clear the Surge control pin output. 
                TimerEnable.3 = 0               ; Clear the timer enable flag.
            else
                SurgeCnt3 = 1                   ; Set the Surge control pin output.
                SCCounter3 = SCCounter3 - 1     ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.4 = 1 then               ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter4 = 0 then              ; Check if counter has timed out.
                SCCounter4 = TimerCounts        ; Reset counter.
                SurgeCnt4 = 0                   ; Clear the Surge control pin output. 
                TimerEnable.4 = 0               ; Clear the timer enable flag.
            else
                SurgeCnt4 = 1                   ; Set the Surge control pin output.
                SCCounter4 = SCCounter4 - 1     ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.5 = 1 then               ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter5 = 0 then              ; Check if counter has timed out.
                SCCounter5 = TimerCounts        ; Reset counter.
                SurgeCnt5 = 0                   ; Clear the Surge control pin output. 
                TimerEnable.5 = 0               ; Clear the timer enable flag.
            else
                SurgeCnt5 = 1                   ; Set the Surge control pin output.
                SCCounter5 = SCCounter5 - 1     ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.6 = 1 then               ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter6 = 0 then              ; Check if counter has timed out.
                SCCounter6 = TimerCounts        ; Reset counter.
                SurgeCnt6 = 0                   ; Clear the Surge control pin output. 
                TimerEnable.6 = 0               ; Clear the timer enable flag.
            else
                SurgeCnt6 = 1                   ; Set the Surge control pin output.
                SCCounter6 = SCCounter6 - 1     ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.7 = 1 then               ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter7 = 0 then              ; Check if counter has timed out.
                SCCounter7 = TimerCounts        ; Reset counter.
                SurgeCnt7 = 0                   ; Clear the Surge control pin output. 
                TimerEnable.7 = 0               ; Clear the timer enable flag.
            else
                SurgeCnt7 = 1                   ; Set the Surge control pin output.
                SCCounter7 = SCCounter7 - 1     ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.8 = 1 then               ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter8 = 0 then              ; Check if counter has timed out.
                SCCounter8 = TimerCounts        ; Reset counter.
                SurgeCnt8 = 0                   ; Clear the Surge control pin output. 
                TimerEnable.8 = 0               ; Clear the timer enable flag.
            else
                SurgeCnt8 = 1                   ; Set the Surge control pin output.
                SCCounter8 = SCCounter8 - 1     ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.9 = 1 then               ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter9 = 0 then              ; Check if counter has timed out.
                SCCounter9 = TimerCounts        ; Reset counter.
                SurgeCnt9 = 0                   ; Clear the Surge control pin output. 
                TimerEnable.9 = 0               ; Clear the timer enable flag.
            else
                SurgeCnt9 = 1                   ; Set the Surge control pin output.
                SCCounter9 = SCCounter9 - 1     ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.10 = 1 then              ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter10 = 0 then             ; Check if counter has timed out.
                SCCounter10 = TimerCounts       ; Reset counter.
                SurgeCnt10 = 0                  ; Clear the Surge control pin output. 
                TimerEnable.10 = 0              ; Clear the timer enable flag.
            else                          
                SurgeCnt10 = 1                  ; Set the Surge control pin output.
                SCCounter10 = SCCounter10 - 1   ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.11 = 1 then              ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter11 = 0 then             ; Check if counter has timed out.
                SCCounter11 = TimerCounts       ; Reset counter.
                SurgeCnt11 = 0                  ; Clear the Surge control pin output. 
                TimerEnable.11 = 0              ; Clear the timer enable flag.
            else                                
                SurgeCnt11 = 1                  ; Set the Surge control pin output.
                SCCounter11 = SCCounter11 - 1   ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.12 = 1 then              ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter12 = 0 then             ; Check if counter has timed out.
                SCCounter12 = TimerCounts       ; Reset counter.
                SurgeCnt12 = 0                  ; Clear the Surge control pin output. 
                TimerEnable.12 = 0              ; Clear the timer enable flag.
            else
                SurgeCnt12 = 1                  ; Set the Surge control pin output.
                SCCounter12 = SCCounter12 - 1   ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.13 = 1 then              ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter13 = 0 then             ; Check if counter has timed out.
                SCCounter13 = TimerCounts       ; Reset counter.
                SurgeCnt13 = 0                  ; Clear the Surge control pin output. 
                TimerEnable.13 = 0              ; Clear the timer enable flag.
            else
                SurgeCnt13 = 1                  ; Set the Surge control pin output.
                SCCounter13 = SCCounter13 - 1   ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.14 = 1 then              ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter14 = 0 then             ; Check if counter has timed out.
                SCCounter14 = TimerCounts       ; Reset counter.
                SurgeCnt14 = 0                  ; Clear the Surge control pin output. 
                TimerEnable.14 = 0              ; Clear the timer enable flag.
            else
                SurgeCnt14 = 1                  ; Set the Surge control pin output.
                SCCounter14 = SCCounter14 - 1   ; Decrement the counter while timer is enabled.
            endif
        endif
        
        if TimerEnable.15 = 1 then              ; Check if Timer has been enabled by IOC interrupt.
            if SCCounter15 = 0 then             ; Check if counter has timed out.
                SCCounter15 = TimerCounts       ; Reset counter.
                SurgeCnt15 = 0                  ; Clear the Surge control pin output. 
                TimerEnable.15 = 0              ; Clear the timer enable flag.
            else
                SurgeCnt15 = 1                  ; Set the Surge control pin output.
                SCCounter15 = SCCounter15 - 1   ; Decrement the counter while timer is enabled.
            endif
        endif
            
        goto main            
         
    ;******************************************************************************* 
    
    ;*******************************************************************************
        end							                                          
    ;*******************************************************************************

  4. #4
    Join Date
    Jan 2006
    Location
    Istanbul
    Posts
    1,235

    Default Re: Interrupt issue with PIC16F18877 and DT-Ints...

    I could not find anything about freezing issue with my eyes, but realized something different as a suggestion:

    You can simply "relaysense" routine as follows:

    Code:
    RelaySense:  
        TimerEnable.byte0 = IOCAF 
        TimerEnable.byte1 = IOCBF 
    
    ' You have already read the flags; thus, no need for individual clear.
        IOCAF = 0
        IOCBF = 0
    
    
    @ INT_RETURN

    For freezing issue, your program may be jumping to another address.
    Last edited by sayzer; - 8th July 2019 at 20:01.
    "If the Earth were a single state, Istanbul would be its capital." Napoleon Bonaparte

  5. #5
    Join Date
    Jun 2017
    Posts
    39

    Default Re: Interrupt issue with PIC16F18877 and DT-Ints...

    Quote Originally Posted by sayzer View Post
    I could not find anything about freezing issue with my eyes, but realized something different as a suggestion:

    You can simply "relaysense" routine as follows:

    Code:
    RelaySense:  
        TimerEnable.byte0 = IOCAF 
        TimerEnable.byte1 = IOCBF 
    
    ' You have already read the flags; thus, no need for individual clear.
        IOCAF = 0
        IOCBF = 0
    
    
    @ INT_RETURN

    For freezing issue, your program may be jumping to another address.
    Thanks for your help sayzer. I think I'll use your approach instead. Much simpler. I believe that my freezing issue may be cause by a bad PIC. Ill be replacing it just to be sure. Thanks again.

  6. #6
    Join Date
    Jan 2006
    Location
    Istanbul
    Posts
    1,235

    Default Re: Interrupt issue with PIC16F18877 and DT-Ints...

    Looking at your code again, my modification seems to stop your timer flags.

    You may have the "for loop" anyway to set the flags if they are 1, but not clear them if they are zero.
    My modification clears your timer flags, and thus pauses your timer in main loop.
    "If the Earth were a single state, Istanbul would be its capital." Napoleon Bonaparte

Similar Threads

  1. What's the interrupt latency and/or overhead when using DT-Ints?
    By HenrikOlsson in forum FAQ - Frequently Asked Questions
    Replies: 10
    Last Post: - 30th August 2016, 16:43
  2. Interrupt Handler issue with PBPro
    By DonD in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 18th February 2011, 20:04
  3. DT-Ints latency and other interrupt conciderations
    By HenrikOlsson in forum mel PIC BASIC Pro
    Replies: 58
    Last Post: - 12th March 2010, 18:27
  4. DT-INTs Interrupt handler question
    By circuitpro in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 8th January 2010, 00:06
  5. RB0 interrupt and toggle issue
    By Macgman2000 in forum mel PIC BASIC Pro
    Replies: 35
    Last Post: - 5th May 2009, 19:49

Members who have read this thread : 13

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts