Count down timer with interrupt/jump ?

Closed Thread
Results 1 to 4 of 4
  1. #1
    Join Date
    Feb 2006
    Brussels, Belgium

    Default Count down timer with interrupt/jump ?


    I've been searching for an answer to this with no success so apologies if I've just been looking in the wrong place or I'm stupid

    I'm building a control circuit / program for a photo trap which needs to do the following:

    1) Count down from 30secs to 0sec while displaying the remaining seconds on a serial LCD. No problems with that bit !
    2) If at any time during the 30sec "window" an input changes state, I want to immediately jump to a subroutine with the shortest possible delay.

    As I understand it, interrupts only work at the end of a command so if I pause 1sec the interrupt would only execute at the end of the pause ? Same as if I paused 1sec then just read an input pin.

    I could go round and around an input read loop with an if...then...goto for enough times to add up to 1sec and then decrease the second counter, refresh the lcd, then round'n'round for another sec. In that case how long do PBP instructions take to execute ? I know it's 4clock cycles per command in assembly language but how many commands per PBP instruction so I can calculate times ?

    I can't help but feel that there might be a really simple/elegant way of doing this.

    Thanks in advance for any tips,


  2. #2
    Join Date
    Jun 2007

    Did you find this post helpful? Yes | No



    have you looked Darrel's instant interrupt : elapsed timer ?
    I think you can modify the sample code to make it work as you suggest

    I have tried this instant interrupt : elapsed timer for similar application and it works fine


  3. #3
    Join Date
    Jul 2003

    Did you find this post helpful? Yes | No


    As I understand it, interrupts only work at the end of a command so if I pause 1sec the interrupt would only execute at the end of the pause ? Same as if I paused 1sec then just read an input pin.
    Yes, but only if you're using ON INTERRUPT, which is really not the way to go for something
    like this application. Assembler interrupts would work, but I think this can be done with a lot
    less hassle.

    Let's get creative on this one, and not use interrupts. We'll just monitor the Timer1 overflow
    flag. With Timer1 running in the background you have a multi-tasking environment that can
    remove a ton of firmware overhead.
       DEFINE OSC 4
       ' Define LAB-X1 LCD registers and bits
       DEFINE  LCD_DREG        PORTD
       DEFINE  LCD_DBIT        4
       DEFINE  LCD_RSBIT       0
       DEFINE  LCD_EREG        PORTE
       DEFINE  LCD_EBIT        1
       DEFINE  LCD_DATAUS      50
       SYMBOL PROBE = PORTA.0 ' O-scope probe for timing tests
       SEC_COUNT VAR BYTE     ' seconds counter
       OLD_COUNT VAR BYTE     ' copy of count
       PORT_VAL  VAR BYTE     ' holds value read from input port
       O_FLOWS   VAR BYTE     ' holds the number of timer1 overflows
       T1LO CON $B0           ' timer1 reload values
       T1HI CON $3C
       PORTB = 0              ' RB3 to RB0 = 0
       TRISB = %11110000      ' RB7 to RB4 = inputs, RB3 to RB0 = outputs
       INTCON  = 0            ' interrupts disabled (we're just watching tmr1 int flag)
       OPTION_REG = 0         ' portb pull-ups on for RB7 to RB4
       T1CON = %00100000      ' 1:4 prescale (4uS per tick), timer1 off
       TMR1H = T1HI           ' $3CB0=15,536. 65,536-15,536 = 50,000
       TMR1L = T1LO           ' 50,000 ticks * 4uS = 0.2 seconds. 1 second / 0.2 = 5
                              ' every 5 timer1 overflows = 1 second
       ADCON1 = 7             ' Set PORTA and PORTE to digital
       LOW PORTE.2            ' LCD R/W line low (W)
       PAUSE 1000             ' Wait for LCD to start up
       LCDOUT $FE,1           ' Clear LCD
       SEC_COUNT=30           ' load for 30 to 0 countdown
       OLD_COUNT=1            ' mismatch for display (see below)
       O_FLOWS=0              ' clear overflow count
       PIR1.0=0               ' clear timer1 overflow flag
       T1CON.0=1              ' start timer1
       TOGGLE PROBE           ' 77uS from start to return
       ' Note: Timer1 overflows every 0.2 seconds, so we have time to execute
       ' a whopping 200,000 single-cycle instructions before this section is
       ' executed
       IF PIR1.0 THEN           ' if timer1 overflow then
          O_FLOWS=O_FLOWS+1     ' inc oveflow counter
          IF O_FLOWS=5 THEN     ' if 1 second elapsed then
             SEC_COUNT=SEC_COUNT-1 ' decrement seconds count
             O_FLOWS=0          ' reset overflow counter
          PIR1.0=0              ' clear timer1 overflow flag
          T1CON.0 = 0           ' stop timer1
          TMR1L = TMR1L + T1LO  ' add in low byte
          IF TMR1L < T1LO THEN  TMR1H = TMR1H + 1  ' if low byte overflow, increment high byte
          TMR1H = TMR1H + T1HI  ' add in high byte
          T1CON.0=1             ' re-start timer1
          IF SEC_COUNT=255 THEN
             SEC_COUNT=30       ' reset to 30 after 0-1 underflow
             OLD_COUNT=1        ' make sure new value is displayed
       ' display is updated only when count has changed, so LCDOUT gets executed
       ' only once each second
          LCDOUT $FE,1,"Count = ",DEC SEC_COUNT
          OLD_COUNT=SEC_COUNT  ' match last displayed count for next pass
       ' portb gets read ~every 77uS
       PORT_VAL = (PORTB >> 4) ' read portb
       IF PORT_VAL !=15 THEN ProcessInput ' do something if switch pressed
       GOTO Test
       ' print switch inputs on 2nd line of LCD when RB7, 6, 5 or 4 are at ground
       LCDOUT $FE,$C0,IBIN4 PORT_VAL ' display input values
       GOTO Test
    This is pretty heavily commented, but if you have questions, let me know. I didn't have a
    serial LCD handy, but this should be pretty easy to modify for your own hardware.

    Making entry into the time-consuming routines conditional, leaves a ton of time to monitor
    your switch inputs, and it's easy to keep everything up to date without using interrupts.

    So you have a boat-load of time to goof-off doing other stuff between the count,
    display updates, and timer reloads.

    Instead of wasting valuable time with a PAUSE 1000, you're running around the entire loop
    from start to return in around 77uS, and have plenty of time to burn for other stuff.

    If you have an O-scope, try placing the TOGGLE PROBE at different locations to see how fast
    everything happens.
    Last edited by Bruce; - 24th August 2007 at 01:19.

    tech at

  4. #4
    Join Date
    Feb 2006
    Brussels, Belgium

    Did you find this post helpful? Yes | No


    Thanks for the answers, much appreciated. Now, if I can just get my company to stop sending me on ridiculous business trips I'll make the leap from virtual programming in Seat 21A of flight xyz and get home and test them !!


Similar Threads

  1. Elapsed Timer Demo
    By Darrel Taylor in forum Code Examples
    Replies: 111
    Last Post: - 29th October 2012, 17:39
  2. COUNT is not counting again
    By jellis00 in forum mel PIC BASIC Pro
    Replies: 33
    Last Post: - 19th June 2009, 04:52
  3. Timer interrupt frequency
    By Samoele in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 17th January 2009, 23:49
  4. Alarms with Mel's "Olympic Timer" based timer - how to?
    By flotulopex in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 20th June 2007, 22:09
  5. timer interupt help 16f73
    By EDWARD in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 3rd July 2005, 08:41

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