Menu

16F684 Timer1 Issues

Help
2010-06-23
2013-05-30
  • Mark Slovacek

    Mark Slovacek - 2010-06-23

    I am trying to figure out how to use a overflow interrupt on TMR1 to semi accurately measure pulses per time period for a future project.

    The posted program was made to signal a TMR1 interrupt after 100ms, and update Sec, Min, and Hours.
    Additionally, the program was designed to start at a specific time so I could track the microcontroller time versus real time.

    The program loses about 14min per hour.

    Some of the code came from suggestions found on the GCBASIC forums. 
    I have racked my brains, and studied the forums trying to figure out why there is so much difference between the microcontrollers time and real time.

    ' This is a program to test the accuracy of the internal timer1
    ' Hardware configuration
    #chip 16F684, 4
    #config osc = int
    ' LCD connection settings
    #define LCD_IO 2 'Set up the LCD to use 4 bit operation
    ' Define the 2 LCD Clock and Data Lines
    #define LCD_DB PORTC.2
    #define LCD_CB PORTC.1
    Dim Counter As Word
    Hour = 8: Min = 30: Sec = 0: Counter = 0
    'Clock pulse frequency is 4/4 = 1 MHz
    'Divided by 1 by prescaler (PS1_1/2), timer incremented at frequency of .5 MHz
    ' = every 2 us
    ' If cleared, timer overflows after 65536 * 2 us = every 131.072 ms
    ' Timer will overflow after 131.072 ms
    ' We need it to overflow after 31.072, so the timer must have a value loaded into it
    ' Need to load TMR1H, TMR1L with value that they will have after 31.072 ms - then it will count to 131.072, taking 100.00 ms
    ' Value = 65536 * (31.071 / 131.072) = 15535.5
    ' High byte of this is 60, low byte is 175 (60 * 256 + 175 = 15535)
    ' So, we need to set TMR1H to 60 and TMR1L to 175.
    ' If you're not comfortable with high and low bytes, put 3035 into a word variable (say TempVar)
    ' Then, set TMR1L to TempVar, and TMR1H to TempVar_H - this makes the compiler split the number up
    ' Set up Timer1
    InitTimer1 Osc, PS1_1/2
    StartTimer 1
    On Interrupt Timer1Overflow Call IncTime
    TMR1L = 0 'Need to do this according to the PIC datasheet
    TMR1H = 60
    TMR1L = 175
    do 'Main part of Program
        cls
        Print HOUR
        Locate 0,2: Print ":"
        Locate 0,3: Print Min
        Locate 0,5: Print ":"
        Locate 0,6: Print Sec
        Wait 300 ms
        
    Loop
    SUB IncTime
    'Increment the counter
    Counter ++
    If Counter = 10 Then '10 x 100ms 1sec
        Sec ++
        Counter = 0
    End If
    If Sec = 60 Then
        Min ++
        Sec = 0
    End If
    If Min = 60 Then
        Hour ++
        Min = 0
    End If
    If Hour = 12 Then
        Hour = 0
    End If
    End Sub
    

    Can anybody tell me what I am doing wrong?

     
  • gcha44

    gcha44 - 2010-06-23

    Hi,
    The 16F84 has only a 8 bits Timer0 and you can't use Tmr1H and Tmr1L!
    So , you can try  another PIC or if you don't , you must use Timer0 .

    Then Timer0 overflow after 256 pulses or 256µS with a 4Mhz cristal  .
    So , to use TMR0 interrupt , you must preload Timer0 with 6 .
    Then ,Timer0 will overflow every 250 µS . With a 1/16 prescaller  , then it'll owerflow every 250 * 16 = 4000 µs or 4 ms
    For one  second (= 1000 ms) , Timer0 will overflow 1000 /4 = 250 times .

    Each time Timer0 will overflow , you'll must write :
    Timer0=6
    Counter +
    if Counter>=250 then
       sec +
       counter=0
    end if
    And so on
    Regards
    GC

     
  • Mark Slovacek

    Mark Slovacek - 2010-06-23

    GC,

    I am a little confused, according to the 16f684 spec sheet there is a 16 bit TMR1 with the capacity to set Tmr1H and Tmr1L.

    http://ww1.microchip.com/downloads/en/devicedoc/41202c.pdf

    Is GCBASIC not set up to utilize the TMR1 features in the 16F684?

    I will try your suggestion in regards to using TMR0.

    Thanks for your help

     
  • gcha44

    gcha44 - 2010-06-23

    Oops , I 'm sorry , I 've read 16F84 , but it was 16F684 !!
    So , you can use Timer1 .
    But , to have One second interrupt ., you can do :
    With 1/2 prescaller , Timer1 must be preloaded to 65536-50000= 15536 because 50000 ( 50000µs=50ms *2=100ms)
    Then you can do the same thing as in previous exemple
    Timer1 must overflow 10 times to have one second delay
    and you have to preload TImer1H=60 , Timer1L=176 at each interrupt
    So , it seams that your code is correct, but I think you  must  put   ( TImer1H=60 , Timer1L=176)   in sub  IncTime , because these values must be preloaded after each interrupt , but if you leave them in main program , Timer1 will be reloaded even is there is no interrupt 
    Regards
    GC

     
  • gcha44

    gcha44 - 2010-06-24

    I realize that I was very tired yesterday , indeed my  last explanation wasn't good . lol
    Because , if you lose about 14 mn , it's evident that TMR1 isn't preloaded each time interrupt occurs , and TMR1 starts again with it's complete value : 65536 . Because   15536/ 65535 =23.7   and   14mn/60mn=23,3  !!
    So , your program is correct . I think you must only put  ( Timer1H=60 , Timer1L=176) in sub IncTime and your problem will be solved.
    Regards
    GC

     

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.