Interruptus Frustratus


Closed Thread
Results 1 to 17 of 17

Hybrid View

  1. #1
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323

    Default Interruptus Frustratus

    I'm having a hard time again...

    My interrupts seem to be taking over, and my main loop never gets executed.

    The project I'm working on controls a few simple outputs based on some user input , some machine inputs, and the real time from a DS1302.

    The user input comes from the "touch sensors" available in the 16F727. The time (minutes and seconds only) and other numeric info are displayed on a 4 digit, 7-segment LED display.

    The touch sensors use Interrupts based on TMR1 and TMR0.

    I had much of my program working until I added the touch sensor routine, then everything went to hell....

    I've trimmed my code back to just the touch sensor and RTC code trying to get it to work. The problem is that the interrupts seem to "take over the show" and my main loop never gets executed.

    This bit of test code should display the "ones of minutes" and the tens and ones of seconds on a LED display.

    When a sensor button is touched, the number of the button pressed should be momentarily displayed on the 4th digit of the display.

    The problem is that while the touch sensors work fine and the appropriate number is displayed when touched, the time is *not* displayed because the main loop is never executed. If I disable the interrupts so that the touch sensors don't work, then the main loop is executed and the time is displayed just fine.

    Why does the interrupt routine highjack the show and keep the main loop from executing?

    Here's the bit of test code that I'm working with... any suggestions would be a appreciated.
    It's a little too big, so I'll split it into 2 posts....

    Code:
    '****************************************************************
    
    Include "MODEDEFS.BAS"   ' Include Shiftin/out modes
    INCLUDE "DT_INTS-14.bas"  ' Base Interrupt System
    INCLUDE "ReEnterPBP.bas"  ' Include if using PBP interrupts
    DEFINE LCD_DREG PORTD    ' Set LCD Data port
    DEFINE LCD_DBIT 4        ' Set starting Data bit (0 or 4) if 4-bit bus
    DEFINE LCD_RSREG PORTC   ' Set LCD Register Select port
    DEFINE LCD_RSBIT 5       ' Set LCD Register Select bit
    DEFINE LCD_EREG PORTC    ' Set LCD Enable port                                                   
    DEFINE LCD_EBIT 6        ' Set LCD Enable bit
    DEFINE LCD_BITS 4        ' Set LCD bus size (4 or 8 bits)
    DEFINE ADC_BITS 8        ' Set number of bits in ADC result
    DEFINE ADC_CLOCK 3       ' Set clock source for ADC (rc = 3)
    DEFINE ADC_SAMPLEUS 100  ' Set ADC sampling time in microseconds 
    define I2C_SCLOUT 1      ' Set I2C Clock to drive high instead of needing pullup
    DEFINE CCP2_REG PORTC    'Hpwm2 port
    DEFINE CCP2_BIT 1        'Hpwm2 bit
    DEFINE OSC 16            '16 MHz
    
    OSCCON = %00110000       'set OSC to 16 mHz.
    
    @  __config _CONFIG1, _DEBUG_OFF & _PLL_EN & _BORV_2_5 & _BOR_ON & _CP_OFF & _MCLRE_OFF & _PWRT_EN & _WDT_ON & _INTOSCIO
    @  __config _CONFIG2, _VCAP_RA6
    
    
    TRISA= %00000000     'Set 'em all to outputs 
    TRISB= %11111111   	 'all input
    TRISC= %00011000     'Set portC all outputs except C.3 and C.4
    TRISD= %00000000     'Set portD all outputs
    TRISE= %00000000     'Set portE all outputs
        
    ANSELA= %00000000	 ' Set all pins to digital 
    ANSELB= %11111111    ' all analog
    ANSELD= %00000000    ' Set all pins to digital 
    ANSELE= %00000000    ' Set all pins to digital
    
    CPSCON0 = %10001101  'Cap sense on, high range oscillator
    
    '---------VARIABLES-----------------------------------
    
    'LED Driver (CAT4016) Variables-----------------------
    LEDData var     byte    
    numeral var     byte
    LEDCounter  var byte
    digit1  var     byte : digit1=0
    digit2  var     byte : digit2=0
    digit3  var     byte : digit3=0
    digit4  var     byte : digit4=0
    
    
    'DS1302 RTC Variables-----------------------
    rtcyear  var     byte   
    rtcday   var     byte   
    rtcmonth var     byte   
    rtcdate  var     byte   
    rtchr    var     byte   
    rtcmin   var     byte   
    rtcsec   var     byte
    rtccontrol  var  byte
    mathtemp    var  Byte   'For doing BCD to Decimal conversion
    
    
    'Touch sensor related Variables---------------------- 
    index        var    byte : index=0  'for the CSM buttons
    timercount   var    word[6] : timercount = 0 ' raw count from TMR1, for each channel
    timerave     var    word[6] : timerave = 0 ' long term average of timercount, for each channel
    AvgCount     var    byte : AvgCount = 32 'number of samples to average
    delay        var    word : delay = 0  ' to delay startup until the timers have stabilized.
    
    
    '---------I/O PINS-----------------------------------   
    'Alias pins - DS1302---------------------------------
    RST      var    PORTE.2  '1302 CS
    IO       var    PORTE.1  '1302 I/O
    SCLK     var    PORTE.0  '1302 Clock
    
    'Alias pins - EEPROM---------------------------------
    SDA      var    PORTC.4  'EEPROM data
    SCL      var    PORTC.3  'EEPROM Clock
    
    'Alias pins - LED display----------------------------
    S_IN     var    PORTA.3  'CAT4016 data
    LEDCLK   var    PORTA.2  'CAt4016 clock
    BLANK    var    PORTC.1  'CAT4016 blanking line
    LATCH    VAR    PORTA.0  'Cat4016 Latch
    
    'Initialize variables-------------------------------- 
    hpwm 2,100,1000  'set LED brightness
    timerave = 2000  'preset the timer average to a "close" value
    '-----------------------------------------------------------------
    'Set initial time (this can be removed in final version)
    'rtcyear = $09   'Set Year
    'rtcday = $1    'Set Day
    'rtcmonth = $1  'Set Month
    'rtcdate = $1   'Set Date of month
    'rtchr = $1     'Set Hour
    'rtcmin = $1    'Set Minutes
    'rtcsec = $1    'Set Seconds
    'Gosub settime   ' DO IT! - Set the time
    
     '--------------------------------------------------------------------------------
    'initialize the DS1302 and set the trickle charge rate
    Low SCLK
    low rst        ' Reset RTC
    high rst       ' RTC Ready for transfer        
    Shiftout IO, SCLK, LSBFIRST, [$8e, 0]  ' Enable write
    low rst        
    high rst
    Shiftout IO, SCLK, LSBFIRST, [$90, %10101011]  ' Set charger on and to "2 diodes, 8Kohm"              
    Low RST         ' Reset RTC
    pause 5
    
    ' -----Grab the time out of the RTC and display it--------------------------
    gosub gettime
    gosub sortdigits
    pause 1000 
    
    '-----Set up Interrrupts--------------------------------------------
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR1GATE_INT,  _CheckCount,   PBP,  yes
         endm    
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
    
    @ INT_ENABLE  TMR1GATE_INT     ; enable Timer1 gate interrupt
    
    
    '----- Timer Setup------------------------------------------------
    OPTION_REG = %11010110    'setup source and prescaler for TMR0
    INTCON.2 = 0; // clear TMR0 interrupt flag
    INTCON.5 = 1; // enable TMR0 interrupt
    T1CON = %11000101 'Timer clock source=CAPOSC, prescale=1:1, dedicated OSC disabled, no external clock synchronize, timer on
    T1GCON = %11100001 'Timer1 gate init/ Toggle Mode
    PIR1.7 = 0   'Clear Gate Interrupt Flag
    
    
    '----------JUST GET IT GOING-------------------
    GOTO Main  'skip the subroutines and get on with it.
    Finish below....

  2. #2
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323


    Did you find this post helpful? Yes | No

    Default

    ....Continued from above.

    Code:
    '---[TMR1 Gate - interrupt handler]--------------------------------------------------
    disable   
    CheckCount:
            T1CON.0 = 0   'stop timer1
            timercount[index] = TMR1L + TMR1H << 8   'stuff the contents of the timer register into a word    
            TMR1L = 0     'reset counter to 0...
            TMR1H = 0     'upper 1/2 too
    
            If delay < 1001 then    'delay user access to the buttons until the count "average" has stabilized.
                delay = delay +1        
            endif    
        
            If timercount[index] > timerave[index] +70 then  'Help provide a speedy recovery for released buttons
                timerave[index] = timercount[index]
            endif
                 
            if (timercount[index] - timerave[index]) < AvgCount Then Close
            timerave[index] = timerave[index] - (timerave[index]/AvgCount)    'average the count so you have a reference to compare....
            timerave[index] = timerave[index] + (timercount[index]/AvgCount)  '...with timercount
            Goto checkscore
        
            Close:
                timerave[index] = timerave[index] - (timerave[index]/(AvgCount/16))   
                timerave[index] = timerave[index] + (timercount[index]/(AvgCount/16))    
        
            Checkscore:       'Determine if a button is pressed (count is less than average)        
                If timerave[index] - (timerave[index] /50) > timercount[index] and (delay > 1000) then 
                   gosub ServiceHardw 'Signal that a button is pressed. 
                endif
            
            If index < 5 then     'Increment to the next touch sensor input
               index = index +1
            else
                index = 0
            Endif
            CPSCON1 = index
         
            TMR0 = 0       'reset timer 0              
            T1CON.0 = 1  'restart timer1
     
    @ INT_RETURN
    enable
    
    
    '----------SUBROUTINES--------------------------------
    'Subroutine for Button 1-----------------------------
    Butt1:
            Digit4 = 1
            gosub sortdigits
            Pause 500
            digit4 = 0
            gosub sortdigits
    Return
    
    
    'Subroutine for Button 2-----------------------------
    Butt2:
            Digit4 = 2
            gosub sortdigits
            Pause 500
            digit4 = 0
            gosub sortdigits
    Return
    
    
    'Subroutine for Button 3-----------------------------
    Butt3:
            Digit4 = 3
            gosub sortdigits
            Pause 500
            digit4 = 0
            gosub sortdigits
    Return
    
    
    'Subroutine for Button 4-----------------------------
    Butt4:
            Digit4 = 4
            gosub sortdigits
            Pause 500
            digit4 = 0
            gosub sortdigits
    
    Return
    
    
    'Subroutine for Button 5-----------------------------
    Butt5:
            Digit4 = 5
            gosub sortdigits
            Pause 500
            digit4 = 0
            gosub sortdigits
    Return
    
    
    'Subroutine for Button 6-----------------------------
    Butt6:
            Digit4 = 6
            gosub sortdigits
            Pause 500
            digit4 = 0
            gosub sortdigits
    Return
    
    
    'Subroutine to display numbers on 7-segment display-----------
    display:
              shiftout S_in, LEDCLK, 1, [LEDData]
    return
    
    
    'Subroutine to map numbers to the correct LED segments------
    getpattern:  
           lookup numeral,[$EE,$28,$CD,$6D,$2B,$67,$E7,$2C,$EF,$6F], LEDData 'MSBFirst / Right side up digits
    return
    
    
    'Subroutine to read time from RTC--------------------              
    gettime:  
            RST = 1         ' Ready for transfer
            ' Read all 8 RTC registers in burst mode
            Shiftout IO, SCLK, LSBFIRST, [$bf]      
            Shiftin IO, SCLK, LSBPRE, [rtcsec, rtcmin, rtchr, rtcdate, rtcmonth, rtcday, rtcyear, rtccontrol]
            RST = 0         ' Reset RTC 
            mathtemp =(rtcsec>>4)*10+(rtcsec & $0F)  'convert BCD seconds into Decimal seconds 
            digit1 = mathtemp dig 0   'digit 1 = ones of seconds
            digit2 = mathtemp dig 1   'digit 2 = tens of seconds     
            mathtemp =(rtcmin>>4)*10+(rtcmin & $0F)  'convert BCD minutes into Decimal minutess 
            digit3 = mathtemp dig 0   'digit 3 = ones of minutes
    '        digit4 = mathtemp dig 1
            gosub sortdigits              
    Return
    
    
    'Subroutine to sort out the buttons-------------------
    ServiceHardw:
            branchl index, [Butt1,Butt2,Butt3,Butt4,Butt5,Butt6]
    return
    
    
    ' Subroutine to write time to RTC------------------------        
    settime: 
            RST = 1         ' Ready for transfer
            Shiftout IO, SCLK, LSBFIRST, [$8e, 0]  ' Enable write
            RST = 0         ' Reset RTC
            RST = 1         ' Ready for transfer
                ' Write all 8 RTC registers in burst mode
            Shiftout IO, SCLK, LSBFIRST, [$be, rtcsec, rtcmin, rtchr, rtcdate, rtcmonth, rtcday, rtcyear, 0]
            rst = 0        
    Return 
    
    
    'Subroutine to lookup numbers and put them in the correct LED digit-----------
    sortdigits:  
            numeral = digit4   
            gosub getpattern
            swap LEDData.0, LEDdata.4   'Swap "DP" and "G" segments on upsidedown digits
            gosub display    
            numeral = digit3
            gosub getpattern
            LEDData.4 = 1       'Turn on lower DP in colon
            gosub display    
            numeral = digit2
            gosub getpattern
            swap LEDData.0, LEDdata.4   'Swap "DP" and "G" segments on upsidedown digits
            LEDData.0 = 1      'Turn on upper DP in colon
            gosub display    
            numeral = digit1
            gosub getpattern
            gosub display
           High Latch
           pause 1
           low Latch
    return
    
          
    'Main loop - Gets the time and displays it----------------------------------        
    main:   
            gosub gettime
            gosub sortdigits
            pause 100              
            Goto main   ' repeat until nauseated...
    
    End

    Thanks!

    Steve

  3. #3
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,615


    Did you find this post helpful? Yes | No

    Talking

    Hi,

    I didn't know DT interrupts were using Enable and Disable Commands ...

    Alain

    Coïtus interruptus frustrans est ...
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  4. #4
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Code:
    INTCON.5 = 1; // enable TMR0 interrupt
    There's no handler for the TMR0 interrupt.

    So the flag for that interrupt never gets cleared.
    It then continuously enters/exits the interrupt processor, never to see the light of day again.

    Added: And Alain is correct. disable/enable has no effect on DT_INTS.
    <br>
    Last edited by Darrel Taylor; - 8th April 2009 at 07:43. Reason: Added:
    DT

  5. #5
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    947


    Did you find this post helpful? Yes | No

    Default

    Steve

    Code:
         
    Checkscore:       'Determine if a button is pressed (count is less than average)        
                If timerave[index] - (timerave[index] /50) > timercount[index] and (delay > 1000) then 
                   gosub ServiceHardw 'Signal that a button is pressed. 
                endif
    Your call to gosub ServiceHardw is the culprit. It nests other subroutines. This is what may be consuming the time. I can recommend you replace the call to gosub ServiceHardw with a bit variable getting set. You then check the bit variable in your mainline code to decide if you need to serviceHardw. It will definitely yield results.

    Code:
         Checkscore:       'Determine if a button is pressed (count is less than average)        
                If timerave[index] - (timerave[index] /50) > timercount[index] and (delay > 1000) then 
                   ServiceHw=1
                endif
    In your main, put this
    Code:
    ServiceHw var  bit        ' declarations section
    
                If ServiceHw then gosub ServiceHw

    Jerson

  6. #6
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323


    Did you find this post helpful? Yes | No

    Default

    Alain, Darrel, Jerson, thanks very much! You guys are great!

    Sooo... if "Disable" & "Enable" don't work with DT_INT, what keeps interrupts from occurring during the interrupt handler? I assume that DT_INT must "protect" it's own handler?

    Is there a way for me to disable the interrupts during certain subroutines?
    When I get the rest of this put together there will be several places where I need to kill the interrupts to perform time sensitive tasks. Is that possible using DT_INT ?
    Do I simply turn the interrupts on and off with the GIE bit when I want to? (INTCON.7 = 0) ?

    Darrel, thanks for catching the TMR0 interrupt with no handler. I don't know why I keep doing that. I had to change the Timer resource from TMR2 to TMR0 and I enabled it's interrupt unnecessarily. Thanks! Turning TMR0 interrupt off helped but didn't completely cure the problem.

    Jerson, please print yourself a pretty gold star and pin it to your shirt for the day!
    The call to gosub "ServiceHardw" was indeed the big culprit. I assume that I just had so much stuff inside my interrupt handler that I ran out of time to do anything else before the next interrupt ?
    I set a bit to tell when a button is pressed and check it in my main code as you suggested, and it works MUCH better now!

    There's clearly a few bugs still to work out before I start adding the rest of my code back in, but it's looking pretty hopeful now.

    Thanks again to all of you. What a great resource!


    Steve

  7. #7
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898


    Did you find this post helpful? Yes | No

    Default

    Enable/Disable are for PBP ON INTERRUPT GOTO

    For DT-INTS you have
    @ INT_ENABLE IntSource
    and
    @ INT_DISABLE IntSource

    You could disable all interrupt by clearing INTCON GIE too. Used with care this could work.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  8. #8
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by mister_e View Post
    Enable/Disable are for PBP ON INTERRUPT GOTO

    For DT-INTS you have
    @ INT_ENABLE IntSource
    and
    @ INT_DISABLE IntSource

    You could disable all interrupt by clearing INTCON GIE too. Used with care this could work.
    AHA! Thanks Steve!

    When using @ INT_DISABLE to protect a subroutine, does it also protect nested gosubs, or do I need to disable interrupts in each nested subroutine to protect them all from interrupt?

    Thanks!

  9. #9
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    947


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Byte_Butcher View Post
    Alain, Darrel, Jerson, thanks very much! You guys are great!
    ...snip...
    Jerson, please print yourself a pretty gold star and pin it to your shirt for the day!
    ...snip...
    Thanks again to all of you. What a great resource!
    Steve
    Wow, I am thrilled for that. Thank you. I'm sure many more will learn from your problem as they browse this resource. I myself have used this website to learn from DT, Steve (bow) many times before I began to return the favour. It's my hope that you will be able to soon. :thumbs up:

Members who have read this thread : 1

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