Menu

INT Interrupts Problems

Help
joe rocci
2009-08-06
2013-05-30
  • joe rocci

    joe rocci - 2009-08-06

    My application uses a rotary encoder on PORTB. Whenever the encoder is moved, an INT interrupt occurs, and the encoder state is read in the interrupt handler. There are also other interrupts running (timers). I'm not having problems with the timer interrupts, but I am having substantial problems with the system crashing when the encoder is turned. I finally trimmed my program down to some test code that illustrates the offending part:

    #chip 16F877A, 20
    #define LCD_IO 4
    #define LCD_RS PORTD.3
    #define LCD_Enable PORTD.2
    #define LCD_NO_RW 1
    #define LCD_DB4 PORTD.4
    #define LCD_DB5 PORTD.5
    #define LCD_DB6 PORTD.6
    #define LCD_DB7 PORTD.7
    On Interrupt ExtInt0 Call EncoderInterrupt 'enable encoder interrupts
    set option_reg.7 off 'enable PortB pullups
    dir portb.5 in 'encoder connected here; pulls low and interrupts on rotation
    dir portb.6 in 'encoder connected here; pulls low and interrupts on rotation
    set OPTION_REG.6 off 'interrupts on negative edges
    SET INTCON.RBIE OFF 'disable other PORTB change interrupts
    k=0
    locate 0,0
    Print "Program Started" 'LCD output
    wait 1 s

    'Wait in loop, counting and displaying encoder interrupts
    loop:
    cls
    locate 0,0
    Print k
    Wait 200 ms
    goto loop    

    'Encoder Interrupts
    sub EncoderInterrupt
        k = k+1
    end sub

    Even with this simple code which just increments and displays a variable , the program seems to crash regularly when the encoder is turned. Interestingly, the longer the processor is allowed to run before the encoder is turned, the less likely it is to crash. After about 10 seconds of run-time, it runs pretty reliably.

    Personally, i'm suspicious of how GCB handles the context save (why is PCLATH just cleared instead of saved and restored?), and I'm also suspicious about whether bank pointers are always pointing to the right bank. But these are just suspicions.

    Does anyone have any insight on this?

    Joe

     
    • Nobody/Anonymous

      Look at the suggestions in the other thread:

      http://sourceforge.net/forum/forum.php?thread_id=3354519&forum_id=579126

      Random crashes sounds like a missing clrf STATUS as mentioned above.

       
    • joe rocci

      joe rocci - 2009-08-10

      After a LOT of experimenting, I'm pretty sure of the cause if this problem. It seems that GCB's WAIT routines don't take kindly to this interrupt. If I disable/enable INT interrupts (SET INTCON.INTE OFF/ON) before and after any explicit WAIT instruction, as well as before/after any GCB instruction that calls internal WAIT routines, the problem seems to pretty much stop.

      This problem is especially pronounced in tight loops, like the one cited above, that use LCD functions. It seems like practically every LCD function uses internal WAIT routines.

      BTW, I'm using the latest GCB build as of this morning.

      Has anyone else seen this?

      Joe

       
    • joe rocci

      joe rocci - 2009-08-10

      After a LOT of experimenting, I'm pretty sure of the cause if this problem. It seems that GCB's WAIT routines don't take kindly to this interrupt. If I disable/enable INT interrupts (SET INTCON.INTE OFF/ON) before and after any explicit WAIT instruction, as well as before/after any GCB instruction that calls internal WAIT routines, the problem seems to pretty much stop.

      This problem is especially pronounced in tight loops, like the one cited above, that use LCD functions. It seems like practically every LCD function uses internal WAIT routines.

      BTW, I'm using the latest GCB build as of this morning.

      Has anyone else seen this?

      Joe

       
    • joe rocci

      joe rocci - 2009-08-10

      Still having problems, but noticed that in the assembly source there are some address conflicts; ie, two variables assigned to the same address. Why???

      ;Set aside memory locations for variables
      DELAYTEMP    EQU    112
      DELAYTEMP2    EQU    113
      SYSCALCTEMPX    EQU    112
      SYSDIVLOOP    EQU    116
      SYSSTRINGLENGTH    EQU    118
      SysCalcTempA    EQU    117
      SysCalcTempB    EQU    121
      SysSTATUS    EQU    127
      SysStringA    EQU    119
      SysStringA_H    EQU    120
      SysStringB    EQU    114
      SysStringB_H    EQU    115
      SysW    EQU    126
      SysWaitTemp10MS    EQU    116
      SysWaitTemp10US    EQU    117
      SysWaitTempMS    EQU    114
      SysWaitTempMS_H    EQU    115
      SYSSTRINGPARAM1    EQU    453
      ENCINT    EQU    32
      K    EQU    33
      LCDBYTE    EQU    34
      LCDCOLUMN    EQU    35
      LCDLINE    EQU    36
      LCDREADY    EQU    37
      LCDVALUE    EQU    38
      LCDVALUETEMP    EQU    39
      PRINTLEN    EQU    40
      SYSPRINTTEMP    EQU    41
      StringPointer    EQU    42
      SysIFTemp    EQU    43
      SysIntOffCount    EQU    44
      SysPRINTDATAHandler    EQU    45
      SysPRINTDATAHandler_H    EQU    46
      SysTemp1    EQU    47
      SysTemp2    EQU    48

       
    • Nobody/Anonymous

      Not sure about what could be the problem, but any interrupt will interfere in wait or any other routine that is being executed in that moment.
      Lcd timings are afected for interrupts... have you tried printing to lcd inside interrupt?

      Anyway in the code of your first post,  you are using the wrong interrupt or the wrong pin: ExtInt0 (INTCON.INTE)  interrupt is for PORTB.0, and PORTBChange (INTCON.RBIE) interrupt is for PORTB.4-7.
      You are using ExtInt0 but encoder are atached to PORTB.5 and 6.

      To know if the program is really crashing you could blink a led in the main loop as you already have a 200ms delay, just toggle led every loop cycle.

       
      • joe rocci

        joe rocci - 2009-08-10

        Good catch on my RB0 mistake, but that's not the problem. My encoder really is connected to RB0 for the INT interrupt (and RB6 for the other input); I just specified the incorrect port in the DIR spec. I fixed that error, but the program still crashes. It's not just that the interrupt affects the timing of things that use internal delay routines, it's an outright crash, or sometimes a restart.

         
    • Nobody/Anonymous

      Ok... i see one problem.
      Your code uses strings, that are located at higher Bank, then uses PCLATH, and with last update GcBasic should save PCLATH or NOT clear it, but what it does is not saving PCLATH but clearing it (have a look to asm interrupt), I think program will crash for sure.

      Then if PCLATH saving is no needed in interrupts, it should not be cleared.

       
      • joe rocci

        joe rocci - 2009-08-10

        Yes, I mentioned earlier that I still suspect the context-save. However, look at the EQU table I just posted...something's wrong there too.

         
    • Hugh Considine

      Hugh Considine - 2009-08-12

      It was the PCLATH clearing causing the problem. The string reading routines set PCLATH, then PCL, in order to read a character of a string from the program memory. If the interrupt occurred in the middle of reading a string, then PCLATH would be cleared, and when PCL was set the PIC would jump to a random location somewhere in the first 256 words of the program.

      I've uploaded yet another update, which shouldn't clear PCLATH unless it's used in the interrupt, and that should then save PCLATH properly if it is.

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.