Menu

help with timer to make clock

Help
2011-03-04
2013-05-30
  • Nobody/Anonymous

    here is what i have, I left out the extra subs that are unrelated to the problem, it only sends out zero values and never increments the count.
    #chip 12F683, 18
    #config MCLRE=off, WDT=off
    Ser_Init
    on interrupt Timer1Overflow call IncCounter
    dim serun as byte
    dim serdec as byte
    dim sercen as byte
    dim sermil as byte
    dim serdecimil as byte

    InitTimer1 ExtOsc, PS1_8
    dim full as byte
    dim min as byte
    dim sec as byte
    dim hr as byte
    full = 0
    sec=0
    min=0
    hr=0
    wait 1 s

    ClearTimer 1
    TMR1L = 0 'Need to do this according to the PIC datasheet
        TMR1H = 36
        TMR1L = 13 'should be 10hz
    StartTimer 1

    main:
    if full = 10 then
    sec=sec+1
    full=0
    end if 
    if sec = 60 then
    min= min+1
    sec=0
    end if
    if min= 60 then
    hr=hr+1
    min=0
    end if
    if hr=25 then hr=0
    bin2ascii (hr)
    xmit_print (":")
    bin2ascii (min)
    xmit_print (":")
    bin2ascii (sec)
    wait 250 ms
    xmit_rs232 12
    xmit_rs232 13
    goto main

    Sub IncCounter
        TMR1L = 0
        TMR1H = 255
        TMR1L = 82
    full=full+1
    end sub

     
  • Mauried

    Mauried - 2011-03-04

    The Main routine takes too long to run.
    The interrupts will occur 10 times a second, which is every 100 ms
    but the main routine takes 250 ms+ to run.
    It will never see full get to 10.
    Either get rid of the wait 250 ms line in the main routine , or reduce the interrupt rate so that the interrupts occur slower.
    If you are trying to build a clock, why not simply interrupt once a second.

     
  • Nobody/Anonymous

    i can't get get it down to 1hz speed, the lowest it will go is 8.xxhz

     
  • gcha44

    gcha44 - 2011-03-09

    1) You must place second , minutes and hours calculations in your Sub IncCounter :
         After full=full+1
        if full = 10 then
          sec=sec+1
          full=0
       end if 
      if sec = 60 then
        min= min+1
        sec=0
      end if
    if min= 60 then
       hr=hr+1
       min=0
    end if
    if hr=25 then hr=0

    because if your main program is too long because a too long data transmission your calculations aren't taken into account !
    2) If loop is too long and PIC doesn't transmits anything , errors may be in differents subs as Ser_init ,xmit_print or     bin2ascii
    GC

     
  • Mauried

    Mauried - 2011-03-09

    Also, where is the clock for the PIC coming from.
    There doesnt appear to be any clock definition in the code.
    To make a clock that keeps time , you must use an external crystal
    as the internal RC oscillator isnt stable enough.
    Its only  1% accurate.

     
  • mmotte

    mmotte - 2011-03-09

    how fast is your external osc running?
    "#chip 12F683, 18    "
    is it a  18 mhz crystal?

    If your doing RTC things  a 32khz clock crystal is usually used.  Run on internal osc for the main.

    Also where are you reseting the Timer1  ovrflow flag?

     
  • Nobody/Anonymous

    I still only get "00:00:00" transmitted to the pc over and over never incriments?
    here is the whole code:
    #chip 12F683, 18
    #config MCLRE=off, WDT=off
    Ser_Init
    on interrupt Timer1Overflow call IncCounter
    dim serun as byte
    dim serdec as byte
    dim sercen as byte
    dim sermil as byte
    dim serdecimil as byte

    InitTimer1 ExtOsc, PS1_8
    dim full as byte
    dim min as byte
    dim sec as byte
    dim hr as byte
    full = 0
    sec=0
    min=0
    hr=0
    wait 1 s

    ClearTimer 1
    TMR1L = 0 'Need to do this according to the PIC datasheet
        TMR1H = 36
        TMR1L = 13 'should be 10hz
    StartTimer 1

    main:

    bin2ascii (hr)
    xmit_print (":")
    bin2ascii (min)
    xmit_print (":")
    bin2ascii (sec)
    wait 10 ms
    xmit_rs232 12
    xmit_rs232 13
    goto main

    Sub IncCounter
    ClearTimer 1
        TMR1L = 0
        TMR1H = 36
        TMR1L = 13
    StartTimer 1
    full=full+1
    if full = 10 then
    sec=sec+1
    full=0
    end if 
    if sec = 60 then
    min= min+1
    sec=0
    end if
    if min= 60 then
    hr=hr+1
    min=0
    end if
    if hr=25 then hr=0
    end sub

    Sub Ser_Init
    ;slight adjustment was required for 9600bps delay value
    #define baud 103 ;expressed as frequency in us
    #define halfbaud 52 ;place Read of SerRx in middle of bit
    #define SerTxHigh Set GPIO.0 On
    #define SerTxLow Set GPIO.0 Off
    #define SerRx GPIO.1
    dir GPIO.0 out ;Tx
    dir GPIO.1 in ;Rx
    SerTxHigh ;Initial RS232 idle state
    end sub

    sub XMIT_PRINT (PrintData$)
    PrintLen = PrintData(0)
    if PrintLen = 0 then exit sub
    'Write Data
    for SysPrintTemp = 1 to PrintLen
    XMIT_RS232(PrintData(SysPrintTemp))
    next
    end sub

    Sub XMIT_RS232(Xmit_Byte)#NR
    SerTxLow
    wait baud us
    For cntr = 1 to 8
    Rotate Xmit_Byte Right
    If Status.C ON Then SerTxHigh
    If Status.C Off Then SerTxLow
    wait baud us
    Next
    SerTxHigh
    wait baud us
    end sub

    sub bin2ascii (LCDValue as word ) #NR
    Dim SysCalcTempX As Word
    LCDValueTemp = 0
    LCDShowChar = 0
    SERDECMIL = 0
    SERMIL = 0
    SERCEN = 0
    SERDEC = 0
    SERUN = 0

    If LCDValue >= 10000 then
    LCDValueTemp = LCDValue / 10000
    LCDValue = SysCalcTempX
    SERDECMIL = LCDValueTemp + 48
    Xmit_RS232 (SERDECMIL)
    LCDShowChar = TRUE
    End If

    If LCDShowChar > 0 or LCDValue >= 1000 then
    LCDValueTemp = LCDValue / 1000
    LCDValue = SysCalcTempX
    SERMIL = LCDValueTemp + 48
    Xmit_RS232 (SERMIL)
    LCDShowChar = TRUE
    End If

    If LCDShowChar > 0 or LCDValue >= 100 then
    LCDValueTemp = LCDValue / 100
    LCDValue = SysCalcTempX
    SERCEN = LCDValueTemp + 48
    Xmit_RS232 (SERCEN)
    LCDShowChar = TRUE
    End If

    'If LCDShowChar > 0 or LCDValue >= 10 then
    LCDValueTemp = LCDValue / 10
    LCDValue = SysCalcTempX
    SERDEC = LCDValueTemp + 48
    Xmit_RS232 (SERDEC)
    'End If

    SERUN = LCDValue + 48
    Xmit_RS232 (SERUN)
    End Sub

     
  • Nobody/Anonymous

    In order to get glitch free output, I think the main program should also be in the isr (no wait states here).  Just output every sec (i.e. when "full " rolls over).  If the Uart routine is also going to be used in main then their will be glitches.

    Kent

    main:
    goto main
    Sub IncCounter
    ClearTimer 1
        TMR1L = 0 
        TMR1H = 36
        TMR1L = 13
    StartTimer 1
    full=full+1
    if full = 10 then 
    sec=sec+1
    full=0
    end if  
    if sec = 60 then 
    min= min+1
    sec=0
    end if
    if min= 60 then
    hr=hr+1
    min=0
    end if
    if hr=25 then hr=0
    if full = 0 then
        if hr < 10 then xmit_print ("0")
        bin2ascii (hr)
        xmit_print (":")
        if min < 10 then xmit_print ("0")
        bin2ascii (min)
        xmit_print (":")
        if sec < 10 then xmit_print ("0")
        bin2ascii (sec)
        xmit_rs232 10
        xmit_rs232 13
    end if
    end sub
    
     
  • Nobody/Anonymous

    so I made the changes you suggested above and have the following code, but i get no output at all, so my guess is the timer1 is not running and full is never reaching 10 and tx never happens.
    #chip 12F683, 18
    #config MCLRE=off, WDT=off
    Ser_Init
    on interrupt Timer1Overflow call IncCounter
    dim serun as byte
    dim serdec as byte
    dim sercen as byte
    dim sermil as byte
    dim serdecimil as byte

    InitTimer1 ExtOsc, PS1_8
    dim full as byte
    dim min as byte
    dim sec as byte
    dim hr as byte
    full = 0
    sec=0
    min=0
    hr=0
    wait 1 s

    ClearTimer 1
    TMR1L = 0 'Need to do this according to the PIC datasheet
        TMR1H = 36
        TMR1L = 13 'should be 10hz
    StartTimer 1

    main:
    goto main

    Sub IncCounter
    ClearTimer 1
    TMR1L = 0
    TMR1H = 36
    TMR1L = 13
    StartTimer 1
    full=full+1
    if full = 10 then
    sec=sec+1
    full=0
    end if
    if sec = 60 then
    min= min+1
    sec=0
    end if
    if min= 60 then
    hr=hr+1
    min=0
    end if
    if hr=25 then hr=0
    if full = 0 then
    'if hr < 10 then xmit_print ("0")
    bin2ascii (hr)
    xmit_print (":")
    'if min < 10 then xmit_print ("0")
    bin2ascii (min)
    xmit_print (":")
    'if sec < 10 then xmit_print ("0")
    bin2ascii (sec)
    xmit_rs232 10
    xmit_rs232 13
    end if
    end sub

    Sub Ser_Init
    ;slight adjustment was required for 9600bps delay value
    #define baud 103 ;expressed as frequency in us
    #define halfbaud 52 ;place Read of SerRx in middle of bit
    #define SerTxHigh Set GPIO.0 On
    #define SerTxLow Set GPIO.0 Off
    #define SerRx GPIO.1
    dir GPIO.0 out ;Tx
    dir GPIO.1 in ;Rx
    SerTxHigh ;Initial RS232 idle state
    end sub

    sub XMIT_PRINT (PrintData$)
    PrintLen = PrintData(0)
    if PrintLen = 0 then exit sub
    'Write Data
    for SysPrintTemp = 1 to PrintLen
    XMIT_RS232(PrintData(SysPrintTemp))
    next
    end sub

    Sub XMIT_RS232(Xmit_Byte)#NR
    SerTxLow
    wait baud us
    For cntr = 1 to 8
    Rotate Xmit_Byte Right
    If Status.C ON Then SerTxHigh
    If Status.C Off Then SerTxLow
    wait baud us
    Next
    SerTxHigh
    wait baud us
    end sub

    sub bin2ascii (LCDValue as word ) #NR
    Dim SysCalcTempX As Word
    LCDValueTemp = 0
    LCDShowChar = 0
    SERDECMIL = 0
    SERMIL = 0
    SERCEN = 0
    SERDEC = 0
    SERUN = 0

    If LCDValue >= 10000 then
    LCDValueTemp = LCDValue / 10000
    LCDValue = SysCalcTempX
    SERDECMIL = LCDValueTemp + 48
    Xmit_RS232 (SERDECMIL)
    LCDShowChar = TRUE
    End If

    If LCDShowChar > 0 or LCDValue >= 1000 then
    LCDValueTemp = LCDValue / 1000
    LCDValue = SysCalcTempX
    SERMIL = LCDValueTemp + 48
    Xmit_RS232 (SERMIL)
    LCDShowChar = TRUE
    End If

    If LCDShowChar > 0 or LCDValue >= 100 then
    LCDValueTemp = LCDValue / 100
    LCDValue = SysCalcTempX
    SERCEN = LCDValueTemp + 48
    Xmit_RS232 (SERCEN)
    LCDShowChar = TRUE
    End If

    'If LCDShowChar > 0 or LCDValue >= 10 then
    LCDValueTemp = LCDValue / 10
    LCDValue = SysCalcTempX
    SERDEC = LCDValueTemp + 48
    Xmit_RS232 (SERDEC)
    'End If

    SERUN = LCDValue + 48
    Xmit_RS232 (SERUN)
    End Sub

     
  • Nobody/Anonymous

    Really should use the code tags.  Copy and pasting native text is in some sort of weird format, and doesn't seem to compile. 

    You could try the internal 4Mhz osc as a test, just to see if there's output.

    I became frustrated with the results from the TMR1 register, and interrupts.  Moved over to CCP1, in the software interrupt mode, so everything is Main now.  The results seem much better, although not great.  For an accurate clock I've used the ds1307 in the past.

    Good luck.

    Kent.

     
  • Mauried

    Mauried - 2011-03-11

    Ive made several clocks using 16F88 with a low frequency clock crystal (2 Mhz)
    which allows you to use a 1 hz tick interrupt to do the counting.
    Ideally also, if you want to use a serial output for the data its best to use a chip
    with a hardware uart, so that the interrupts dont glitch the output characters.
    The timer overflow concept to interrupt should work ok as long as you keep the code within
    the interrupt routine at a minimum.
    There is a simple example that comes with the GCbasic install called interrupt that explains
    how to use the timer overflow to count .

     
  • Nobody/Anonymous

    I think you configured Timer1 to use external clock:

    InitTimer1 ExtOsc, PS1_8

    Exists that external clock??
    That's not the clock you use for PIC, its a dedicated ext. clock, ussually 32.768 KHz for real time,  that should be connected to T1OSI and T1OSO pins.

    If you want to use the same clock the cpu, then configure this way:
    InitTimer1 Osc, PS1_8

     
  • kent_twt4

    kent_twt4 - 2011-11-22

    Closed due to spam bot.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.