Looked all over trying to find an example with a second crystal connected to the TIMER1 overflow. This example uses the earlier 18F452 version of the Olimex PIC-WEB board. Ran the clock for a day without gaining or loosing a second! Lots of places where I was not sure what to do. Comments are welcome.
Regards
Tim C
Code:
' Name : TMR1CLK.pbp
' Target PIC : PIC18F452 or similar 18F types
' Hardware : PIC-WEB ver A board with added LCD
' Oscillator : 10MHz crystal. You May have to modify default 18F452 fuses for > 4Mhz
' Resolution : Expect to get +- 5sec/day or better
' Description : PicBasic Pro program using external 32K watch xtal and Timer1
' interrupt for a real-time clock.
' Origional ver from: http://melabs.com/resources/samples/18f/tmr1clk18.htm
'
DEFINE OSC 10 ' We're using a 10MHz oscillator
DEFINE LOADER_USED 1 ' Boot-Loader is being used
Define INTHAND myint ' Define interrupt handler
Symbol LED_0 = PORTD.5
symbol BUTTON_0 = PORTB.0
wsave VAR BYTE bankA system ' Saves W
ssave VAR BYTE bankA system ' Saves STATUS
seconds VAR BYTE bankA ' variables within myint must be in bank 0.
minutes VAR Byte ' Elapsed minutes
hours var byte
' LCD config
Define LCD_DREG PORTD
Define LCD_DBIT 0
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
hours = 2
minutes = 23 ' Pre Set time here then add seconds to clock using button
seconds = 0
T1CON.7=0 ' 8 Bit r/w (16 bit seems to cause problems)
T1CON.5=0 ' Part 1 of 1:1 prescale
T1CON.4=0 ' Part 2 pf 1:1 prescale
T1CON.3=1 ' turn on the low freq clock osc
T1CON.2=1 ' Do not Sync low Freq clock with main clock
T1CON.1=1 ' use 32Khz xtal as the Timer1 source
T1CON.0=1 ' enable Timer1
PIE1 = $01 ' Enable TMR1 overflow interrupt
INTCON = $C0 ' Finally Enable global interrupt and peripheral interrupts
GoTo mainloop ' 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
; 32768 counts (2^15).
movlw 080h ; Prepare to set TMR1 high register
movwf TMR1H ; Set TMR1H to 80h
incf _seconds,F ; INCREMENT seconds 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
' Subroutine to update the time variables
get_time:
if seconds > 59 then
seconds = seconds - 60 ' better then making seconds=0
minutes = minutes + 1
if minutes > 59 then
minutes = 0
hours = hours + 1
if hours > 12 then ' simple 12 hour clock format
hours = 1
endif
endif
endif
Return
mainloop:
GoSub get_time ' Update minutes and seconds
TOGGLE LED_0
LCDOut $fe,2,"Time: ",DEC hours, ":", DEC2 minutes, ":", DEC2 seconds, " "
Pause 300 ' Pause to see LED blink. Also help with debounce
if button_0 = 0 then
LCDOut $fe,$C0,"+1s "
seconds = seconds + 1
else
LCDOut $fe,$C0," "
endif
GoTo mainloop ' Repeat main loop
End
Bookmarks