GEEZER
- 30th March 2005, 04:47
I'm new a this. I need a background timer for a project to give me an exact second. I have it down to a max error of .3% it seems to drift between .3% and .1%. Is this as good as it gets?
I am using a 16F877A at 20 mHZ. Can I make any adjustments that will give me absolute precision?
Here's my code.
DEFINE LCD_DREG PORTC
DEFINE LCD_DBIT 4
DEFINE LCD_RSREG PORTC 'DEFINES
DEFINE LCD_RSBIT 1
DEFINE LCD_EREG PORTC
DEFINE LCD_EBIT 0
DEFINE LCD_BITS 4
DEFINE LCD_LINES 4
DEFINE LCD_COMMANDUS 3000
DEFINE LCD_DATAUS 1000
DEFINE OSC 20
'VARIABLES
REFRESHED VAR BIT
X VAR WORD
Y VAR WORD
Z VAR WORD
ZZ VAR WORD
X = 0
Y = 0
Z= 0
ZZ=0
ON INTERRUPT GOTO PULSE_COUNT 'WHERE TO GO ON INTERRUPT
GOTO INITIALIZE 'SKIP INTERUPT CODE TO SET UP TIMER
''' INTERRUPT CODE '''
DISABLE
PULSE_COUNT:
T1CON.0 = 0 ' TURNS TIMER OFF
T1CON.0 = 1
REFRESHED = 1 'SET FLAG TO SAY COUNT READ
X = X + 1
IF X = 133 THEN
Y = Y + 1
X = 0
ENDIF
INTCON.2 = 0 'CLEARS INTERRUPT FLAG
RESUME
ENABLE ' RELOAD SYSTEM VARIABLES
''' END OF INTERRUPT CODE '''
''' INITIALIZE ALL REGS '''
INITIALIZE:
OPTION_REG.0 = 0 'SET PRESCALER TO 1:1
OPTION_REG.1 = 0
OPTION_REG.2 = 0
OPTION_REG.5 = 0 'TMR0 CLOCK FROM MAIN OSC
OPTION_REG.3 = 0 'PRESCALER ASSIGNED TO TMR0
INTCON.2 = 0 'CLEARS INTERRUPT FLAG
T1CON = %00000110
T1CON.0 = 1 'TURNS TIMER ON
TMR0 = 7 'LOAD THE TIMER IN MEMORY
INTCON.5 = 1 'ENABLE TMR0 INTERRUPTS
REFRESHED = 0 'HOLD FIRST READ TILL MAIN INT OCCURS
INTCON.7 = 1 'START TIMER RUNNING
''' CALCULATIONS AND READ OUT '''
HIGH PORTC.1
PAUSE 1000
LCDOUT $FE, 1
LOOP:
IF Y = 59 THEN
Z = Z + 1
Y = 0
ENDIF
iF REFRESHED = 1 THEN
LCDOUT $FE, 1
LCDOUT $FE, 2
LCDOUT
LCDOUT $FE, $C0
LCDOUT " SEC ", DEC Y
LCDOUT $FE, $90
LCDOUT " MIN ", DEC Z
LCDOUT $FE, $D0
LCDOUT
REFRESHED = 0 'PREVENT RE-READ TILL NEXT
ENDIF 'INTERRUPT
PAUSE 50
GOTO LOOP
END
Your help is appreciated.
The Geezer
I am using a 16F877A at 20 mHZ. Can I make any adjustments that will give me absolute precision?
Here's my code.
DEFINE LCD_DREG PORTC
DEFINE LCD_DBIT 4
DEFINE LCD_RSREG PORTC 'DEFINES
DEFINE LCD_RSBIT 1
DEFINE LCD_EREG PORTC
DEFINE LCD_EBIT 0
DEFINE LCD_BITS 4
DEFINE LCD_LINES 4
DEFINE LCD_COMMANDUS 3000
DEFINE LCD_DATAUS 1000
DEFINE OSC 20
'VARIABLES
REFRESHED VAR BIT
X VAR WORD
Y VAR WORD
Z VAR WORD
ZZ VAR WORD
X = 0
Y = 0
Z= 0
ZZ=0
ON INTERRUPT GOTO PULSE_COUNT 'WHERE TO GO ON INTERRUPT
GOTO INITIALIZE 'SKIP INTERUPT CODE TO SET UP TIMER
''' INTERRUPT CODE '''
DISABLE
PULSE_COUNT:
T1CON.0 = 0 ' TURNS TIMER OFF
T1CON.0 = 1
REFRESHED = 1 'SET FLAG TO SAY COUNT READ
X = X + 1
IF X = 133 THEN
Y = Y + 1
X = 0
ENDIF
INTCON.2 = 0 'CLEARS INTERRUPT FLAG
RESUME
ENABLE ' RELOAD SYSTEM VARIABLES
''' END OF INTERRUPT CODE '''
''' INITIALIZE ALL REGS '''
INITIALIZE:
OPTION_REG.0 = 0 'SET PRESCALER TO 1:1
OPTION_REG.1 = 0
OPTION_REG.2 = 0
OPTION_REG.5 = 0 'TMR0 CLOCK FROM MAIN OSC
OPTION_REG.3 = 0 'PRESCALER ASSIGNED TO TMR0
INTCON.2 = 0 'CLEARS INTERRUPT FLAG
T1CON = %00000110
T1CON.0 = 1 'TURNS TIMER ON
TMR0 = 7 'LOAD THE TIMER IN MEMORY
INTCON.5 = 1 'ENABLE TMR0 INTERRUPTS
REFRESHED = 0 'HOLD FIRST READ TILL MAIN INT OCCURS
INTCON.7 = 1 'START TIMER RUNNING
''' CALCULATIONS AND READ OUT '''
HIGH PORTC.1
PAUSE 1000
LCDOUT $FE, 1
LOOP:
IF Y = 59 THEN
Z = Z + 1
Y = 0
ENDIF
iF REFRESHED = 1 THEN
LCDOUT $FE, 1
LCDOUT $FE, 2
LCDOUT
LCDOUT $FE, $C0
LCDOUT " SEC ", DEC Y
LCDOUT $FE, $90
LCDOUT " MIN ", DEC Z
LCDOUT $FE, $D0
LCDOUT
REFRESHED = 0 'PREVENT RE-READ TILL NEXT
ENDIF 'INTERRUPT
PAUSE 50
GOTO LOOP
END
Your help is appreciated.
The Geezer