ME Labs, Inc.
719-520-5323
 
Home:
  Developer Resources:

Programming Clues
    Sample Programs
   
    PICBASIC PRO™
Compiler Manual
    PICBASIC™ Compiler
Manual
    Serin2/Serout2 Modes
    ASCII Character Set
    Number Conversion
    Floating Point
Routines
    PBP Debug Monitor
    Articles and Tutorials

Hardware Clues
    Parts / Vendor List
    PICPROTO™ Boards
    LAB-X1 Docs
    LAB-X2 Docs
    LAB-X20 Docs
    LAB-X3 Docs
    LAB-X4 Docs
    LAB-XUSB Docs
    LAB-XT Docs
     
 

ME Labs, Inc. | 1-719-520-5323 | Example Program - TMR1CLK18.pbp

PicBasic Pro program that demonstrates the use of the Timer1 interrupt for a real-time clock. Written for the LAB-X1 experimenter board with an 18F452.
' Name        : TMR1CLK18.pbp
' Compiler    : PICBASIC PRO Compiler 2.6
' Assembler   : MPASM
' Target PIC  : PIC18F452 or similar 18F types
' Hardware    : Lab-X1 board
' Oscillator  : 4MHz crystal
' Keywords    : INTERRUPTS, LCDOUT, TIMER1
' Description : PicBasic Pro program that demonstrates the use of the Timer1
' interrupt for a real-time clock.  Written for the LAB-X1 experimenter board
' with an 18F452.
'

' Define interrupt handler
Define  INTHAND myint

wsave VAR BYTE bankA system   ' Saves W
ssave VAR BYTE bankA system   ' Saves STATUS

TICK VAR  BYTE bankA  ' make sure that the variables are in bank 0 if they are
                      ' to be used in the interrupt handler

seconds VAR BYTE      ' Elapsed seconds
minutes VAR WORD      ' Elapsed minutes
        
   minutes = 0        ' Clear time
   seconds = 0

   T1CON = $01        ' Turn on Timer1, prescaler = 1
   INTCON  = $C0      ' Enable global interrupts, peripheral interrupts
   PIE1 = $01         ' Enable TMR1 overflow interrupt

   GoTo main          ' jump over the interrupt handler and sub
 
   ' Assembly language interrupt handler
Asm
myint 
   ; Save the state of critical registers
   movwf   wsave      ; Save W
   swapf   STATUS, W  ; Swap STATUS to W (swap avoids changing STATUS)
   clrf    STATUS     ; Clear STATUS
   movwf   ssave      ; Save swapped STATUS

   ; Set the high register of Timer1 to cause an interrupt every
   ; 16384 counts (65536-16384=49152 or $C000). At 4MHz, prescale
   ; set to 1, this equates to a tick every 16384uS.  This works
   ; out to about 61 ticks per second, with a slight error.  The
   ; error could be reduced substantially by setting the TMR1L
   ; register and playing with different values for the prescaler
   ; and the ticks per second.

   movlw   0C0h       ; Prepare to set TMR1 high register
   movwf   TMR1H      ; Set TMR1H to C0h
   incf    _TICK,F    ; INCREMENT TICK COUNT
   bcf     PIR1, 0    ; Clear interrupt flag
        
   swapf   ssave, W   ; Retrieve the swapped STATUS value (swap to avoid changing STATUS)
   movwf   STATUS     ; Restore it to STATUS
   swapf   wsave, F   ; Swap the stored W value
   swapf   wsave, W   ; Restore it to W (swap to avoid changing STATUS)
   retfie             ; Return from interrupt
EndAsm

   ' PicBasic subroutine to update the minutes and seconds variables
get_time:
   ' Update the time when needed. The TICK variable will
   ' overflow if you don't update within 4 seconds.  This could
   ' be done in the interrupt handler, but it's easier to do
   ' it in PicBasic, and you usually want the interrupt handler
   ' to be as short and fast as possible.
        
   PIE1 = 0                                ' Mask the interrupt while we're messing with TICK
   seconds = seconds + (tick/61)           ' Add the accumulated seconds
   tick = tick // 61                       ' Retain the left-over ticks
   PIE1 = $01                              ' Interrupt on again
   minutes = minutes + (seconds / 60)      ' Add the accumulated minutes
   seconds = seconds // 60 ' Retain the left-over seconds
Return                                     ' Return to the main program
 
main:
' **************************************************************
' Begin program code here.  The minutes and seconds variables can
' be used in your code.  The time will be updated when you call the
' get_time routine. Disable interrupts while executing timing-critical
' commands, like serial communications.

Define  LCD_DREG  PORTD
Define  LCD_DBIT  4
Define  LCD_RSREG PORTE
Define  LCD_RSBIT 0
Define  LCD_EREG  PORTE
Define  LCD_EBIT  1

   ADCON1 = 7          ' Set PORTA and PORTE for digital operation     
   Low PORTE.2         ' Enable the LCD
        
   Pause 150           ' Pause to allow LCD to initialize
   LCDOut $fe,1        ' Clear LCD

   loops   VAR WORD
   loops = 0

mainloop:  
   loops = loops + 1
   LCDOut $fe,$C0,"Loops Counted: ", DEC5 loops
    
   GoSub get_time      ' Update minutes and seconds

   LCDOut $fe, 2, "Time: ",DEC5 minutes, ":", DEC2 seconds ' Display the elapsed time

   GoTo mainloop       ' Repeat main loop
        
   End

           

Download the program file.