How to program the timer

2008-06-02
2013-05-30
  • Nobody/Anonymous

    I don't understand how to program the timer and how to measure the time in seconds or miliseconds. So, what does the prescaler do and how do I read the timevalue. I assume you need TMR1H and TMR1L for that.

     
    • Hugh Considine

      Hugh Considine - 2008-06-02

      A few basic facts:
      - The timer counts CPU clock cycles
      - The timer overflow interrupt event occurs when the timer goes from 255 to 0 (8 bit timers), or from 65535 to 0 (16 bit timers)
      - The prescaler divides the number of CPU clock cycles the timer sees.

      I've not tried it, but this code should be suitable for keeping track of time:

      #chip 16F88, 8
      #config osc = int

      Dim TenthSeconds As Word
      TenthSeconds = 0

      'Clock pulse frequency is 8/4 = 2 MHz
      'Divided by 4 by prescaler (PS1_1/4), timer incremented at frequency of 0.50 MHz
      ' = every 2 us
      ' If cleared, timer overflows after 65535 * 2 us = every 131.07 ms

      InitTimer1 Osc, PS1_1/4
      StartTimer 1
      On Interrupt Timer1Overflow Call IncCounter

      Do
          'Main code
          'Do something useful with TenthSeconds here
      Loop

      Sub IncCounter
          ' Timer will overflow after 131.07 ms
          ' We need it to overflow after 100.00, so the timer must have a value loaded into it
          ' Need to load TMR1H, TMR1L with value that they will have after 31.07 ms - then it will count to 131.07, taking 100.00 ms
          ' Value = 65535 * (31.07 / 131.07) = 15535
          ' 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 15535 into a word variable (say TempVar)
          ' Then, set TMR1L to TempVar, and TMR1H to TempVar_H - this makes the compiler split the number up

          TMR1L = 0 'Need to do this according to the PIC datasheet
          TMR1H = 60
          TMR1L = 175

          'Increment the counter
          TenthSeconds += 1
      end sub

       
    • Nobody/Anonymous

      I attempted to compile the above program and had a syntax error on line 14.  I could not find "on interrupt" in the manual.  I think I have the latest version of the program. 

      Is there a syntax error, updated manual?  Or is Version: 0.9 10/2/2007  the latest version?

       
    • kent_twt4

      kent_twt4 - 2008-08-02

      The on interrupt command will be found in GCBasic folder/?GCBasic(compiled html help file).  For IE7 had to uncheck the always ask box in order for the html link to work.

      Hughes example compiled fine in the latest Version GCBasic 0930, wouldn't hurt to load the 'update zip' either.  If there is still a syntax problem, then post your code, so that it can be checked for errors.

       
    • Nobody/Anonymous

      The code is posted here, I pulled it and tried to compile it.  So I must have an old copy of the compiler.  I pulled from this site.  gcbasic.sourceforge.com was not there for me all day though I could get to sourceforge.com.  Will try there again.

      I just unzipped the program in a directory and I wrote a batch file to call gcbasic with the /d: to point to the support files.  I did not do a windows install or use and IDE.  Did not see a reason for all that.  Just want to convert a gcbasic file to asm.

      Where can I get the latest code?  All the update.zip links were down this morning, that is why I pulled it from here.

      Also, is there a switch to throw the gcbasic lines in front of the macro expansion as a comment, then I can use mplabs or something like it to debug the code and see my gcbasic lines as a comment

       
    • Nobody/Anonymous

      What do the hi and low bytes do? How do they work?

       
  • Horacio

    Horacio - 2012-05-15

    Hey, thanks!
    This is great info… I wonder why no one has replied to it.
    I was looking for a way of having a program run for a couple of minutes and then making it go to sleep. This is very much what I was looking up, but had some strange results.
    I implemented it using a 12F629 with a clock frequency of 4MHz and a prescaler value of 1/8.

    I copied/pasted/modified your code as follows:


    #chip 12F629,4

    #config osc = int

    Dim HalfSeconds As Word

    HalfSeconds = 0

    'Clock pulse frequency is 4/4 = 1 MHz

    'Divided by 8 by prescaler (PS1_1/8), timer incremented at frequency of 0.125 MHz

    ' = every 8 us

    ' If cleared, timer overflows after 65535 * 8 us = every 524.28 ms

    InitTimer1 Osc, PS1_1/8

    StartTimer 1

    On Interrupt Timer1Overflow Call IncCounter

    Do

        'Main code
        '(blinks an LED)
        if HalfSeconds < 120 goto nothingyet 'keep looping if less than a minute
        asm sleep

    nothingyet:
    Loop

    Sub IncCounter

        ' Timer will overflow after 524.28 ms

        ' We need it to overflow after 500.00 ms, so the timer must have a value loaded into it

        ' Need to load TMR1H, TMR1L with value that they will have after 24.28 ms - then it will count to 524.28, taking 500.00 ms

        ' Value = 65535 * (24.28 / 524.28) = 3035

        ' High byte of this is 11, low byte is 219 (11 * 256 + 219 = 3035)

        ' So, we need to set TMR1H to 11 and TMR1L to 219.

        ' 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

        TMR1L = 0 'Need to do this according to the PIC datasheet_ <-- I was not sure about this one but left it in anyway_

        TMR1H = 11

        TMR1L = 219

        'Increment the counter

        HalfSeconds = HalfSeconds + 1   ' the graphical gcbasic editor changed the original HalfSeconds += 1 to this form…

    end sub


    That is just the way I programmed into the 12F629, and it worked just fine; the LED blinked for about a minute and then the chip would go to sleep.

    My problem is that when I measured the actual time it took for it to go to sleep it was just 51 seconds.
    At first I thought it had something to do with the numbers I input into the H and L timers to compensate for the 24.28 ms difference in overflow. I tried changing the values but nothing noticeable came up… I even changed those values in TMR1H and TMR1L to zero and couldn't find any difference.
    I'm not sure how this is supposed to work, but my guess is that those values should be input into the H and L values of the timer every time it overflows, and the way I see it in the program is that they are updated every time the subroutine is called… Anywho, I tried changing that but couldn't figure out how to tell it to update it only when overflowing.

    I tried changing other things and the only way I could get the program to go to sleep after a minute was by changing the value HalfSeconds was compared to from 120 to 142 (!)

    I would appreciate any help and comments on this and on what I might be doing wrong (or if there's any simpler way of doing it)..

     

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks