Clock using Instant Interrupts

+ Reply to Thread
Results 1 to 4 of 4
  1. #1
    Join Date
    Feb 2009

    Default Clock using Instant Interrupts

    I am new to PIC programming and had a question regarding using Interrupts. I had tried using the "Standard" way, but I stumbled upon Darrel's instant interrupts and they seemed much easier and more reliable, so I gave them a try. My goal is to make a programmable clock using a PIC16F627A using a Sony remote and TSOP receiver. I have made simple IR comms work and display, along with a clock, but my issue is that I was having trouble interrupting the clock function when I press my program key on the remote. It just wanted to keep timing and ignore my command, so I gave instant interrupts a try.

    My goal in the end is to have my main routine looking for IR pulses, and the interrupt generating the time, but for now I just wanted to make sure I am using the interrupt right, so I am trying to use the interrupt to generate 1/10th second counts. Here is my code.

    '*  Name    : UNTITLED.BAS                                      *
    '*  Author  : [select VIEW...EDITOR OPTIONS]                    *
    '*  Notice  : Copyright (c) 2009 [select VIEW...EDITOR OPTIONS] *
    '*          : All Rights Reserved                               *
    '*  Date    : 2/11/2009                                         *
    '*  Version : 1.0                                               *
    '*  Notes   :                                                   *
    '*          :                                                   *
    ; Initialize your hardware first
    INCLUDE "DT_INTS-14.bas"     ; Base Interrupt System
    INCLUDE "ReEnterPBP.bas"     ; Include if using PBP interrupts
    Include "modedefs.bas"
    Define OSC
    DEFINE LOADER_USED 1     ' Using boot-loader for initial prototype
    define DEBUG_MODE 0 ' 1 = inverted, 0 = true 
    Second    var     byte
    Minute2   VAR     BYTE    ' Ones column for minutes
    Minute1   VAR     BYTE    ' Tens column for minutes
    Hour2     VAR     BYTE    ' Ones column for hours
    Hour1     VAR     BYTE    ' Tens column for hours
    AMPM      VAR     BIT     ' 1 when PM
    Counts    VAR     BYTE    ' Counts for timer
    Second = 0
    Minute1 = 0
    Minute2 = 0
    Hour1 = 1
    Hour2 = 2
    AMPM = 0
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR1_INT,   ReloadTMR1,   ASM,  no    ; MUST be first
            INT_Handler   TMR1_INT,   _T1handler,   PBP,  yes
        INT_CREATE               ; Creates the interrupt processor
    ;--- Change these to match the desired interrupt frequency -------------------
    ;--- See for more Info.
    @Freq       = 10                  ; Frequency of Interrupts in Hz
    @Prescaler  = 2                   ; Timers Prescaler setting
    T1CON = $10                       ; $30 = Prescaler 1:8, TMR1 OFF
    ; $00=1:1, $10=1:2, $20=1:4, $30=1:8 --  Must match @Prescaler value
    @ INT_ENABLE  TMR1_INT            ; enable Timer 1 interrupts
    GOSUB StartTimer                  ; Start the Timer
    IF counts = 10 then  
    Second = Second + 1      'Calculate time and change values
    If Second = 60 then 
       Minute2 = Minute2 +1
       Second = 0
         IF Minute2 = 10 THEN
         Minute1 = Minute1 + 1
         Minute2 = 0
            IF Minute1 = 6 then
            Hour2 = Hour2 + 1
            Minute1 = 0
               IF Hour2 = 10 THEN
               Hour1 = 1 
               Hour2 = 0
    IF Hour1 = 1 AND HOUR2 = 3 THEN      'Roll clock over to 1 from 12
       Hour1 = 0
       Hour2 = 1
       IF AMPM = 0 THEN                  'Establish AM and PM times
          AMPM = 1
         IF AMPM = 1 THEN
            AMPM = 0
    If Hour1 = 0 then                    'If hour 1 is 0 then do not display it
       Hour1 = 20                        'SLED-C4 will not display anything if the
    Endif                                'value is above 10
    DEBUG "D", Hour1,Hour2,Minute1,Minute2 ' Display time
    DEBUG "P",12,"~"                       ' Display Colon
    GOTO Main
    Counts = Counts + 1  ;   Increase the 1/10th sec count
    ;---[TMR1 reload - interrupt handler]-----------------------------------------
    ASM                               ; Calculate Timer Reload Constant
    ReloadInst  = 8                   ; # of Intructions used to reload timer
      if ((Prescaler == 1)||(Prescaler == 2)||(Prescaler == 4)||(Prescaler == 8))
    MaxCount    = 65536 + (ReloadInst / Prescaler)
    TimerReload = MaxCount - (OSC*1000000/4/Prescaler/Freq)
        if ((TimerReload < 0) || (TimerReload > (65535-ReloadInst)))
            error Invalid Timer Values - check "OSC", "Freq" and "Prescaler"
          error Invalid Prescaler
    @Timer1 = TMR1L                   ; map timer registers to a word variable
    Timer1       VAR WORD EXT
    TimerReload  CON EXT              ; Get the External Constant
    TMR1ON       VAR T1CON.0          ; Alias the Timers ON/OFF bit
    ;---Reload Timer1------
        MOVE?CT  0, T1CON, TMR1ON     ;  1     stop timer
        MOVLW    LOW(TimerReload)     ;  1     Add TimerReload to the 
        ADDWF    TMR1L,F              ;  1     value in Timer1
        BTFSC    STATUS,C             ;  1/2
        INCF     TMR1H,F              ;  1
        MOVLW    HIGH(TimerReload)    ;  1
        ADDWF    TMR1H,F              ;  1
        MOVE?CT  1, T1CON, TMR1ON     ;  1     start timer
    ;---Start/Stop controls -----
        Timer1  = TimerReload         ; Load Timer
        TMR1ON = 1                    ; start timer
        TMR1ON = 0                    ; stop timer
    Basically the code sits at the default 12:00 and never moves. Judging from this, it would seem that it gets to the display time DEBUG statement, or I would have a display of 8888, but I'm not really sure what happens after that. I am assuming the PIC is fast enough to get through the clock routine when Counts = 10 before it is interrupted, but again, not sure where I am hanging up.

    Any suggestions from some of the PIC veterans out there?

    Another quick question. I don't think I saw how to disable instant interrupts from occuring when I get to a point that I dont want them?

  2. #2
    Join Date
    Jul 2003
    Colorado Springs


    Hi PICpocket ... good name

    I think the biggest problem is the IF block ...
    IF counts = 10 then
        ; counts time here
        GOTO MAIN
    When counts gets to 10, it adds to the time, then bypasses the GOTO Main and falls into the interrupt handler which has nowhere to return to.

    Also, counts wasn't initialized to 0, so it may have to go all the way to 255 then rollover to 0, before making it to ten. Then once it gets to 10, you'll need to set counts to 0, or it will count all the way up again.

    The timekeeping part would be better inside the interrupt handler. Depending on what else you add to the Main loop, it could lose time.

    Any Software timed commands like DEBUG will be disturbed by interrupts.
    To send data via RS232, you should use the USART with HSEROUT.
    Or, you can disable the interrupts when sending data, but it can mess up the time if your not careful.

    To disable the interrupt ...
    To enable the int ...

    Which brings us to the IR signal (code not included).
    Trying to read that using PAUSEs or similar methods won't work reliably because the timing will be disrupted by the interrupts. You can probably use another timer for the IR reception.


  3. #3
    Join Date
    Jul 2003


    If you use Timer2 for your clock it leaves Timer1 free to be used with hardware capture. Then you can use capture to read your IR signal.

    Here's an example tested with the SLED-C4. It only needs to test for the TMR2IF flag to keep time, so no interrupts are used. And you have quite a few instruction cycles to do other things between clock updates.

    DEFINE DEBUG_MODE 0 ' SLED-C4 serial mode = true
    ' setup vars for clock
    Time VAR WORD      ' accumulates TMR2 to PR2 match counts
    Minutes VAR BYTE   ' minutes
    Hours VAR BYTE     ' hours
    Match VAR PIR1.1   ' TMR2 to PR2 match interrupt flag bit
    PORTB.0=1          ' make sure SLED-C4 data input pin idles high        
    TRISB = %00001000  ' RB3 = CCP1 capture input, rest outputs
    CMCON = 7          ' disable comparators
    INTCON = 0         ' not using interupts. Just monitoring int flag bits
    PAUSE 250          ' let SLED-C4 power-up
    Time = 0           ' clear TMR2 to PR2 match counter
    Hours = 10         ' set clock starting hour here
    Minutes = 03       ' set clock starting minutes here
    ' set SLED-C4 start time
    DEBUG "D", Hours DIG 1,Hours DIG 0,Minutes DIG 1,Minutes DIG 0
    ' TMR2 increments from 0 until it matches the PR2 register value
    ' and then resets to 0 (on the next increment cycle) so place a
    ' value in PR2 1 cycle short of what you want. Here we want 250 for
    ' 60mS, so we write 249 to PR2.
    PR2 = 249           ' 249 +1 extra cycle for reset = 250*16*15*1uS=60mS
    Match = 0           ' clear match flag
    ' setup & start TMR2
    T2CON = %01110110  ' 1:16 prescale, 1:15 postscale, TMR2 on
       ' every 60mS the TMR2IF flag is set, and this routine is entered.
       ' Plenty of time to do other stuff.
       IF Match THEN          ' has TMR2 matched PR2? (should happen every 60mS)
          Match = 0           ' yes. clear TMR2 to PR2 match flag bit
          Time = Time + 1     ' increment 60mS count    
          IF Time = 1000 THEN ' has 60 seconds (1000*60mS) passed?
             Time = 0         ' yes. clear count
             Minutes = Minutes + 1 ' increment minute count
             IF Minutes = 60 THEN  ' have 60 minutes passed?
                Minutes = 0        ' yes. roll-over minutes from 59 to 00
                Hours = Hours + 1  ' update hour every 60 minutes
                IF Hours = 24 THEN Hours = 0 ' roll-over hours from 24 to 00
             ' print new time only once every minute
             DEBUG "D", Hours DIG 1,Hours DIG 0,Minutes DIG 1,Minutes DIG 0 
       GOTO Main
    It's pretty decent at keeping time. Ran for 3 hours, and it was spot-on with my PC clock to the second.

    tech at

  4. #4
    Join Date
    Feb 2009


    Thanks for the help both Darrel and Bruce!

    I kicked myself for not seeing that I wasn't resetting the Counts in my first posting However, things are working well now, and I can read my IR signal as I want by putting the clock routine as my interrupt and the IR PULSIN command as my main (as Darrel suggested). At this point is it just some coding to recognize alarms and different programmable options that I will throw in.

    I don't think I will have a problem with having enough time for tasks between interrupts since I am only doing the initial PULSIN command in my Main. If there was some kind of restriction in the interrupt routine I might have a problem them, but most of the heavy coding will be outside the main and the Interrupt routine. Though the code Bruce posted is very concise. I will try things out with both of them and see how things go.

    Ill post here if I have any more questions.

Similar Threads

  1. Instant Interrupts - Revisited
    By Darrel Taylor in forum Code Examples
    Replies: 790
    Last Post: - 9th January 2019, 16:38
  2. 18F2420, instant interrupts, and TMR0
    By dhickman in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 11th March 2009, 19:33
  3. DT instant interrupts with mister_e keypad
    By Tomexx in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 26th November 2008, 21:02
  4. DT's Instant Interrupts trouble
    By Tomexx in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 24th November 2008, 21:48
  5. Replies: 1
    Last Post: - 1st November 2006, 04:11

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