• LAB-X1 Timer2 Clock

    This example shows how to create a 24-hour time clock on the LAB-X1 using Timer2/PR2 match - with buttons to increment hours, minutes, reset the time to 12:00, and reset the Timer2 tick counter.

    Also shown is how to use the 16F1934 IOCBF interrupt flags to recognize button presses in the background. I.E. you don't need to poll port pins to detect a change, and no interrupts required.
    Code:
    ' Name        : T246_1934X.pbp
    ' Compiler    : PICBASIC PRO Compiler 2.6
    ' Assembler   : MPASM
    ' Target PIC  : 40-pin 16F1934 or similar
    ' Hardware    : LAB-X1 Experimenter Board
    ' Oscillator  : 4MHz external crystal
    ' Keywords    : LCDOUT
    ' Description : PICBASIC PRO program to demonstrate using Timer2 for a
    ' 24 hour format clock. Time is shown on the LCD as Time = 11:14 with
    ' hours : minutes. The keypad is used to increment hours, minutes, reset
    ' the time to 12:00, and reset the Timer2 tick counter.
    '
    ' Note: Open the 16F1934.INC file in your PBP directory, and comment out the default
    ' __config settings.
    ASM
       __config _CONFIG1, _FOSC_XT & _WDTE_SWDTEN & _PWRTE_ON & _MCLRE_ON & _BOREN_ON & _IESO_ON & _FCMEN_ON
       __config _CONFIG2, _PLLEN_OFF & _LVP_OFF & _VCAPEN_OFF & _STVREN_ON & _BORV_25
    ENDASM
     
    ' Define LCD pins
    Define LCD_DREG  PORTD
    Define LCD_DBIT  4
    Define LCD_RSREG PORTE
    Define LCD_RSBIT 0
    Define LCD_EREG  PORTE
    Define LCD_EBIT  1
     
    ' 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
    IocFlag Var INTCON.0  ' portb int-on-change flag bit
     
       Gosub Init         ' jump to hardware initialization routine
     
       Lcdout $fe,1,"Time = ", #Hours DIG 1,#Hours DIG 0,":",#Minutes DIG 1,#Minutes DIG 0
        ' setup & start TMR2 after Lcdout
       T2CON = %01110110  ' set 1:16 prescale, 1:15 postscale, TMR2 on
     
    Main:
       ' every 60mS the TMR2IF flag is set, and this routine is entered.
       ' Plenty of time to do other stuff.
       If Match = 1 Then           ' has TMR2 matched PR2? (should happen every 60mS)
          Match = 0                ' yes. clear TMR2 to PR2 match flag bit PIR1.1
          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 Minutes
             If Minutes = 60 Then  ' roll-over from 59 to 0
                Minutes = 0        ' zero Minutes count
                Hours = Hours + 1  ' and increment Hours count
                If Hours = 24 Then ' roll-over from 23 to 0
                   Hours = 0       ' zero Hours count
                Endif
             Endif
             ' Update time on LCD every 60 seconds
             Lcdout $fe,$87,#Hours DIG 1,#Hours DIG 0,":",#Minutes DIG 1,#Minutes DIG 0
          Endif   
       Endif
     
          ' test for key press
       If IocFlag Then    ' if keys SW13, 14, 15 or 16 were pressed,
          Gosub GetKeys   ' get the button/buttons pressed
       Endif
       Goto Main
     
    ' ===========\ Get Keypad Switch Presses /=========== '   
    GetKeys:
       Pause 500              ' crude debounce for key press
     
       ' SW13 increments Hours
       If IOCBF.4 Then       ' IOCBF.4 = 1 when low edge detected on RB4
          While PORTB.4 = 0  ' wait for key release        
          Wend               ' 
          Hours = Hours + 1 : Time = 0
          If Hours = 24 Then Hours = 0
       Endif
     
       ' SW14 increments Minutes
       If IOCBF.5 Then       ' IOCBF.5 = 1 when low edge detected on RB5
          While PORTB.5 = 0  ' wait for key release
          Wend               '         
          Minutes = Minutes + 1 : Time = 0
          If Minutes = 60 Then Minutes = 0
       Endif
     
       ' SW15 zeros Time "tick" counter
       If IOCBF.6 Then       ' IOCBF.6 = 1 when low edge detected on RB6
          While PORTB.6 = 0  ' wait for key release
          Wend               '      
          Time = 0
       Endif
     
       ' SW16 resets clock to 12:00
       If IOCBF.7 Then       ' IOCBF.7 = 1 when low edge detected on RB7
          While PORTB.7 = 0  ' wait for key release
          Wend               '         
          Hours = 12 : Minutes = 0 : Time = 0
       Endif
       IOCBF = 0             ' reset all int-on-change bits on exit
       IocFlag = 0
       ' Update LCD on each change
       Lcdout $fe,$87,#Hours DIG 1,#Hours DIG 0,":",#Minutes DIG 1,#Minutes DIG 0
       Return
     
    Init:
       ANSELA = 0    ' porta all digital
       ANSELB = 0    ' portb all digital
       ANSELD = 0    ' portd all digital
       ANSELE = 0    ' porte all digital
     
       OPTION_REG.7 = 0    ' enable PORTB pullups   
       PORTB = 0           ' RB3 low
       TRISB = %11110111   ' RB3 = 0 for output to keys 13, 14, 15, 16
       WPUB = %11110000    ' weak pull-ups on for ----> RB4, 5,  6,  7
       IOCBP = 0           ' positive edge disabled
       IOCBN = %11110000   ' negative edge int-on-change enabled for keys
     
       TRISD = 0           ' PORTD all outputs
     
       INTCON = 0          ' not using interupts. Just monitoring int flag bits
       Time = 0            ' clear TMR2 to PR2 match counter
       Hours = 10          ' set clock starting hour to 10 here
       Minutes = 16        ' set clock starting minutes to 16 here
     
       ' TMR2 increments from 0 until it matches the value in the PR2 register.
       ' The match automatically resets Timer2 and sets the Timer2 interrupt flag
       ' bit PIR1.1.
     
       PR2 = 249           ' 0 to 249 = 250. 250*16*15*1uS=60mS
       Match = 0           ' clear PIR1.1 match flag bit
       Pause 100           ' Wait for LCD to start
     
       Return              ' Return to caller
     
       End
    This article was originally published in forum thread: LAB-X1 Timer2 Clock started by Bruce View original post