Proton BASIC Compiler - New Article

• # Interrupt Driven clock Timer 1

In response to a question on the forum I wrote this little snippet of code to make a timer. At its core is an interrupt running at 100hz off of TMR1. In the interrupt routine is a series of incrementing counters and If THEN statements. As each counter rolls past its set point the IF THEN statement resets the counter and increments the next, Note it is written entirely in BASIC! Lastly we display the result on an lcd.

Points to note are the interrupt is turned off before making a copy of all the timer vars, before enabling interrupts again. Play with FUDGE_FACTOR to get the timing right.

Example Code

'-----------------------------------------------
' DEMONSTARTION OF A 100THS OF A SECOND TIMER
' COUNTING UP TO 255 DAYS
'
'
' FIDDLE WITH FUDGE FACTOR TO IMPROVE ACCURACY
'
' BY TIM BOX NOV 03
'-----------------------------------------------

Include "PROTON_4.INC"

DIM _100THS ' DECLARE ALL VARS AS BYTES
DIM SECS
DIM MINS
DIM HOURS
DIM DAYS
DIM TEMP_100THS
DIM TEMP_SECS
DIM TEMP_MINS
DIM TEMP_HOURS
DIM TEMP_DAYS

DIM GIE AS INTCON.7 ' ALIAS

DIM TIMER1REG AS TMR1L.WORD ' MAKE THE TIMER VAR INTO A WORD
SYMBOL FUDGE_FACTOR = 7 ' FIDDLE WITH TO IMPROVE ACCURACY
SYMBOL TMR1_VAL =((65536)-(XTAL*2500))+FUDGE_FACTOR ' CALCULATE OSC OFFSET VALUES FOR 100HZ INTERRUPT

ON_INTERRUPT INTERRUPT_ROUTINE ' WHERE TO GO ON AN INTERRUPT

GOTO START ' JUMP THE INTERRUPT CODE

INTERRUPT_ROUTINE:

CLEAR T1CON.0 ' STOP TMR1
TIMER1REG = TIMER1REG + TMR1_VAL ' LOAD TMR1
SET T1CON.0 ' START TMR1

INC _100THS
IF _100THS = 100 THEN ' UP 100TS
CLEAR _100THS
INC SECS ' UP SECONDS
IF SECS = 60 THEN
CLEAR SECS
INC MINS ' UP MINS
IF MINS = 60 THEN
CLEAR MINS
INC HOURS
IF HOURS = 24 THEN ' UP HOURS
CLEAR HOURS
INC DAYS
ENDIF
ENDIF
ENDIF
ENDIF
CLEAR PIR1.0 ' CLEAR TMR1 INTERRUPT FLAG
CONTEXT RESTORE ' END INTERRUPT ROUTINE

START:
CLEAR ' CLEAR ALL VARS
T1CON = %00000000 ' SET UP TMR1 TO HAVE 1:1 PRESCALER AND ACT AS A TIMER
PIR1.0 = 0 ' CLEAR TMR1 INTERRUPT FLAG
INTCON = %11000000 ' GLOBAL AND PERIPHERAL INTERRUPTS ON
PIE1.0 = 1 ' ENABLE TMR1 AS PERIPHERAL INTERRUPT SOURCE
T1CON.0 = 1 ' SET TIMER1 RUNNING

CLS ' CLEAR THE LCD

WHILE 1 = 1 ' MAKE AN ENDLESS LOOP
GIE = 0 ' TURN OFF GLOBAL INTERRUPTS
WHILE GIE = 1 : GIE = 0 : WEND ' AND MAKE SURE THEY ARE OFF
TEMP_100THS = _100THS ' MAKE A COPY OF THE VARS
TEMP_SECS = SECS
TEMP_MINS = MINS
TEMP_HOURS = HOURS
TEMP_DAYS = DAYS
GIE = 1 ' TURN THE INTERRUPTS BACK ON

PRINT AT 1,1,DEC2 TEMP_DAYS,":",DEC2 TEMP_HOURS,":",DEC2 TEMP_MINS,":",DEC2 TEMP_SECS,":",DEC2 TEMP_100THS

DELAYMS 100 ' SMALL DELAU

WEND ' ROUND AND ROUND WE GO

STOP
contributed by Timothy Box