help: TMR0 interrupts disabling PORTAchange interrupts???


Closed Thread
Results 1 to 5 of 5
  1. #1
    xnihilo's Avatar
    xnihilo Guest

    Smile help: TMR0 interrupts disabling PORTAchange interrupts???

    Hello,

    Once again, I will need some clever advise.

    I'm using interrupts triggered by changes on PORTA pins. I also need to increment a timer for a 5 minutes countdown while leaving the interrupts for PORTA and having my main loop being a @SLEEP.
    My problem is that when the countdown begins and I get back to the main loop (where I skip the @SLEEP because it would freeze my timer and use a loop with a 15Us pause instead), it does not react to PORTA interrupts anymore.
    There is an LCDOUT in my main loop and the display seems to be refreshed very quicly and at a given period of time it jumps to the right routine in my INT handler to display the countdown (it updates the counter state avery 30s).

    Below is the code, maybe if you have a look you will see what I don't see, probably an obvious error... Thanks for any help.


    Code:
    '-------------------------------------------------------------------------------
    
    a = PORTA           'clear any mismatch with latched values
    
    
    LCDOUT $fe,1,"1st A=",#a        'output ascii value of variable a: 47, %00|101|111
    PAUSE 3000
    
    'MEMO: GIE is handled by PBP !!! Don't enable GIE bit manually or expect troubles!
    'Contribution from Darrel Taylor, www.picbasic.co.uk/forum/
    
    INTCON = %00001000 			'val=8, enable porta interrupts on change, clear interrupt flags, datasheet p13
        				' flag (bit0) for portA INT must be cleared by software after int occurs
    
    'All A port pins trigger an int
    
    
    IOCA =  %111111				'enable interrupts on change individually (RA5  is used for handshaking with gun unit, default is 0v)
    IOCB = %0000
    
    
    'If enabling INT for RA3 and no WPU is used, it triggers ints!!!
    
    'Do not leave input (high impedance) pins floating
    '-------------------------------------------------------------------------------

    Code:
    '-------------------------------------------------------------------------------
    ON INTERRUPT GOTO in_sig		'when interrupt occurs on any portA pin
    '-------------------------------------------------------------------------------
    
    loop1: 				'main program is a stupid loop waiting for a int on change triggered by an ir signal on sensors or input on supply port
    'put MCU to sleep in low power mode until an int awakens it
    LCDOUT $fe,1,"crit=",#critical
    
    IF (critical == 1) THEN    'we can't use "@sleep" when using TMR0 because when at sleep, TMR0 is frozen
        PAUSEUS 15      'minimum pause length at 8MHz
        'waits for a int of TMR0 or any other int
    ELSE
    @ SLEEP        
    ENDIF
    GOTO loop1  
    
    '###############################################################################
    
    DISABLE 				'disable individual interrupts while executing the interrupt routine (do not put check interrupts calls after each instruction)
    
    
    in_sig: 
    
    a = porta
    
    IF ((critical == 1) && (INTCON.2 == 1)) THEN count_down     'if flag is set for interrupt because of TMR0 overflow




    Code:
    IF (damage >= 100) THEN 		'0-99% damage, player is alive, 100 and over means player is dead
        IF (healed == 1) THEN       'if healed already, there will be no critical condition, player dies
            dead = 1
            WRITE dead_,dead
            READ dead_,tempvar
            IF (tempvar != dead) then 
                SOUND speaker,[100,200]
                LCDOUT $fe,1,"RoR"
                PAUSE 2000
            ENDIF
        ELSE                           'if not already healed, player will enter critical condition for 5 minutes within which he can be patched and go back to 75% damage
            LCDOUT $fe,1,"CritSts"
            PAUSE 2000
            
            critical = 1    'from now on, player will be in critical condition for 5min and can be patched and still be hit
            countdown = 0   'clear the countdown timer
            TMR0 = 98       'set the offset (for 10ms duration with 1:128 at 8MHz)
            INTCON.2 = 0    'clear TMR0 overflow flag
            INTCON.5 = 1    'enable TMR0 overflow INT (GIE will be set by PBP at the end of the int handler    
            HIGH speaker    'output sound on speaker or buzzer
            'player won't send status back to gun, so if AC is enabled, gun cannot be operated
        ENDIF
    ENDIF








    Code:
    '--------------------------------------------------------------------------------------------------------------------------------------------
    count_down:
    
    'routine that increases the countdown when in critical condition
    'the update/increment of the timer happen every 10ms
    
    alert = (alert + 1)
    IF (alert == 30000) THEN     'at every 30s
        LCDOUT $fe,1,"countdown:"
        LCDOUT $fe,$C0,#countdown
        PAUSE 1000
        countdown = (countdown + 1)
        alert = 0
    ENDIF
    IF (countdown == 10) THEN   'if 30s elapsed, player dies
        LCDOUT $fe,1,"CntDwnEND"
        PAUSE 3000
        INTCON.5 = 0    'disable TMR0 overflow int
        TMR0 = 0        'stop tmr0
        INTCON.2 = 0    'reset int flag
        LOW speaker     'use a 5V piezzo buzzer, not a speaker
        GOTO died
    ENDIF
    
    GOTO finish










    Code:
    finish:
    
    a = porta               'mirror porta and clear the mismatch, refresh latches
    INTCON.0 = 0
    
    resume                  'end int routine
    
    enable                  'REENABLING GIE, PBP lame instruction
    
    
    END                     'end of program


    I read my code again and again and the following line just at the begining of my interrupts handler may cause a problem:
    Code:
    IF ((critical == 1) && (INTCON.2 == 1)) THEN count_down     'if flag is set for interrupt because of TMR0 overflow
    because when entering the interrupts handler, if the "critical" called variable is set and the flag for TMR0 overflow interrupt is set (what will probably be the case if I'm stupid enough not to clear it before leaving the int handler routine) then it will jump to the code that handles the interrupt that occured because of the TMR0 overflow, and I guess that if an int occurs because of a change on PORTA, it will be kinda ignored because the conditions are met for TMR0 overflow interrupt before it is even checked for PORTA change ??? ...

    I should probably use:
    Code:
    IF ((INTCON.0 == 0) && (critical == 1) && (INTCON.2 == 1)) THEN count_down     'if flag is set for interrupt because of TMR0 overflow
    instead and check that I reset the flag for TMR0 overflow interrupt everytime this INT occurs
    Code:
    count_down:
    
    'routine that increases the countdown when in critical condition
    'the update/increment of the timer happen every 10ms
    
    INTCON.2 = 0    'reset int flag <<<<<<--- Reset the flag for TMR0 overflow before leaving the INT handler
    
    alert = (alert + 1)
    IF (alert == 30000) THEN     'at every 30s
        LCDOUT $fe,1,"countdown:"
        LCDOUT $fe,$C0,#countdown
        PAUSE 1000
        countdown = (countdown + 1)
        alert = 0
    ENDIF
    Last edited by xnihilo; - 18th August 2008 at 12:17.

  2. #2
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    ENABLE
    doesn't reenable GIE. It's a compiler directive that tells PBP to start checking again for interrupts.
    As far as I know, there's only 2 ways to reenable GIE...RESUME, in PBP, (RETFIE in assembly), which sets it automatically upon execution, and manually setting the bit.
    Last edited by skimask; - 18th August 2008 at 18:11.

  3. #3
    xnihilo's Avatar
    xnihilo Guest


    Did you find this post helpful? Yes | No

    Smile Problem is solved

    Reseting the TMR0 ovf flag and the TMR0 preload value before leaving handler and checking what int flag are set upon entering the int handler did the trick.
    More funny, the int period is now all right (about 10ms)... What is strange is that I did not change a lot of things besides setting the preload for TMR0 before leaving the int handler...

    Skimask: yes, the code comments were a bit wrong I agree.
    RESUME, ENABLE. I changed the comments in my program
    As you may have noticed I'm not very strict when I write my code and my comments. I should be more cautious because other people may/will read and use the code...
    My brother always tells me that my code is a mess... He's right

    This forum is such a great place.
    I have to reference it in my code so people reading it will know that if I could finish my projects it is because many people on this forum guided me and even sometimes gave me the answers.

    Cool forum!

  4. #4
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by xnihilo View Post
    Reseting the TMR0 ovf flag and the TMR0 preload value before leaving handler and checking what int flag are set upon entering the int handler did the trick.
    More funny, the int period is now all right (about 10ms)... What is strange is that I did not change a lot of things besides setting the preload for TMR0 before leaving the int handler...

    Skimask: yes, the code comments were a bit wrong I agree.
    RESUME, ENABLE. I changed the comments in my program
    As you may have noticed I'm not very strict when I write my code and my comments. I should be more cautious because other people may/will read and use the code...
    My brother always tells me that my code is a mess... He's right

    This forum is such a great place.
    I have to reference it in my code so people reading it will know that if I could finish my projects it is because many people on this forum guided me and even sometimes gave me the answers.

    Cool forum!
    More Importantly, You will come back to your code, long after you have forgotten the details
    and will have to wade through it and try to remember . . . whereas, properly commented code will be easy, sensible, and readable. Spend a little time now or a lot later.
    Happy you got it working! Zot! Tag, you're it!
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  5. #5
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by xnihilo View Post
    Reseting the TMR0 ovf flag and the TMR0 preload value before leaving handler and checking what int flag are set upon entering the int handler did the trick.
    More funny, the int period is now all right (about 10ms)... What is strange is that I did not change a lot of things besides setting the preload for TMR0 before leaving the int handler...
    I guess my main point about ENABLE was that if you ENABLE'd while still processing the interrupt, it'll 'interrupt' right there and you could get stuck in that same loop until you just happen to get lucky and can get out.

Similar Threads

  1. COUNT is not counting again
    By jellis00 in forum mel PIC BASIC Pro
    Replies: 33
    Last Post: - 19th June 2009, 04:52
  2. 18F2420, instant interrupts, and TMR0
    By dhickman in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 11th March 2009, 18:33
  3. 18F2620 tmr0 and interrupts
    By astouffer in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 8th March 2009, 00:56
  4. using TMR0 as a counter..
    By sirvo in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 28th July 2007, 02:56
  5. Strange behaviour from PIC16F877 on TMR0
    By mikebar in forum mel PIC BASIC Pro
    Replies: 18
    Last Post: - 19th August 2006, 01:31

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