Working clock example using 32K watch crystal


+ Reply to Thread
Results 1 to 20 of 20
  1. #1
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default Working clock example using 32K watch crystal

    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

  2. #2
    malc-c's Avatar
    malc-c Guest

    Default

    ' Description : PicBasic Pro program using external 32K watch xtal and Timer1
    But 50% of the program is in assembler

  3. #3
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Default

    Quote Originally Posted by malc-c View Post
    But 50% of the program is in assembler
    Then show him how it's done. (in straight PBP)
    This task is worth 2 free 4x20 Parallel LCD's ... shipping outide of US/Canada extra.

    In case of multiple responses ... style will prevail.
    As judged by Darrel Taylor
    Ends 11/10/2010 Midnight Mountain Time
    DT

  4. #4
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,817

    Talking Naw only just point the way

    INCLUDE "DT_INTS-18.pbp" ; Base Interrupt System
    INCLUDE "ReEnterPBP-18.pbp" ; Include if using PBP interrupts"
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  5. #5
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default

    The earlier versions I wrote had NO asm but lost almost a minute an hour. To make up for that one could re-tune using TMR1H and TMR1L with a larger value. Problem is every change made to the program would mean spending a few days retuning and it would never be as precise.

    So yea I would love to be able to do this without asm in PBP AND be as accurate!

    Down the road I intend to join this interrupt sample with a SNTP internet program so I can have a near perfect millisecond low power $60 clock.

    Regards
    Tim C

  6. #6
    Join Date
    Jul 2003
    Posts
    2,405

    Default

    Code:
       ' Int handler doesn't mess with any PBP system variables - or lower 15-bits
       ' of TMR1 accumulated time. Uses only 4 instructions to set TMR1H high bit,
       ' increment seconds, clear the interrupt flag bit, save & restore WREG, STATUS,
       ' BSR and return from int handler.
     
    @myint                  ; create myint label
       TMR1H.7=1            ' Set TMR1 high bit for 1 second overflows
       seconds = seconds+1  ' Increment seconds
       PIR1.0=0             ' Clear TMR1 int flag
       @ retfie  FAST       ; Return with 'auto restore' of WREG, STATUS and BSR
    Should do it.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  7. #7
    malc-c's Avatar
    malc-c Guest

    Default

    Quote Originally Posted by Darrel Taylor View Post
    Then show him how it's done. (in straight PBP)
    I wish --- (I'll remove my tongue from in my cheek now )

  8. #8
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default

    Thank you Bruce
    Smaller, tighter, yet perfect speed. Started the clock last night with your change and so far the PIC18F452 has not gained or lost one second.
    Tim C

  9. #9
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,572

    Default

    Hi,

    I didn't see that one :
    http://www.pbpgroup.com/modules/wfse...hp?articleid=8

    did I miss something ???

    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  10. #10
    Join Date
    Jan 2005
    Location
    Boston MA
    Posts
    19

    Default

    Alain,
    Darrel's great example uses one crystal mine uses 2. And oh if something is sitting there soldered to the dev board and you don't have code to see if it works!!

  11. #11
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,572

    Default

    Quote Originally Posted by timc View Post
    Alain,
    Darrel's great example uses one crystal mine uses 2. And oh if something is sitting there soldered to the dev board and you don't have code to see if it works!!
    Hi, Timc

    Lol ... I didn't remember I had modified Darrel's code to use a 32 Khz Xtal ...

    and thought it was already done in the original release ...

    Here it is.

    Alain
    Attached Files Attached Files
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  12. #12
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Default

    There's a couple good examples. I like Bruce's.
    But it uses in-line assembly language instead of straight PBP.

    The Elapsed Timer modification is nice too ... but ...

    Nobody wins the LCD's.
    DT

  13. #13
    Join Date
    Sep 2009
    Posts
    716

    Default Re: Working clock example using 32K watch crystal

    I was playing with TimC RTC code, and I found 1 problem...
    If the interrupt occurs between these lines
    Code:
          GoSub get_time      ' Update minutes and seconds
          TOGGLE LED_0
          LCDOut $fe,2,"Time: ",DEC hours, ":", DEC2 minutes, ":", DEC2 seconds, "   "
    There is a chance to show 60 seconds.
    It happened to me, so I then wondered what was going on...
    Solution:
    Code:
    seconds        VAR BYTE bankA  ' variables within myint must be in bank 0.
    minutes        VAR Byte bankA       ' Elapsed minutes
    hours          var byte bankA
    :
    :
    :
    @myint                  ; create myint label
       TMR1H.7=1
        seconds = seconds+1  ' Increment second
        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 hours = 1    ' simple 12 hour clock format
            endif
        endif 
     PIR1.0=0             ' Clear TMR1 int flag
       @ retfie  FAST
    And remove get_time procedure
    Last edited by pedja089; - 25th May 2011 at 00:11. Reason: Repair CODE tag's

  14. #14
    Join Date
    Sep 2009
    Posts
    716

    Default Re: Working clock example using 32K watch crystal

    I'm trying to add the calendar.
    Does anyone have an idea how to make a calculation of leap year.
    I tried this
    If day>30+month.0 or (Month=2 and day>28 and year//4<>0) or (Month=2 and day>29 and year//4=0)then
    month=month+1
    but the code is 300b larger then this
    If day>30+month.0 or (Month=2 and day>28)then
    month=month+1
    Is there a more efficient way?

  15. #15
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,086

    Default Re: Working clock example using 32K watch crystal

    How about using 3 If-Then's insead of one with 3 OR's?

    Ioannis

  16. #16
    Join Date
    Sep 2009
    Posts
    716

    Default Re: Working clock example using 32K watch crystal

    I spent all night trying to find the best way ... I think this is
    Code:
                  If month=2 then
                     If year//4<>0 then
                        DMonth=29
                     else
                        DMonth=28
                     endif
                  else
                  Dmonth=30+month.0 
                  endif   
                  If day>Dmonth then
    @                CLRF _Day
    @                INCF _Month,F
                     If month>12 then
    And everywhere there is any = 0, I replaced the @ clrf, +1 replaced with @ incf.
    The end result was the RTC which consumes about 2uA and code size about 500B.

  17. #17
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,086

    Default Re: Working clock example using 32K watch crystal

    I think you have to change the <>0 to =0 when you test for the modulo 4.

    A better solution to cover more years (you code will not cover year 2100) is to use mod 400, mod 100 and mod 4 to test for leap year (mod 100 is NOT leap year, while 400 and 4 ARE leap years).

    Of course we may not live in year 2100, but just in case...

    Now about the @ commands, just be sure you are on page 0. Else you have to check the page bits. Or put this subroutine on top of your code.

    Ioannis
    Last edited by Ioannis; - 30th May 2011 at 11:13.

  18. #18
    Join Date
    Sep 2009
    Posts
    716

    Default Re: Working clock example using 32K watch crystal

    Thanks for that... It was just typo... 0-99 year is fine for this aplication.
    On the top of ISR I have BSR=0, and isr routine is on top of my programm.

  19. #19
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,086

    Default Re: Working clock example using 32K watch crystal

    If I may suggest, make the minutes and hours update in your main loop and not in Interrupt. A temp variable wll be needed for this.

    Ioannis

  20. #20
    Join Date
    Sep 2009
    Posts
    716

    Default Re: Working clock example using 32K watch crystal

    If pic loses power, it goes to sleep. And everything is shut off, only tmr1 is on. So i need that in ISR. Is there better way?

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts