Timer overflows and interrupts


Closed Thread
Results 1 to 11 of 11
  1. #1
    barkerben's Avatar
    barkerben Guest

    Default Timer overflows and interrupts

    Hi,

    I'm planning on using the hardware timer to genrate a clock, freeing up the chip to do other things.

    I had been planning that whenever the timer overflowed (on a 16F768), a service routine would be called that would incremement a counter. This counter would be constantly polled in the main program, and when it reached some value, anther counter could be incremented, and the first reset (because I can only count up to 256 in one variable), and so on ...

    I'm planning t generate a clock at betweeen 1Hz-->10Hz.
    Does this sound reasonable?

    I've come across Prescalers in some literture as well, but it is all a bit confusing - how are they used, and how can I calculate interrupt period ...?

  2. #2
    Join Date
    Jul 2003
    Location
    Sweden
    Posts
    237


    Did you find this post helpful? Yes | No

    Post

    Hi Ben,

    >>first reset (because I can only count up to 256 in one variable), and so on ...<<

    Last time i checked a WORD sized variable could count up to 65535. Apart from that you're on the right track.

    >>I'm planning t generate a clock at betweeen 1Hz-->10Hz.
    Does this sound reasonable?<<

    It sure does, 1 to 10 Hz should be no problem. Just make sure your mainprogram loops fast enough.

    >>I've come across Prescalers in some literture as well, but it is all a bit confusing<<

    A prescaler slows down the clocksignal to the timer. If you set the prescaler to 1:2 your timer will count at half the speed. With 1:8 it will ofcourse be 8 times slower. With no prescaler th timer will increment once evrey 1/4 of your oscillatorspeed.

    I thought i'd give you some advice but i can't find a pic called 16F768. Not a big problem since the timers are very similar throughout the entire 16(and 12) series. I'll also assume that you're running it at 4MHz. Your "instructionclock" will be 4MHz/4=1MHz, this is your timebase.

    Using Timer1 to get 10Hz.
    Set the prescaler to 1:2 and let the timer count 50000 steps. Since the timer only count upwards you'll need to "preset" it to 65536-50000=15536. Or you could set the prescaler to 1:4 and count 25000, or prescale to 1:8 and count 12500.

    Using Timer1 to get 4Hz.
    Prescale to 1:4 and count 62500 steps or prescale to 1:8 and count 31250 steps.

    Using Timer1 to get 2Hz.
    Prescale to 1:8 and count 62500 steps.

    We have now almost reached the limit of timer1. To get it even slower you'll need to use a software counter(postscaler) just like you described earlier. The actual limit of the hardwarecounter is OSC/4/8/65536, with 4MHz that equals 1.90735Hz.

    You could also use Timer2 but this timer can't go lower than OSC/4/16/256/16, with 4MHz that's 15,259Hz. You quickly realize that you must use a software postscaler to get down to your 10Hz.

    Timer0 can be used but i don't recomment it. It shares it's prescaler with the WDT. You could "steal" it from the WDT but then the WDT must be disabled. If you do that the pic won't be able to recover(reset) if your program hangs.

    /Ingvar

  3. #3
    barkerben's Avatar
    barkerben Guest


    Did you find this post helpful? Yes | No

    Default

    Thanks for that - that's really helpful. My inability to remember a PIC number is why you couldn't find it - In fact I have a PIC 16F876

    The same numbers, but in a completely different order. Oh well...!

    The idea is that the counter is incremented in the service routing, and the value of the counter is polled in the loop. The whole thing is basically a variable oscillator controlled via the serial line (again using interrupts), so all the main loop needs to do is loop and constantly check if anything needs changing by comparing variables. Hopefully this will mean very low latency.

    Thanks again,


    Ben

  4. #4
    barkerben's Avatar
    barkerben Guest


    Did you find this post helpful? Yes | No

    Default

    Ah - just read your reply in more detail. I think I will probably go for setting the timer to a constant rate of, say, 10Hz, then
    changing my effective frequency by only responding every n interrupts, where n is a value received over the serial link.

    This will make it easier to change the frequency than having to recalibrate the hardware timer each time. As long as the hardware timer is >= my max desired frequency, then by setting different values for n I should be able to get any frequency below.

    Thanks,


    Ben

  5. #5
    barkerben's Avatar
    barkerben Guest


    Did you find this post helpful? Yes | No

    Default

    I really should get all of my replys into one post ...

    Presumably to set hardware properties in the PIC via PICBasic, I just refer directly to the neccesart control registers - for instance, to set up a 1:2 prescaler on timer1 I would use the basic command:

    T1CON.4=1
    T1CON.5=0

    And similarly for setting up interrupt registers, or in fact any control registers within the PIC...


    Cheers (for the last time!)

    Ben

  6. #6
    barkerben's Avatar
    barkerben Guest


    Did you find this post helpful? Yes | No

    Default

    Oops - I'm talking rubbish. I need to get a 1Hz base clock, and then count n times to get n*1Hz clock....

    Doh!


    Ben

  7. #7
    Join Date
    Jul 2003
    Location
    Sweden
    Posts
    237


    Did you find this post helpful? Yes | No

    Post

    If you have a freq of 10 Hz you can divide that by using a softwarecounter(postscaler). You'll end up with 10 divided by your postscalervalue. The postscaler can only be integers. Soooo.........

    10Hz / 1 = 10Hz
    10Hz / 2 = 5Hz
    10Hz / 3 = 3.333Hz
    10Hz / 4 = 2.5Hz
    10Hz / 5 = 2Hz
    10Hz / 6 = 1.667Hz
    and so on .......

    A better way would be to use a fixed postscaler. Then change the timer reloadvalue and prescaler to get twice the frequency you want. This way you can produce very accurate frequencies in the region you want. If you use a fixed prescaler of 1:8 and a fixed postscaler of 1:2 and only change the reloadvalue you can produce ......

    65536 - 6250 = 59286 ---> 10Hz
    65536 - 6251 = 59285 ---> 9.9984Hz
    65536 - 6252 = 59284 ---> 9.9968Hz
    ......
    65536 - 6944 = 58592 ---> 9.0006Hz
    65536 - 6945 = 58591 ---> 8.9993Hz
    ......
    65536 - 7812 = 57724 ---> 8.0005Hz
    65536 - 7813 = 57723 ---> 7.9995Hz
    ......
    65536 - 12500 = 53036---> 5Hz
    65536 - 12501 = 53035---> 4.9996Hz
    ......
    65536 - 20833 = 44703 ---> 3.0000Hz
    65536 - 20834 = 44702 ---> 2.9999Hz
    ......
    65536 - 31250 = 34286 ---> 2Hz
    65536 - 31251 = 34285 ---> 1.9999Hz
    ......
    65536 - 62499 = 3037 ---> 1.000016Hz
    65536 - 62500 = 3036 ---> 1Hz

    It's fairly easy to let PBP calculate the reloadvalue for you. You could specify your frequency in mHz(milliHertz). 10 Hz would be 10000, 1 Hz would be 1000. Run it through this code to produce your timer1reloadvalue. All variables are WORD sized.

    Dummy = 62500
    Dummy = Dummy * 1000
    TMR1Reload = DIV32 DesiredFreq
    TMR1Reload = 0 - TMR1Reload

    The 62500 comes from OSC/4/Prescaler/Postscaler. 4000000/4/8/2=62500. 1000 is there to make it possible to specify mHz.

    There are ways to expand all of this to include variable prescalersettings to get better accuracy at higher frequencies, but that's a story for another day......

    /Ingvar

  8. #8
    barkerben's Avatar
    barkerben Guest


    Did you find this post helpful? Yes | No

    Default

    Thanks - I realise my 1Hz base clock was rubbish - of course I need to start at the maximum freq. and work down.

    One final questio about the prescaler idea you posted:

    TMR1Reload does not appear in the manual that I can see - is it a PBP command...?


    Cheers,


    Ben

  9. #9
    barkerben's Avatar
    barkerben Guest


    Did you find this post helpful? Yes | No

    Default

    Ah - it looks like maybe I can just use:

    TMR1=TMR1Reload to preset the timer. Is this correct?


    Ben

  10. #10
    Join Date
    Jul 2003
    Location
    Sweden
    Posts
    237


    Did you find this post helpful? Yes | No

    Post

    Almost, you'll need to write it in two steps.

    TMR1L = TMR1Reload.lowbyte
    TMR1H = TMR1Reload.highbyte

    I guess that you've already realized that "TMR1Reload" is a plain word sized variable, nothing else.

    I also must tell you that if you need extreme accuracy you'll need an assembler interrupt. You will have some latency if you're planning on using "ON INTERRUPT". You may overcome that by adding the "TMR1Reload" to the TMR1. You'll also have to add the time it takes to do that addition, no big deal since that time will be constant. It might be better to add that when calculating the TMR1 reloadvalue, it would save you one addition in the interruptroutine. A portion of the interrupt would(could) look like .....

    T1CON.0 = 0 'Stop timer1 while we're messing with it
    Dummy.lowbyte = TMR1L
    Dummy.highbyte = TMR1H
    Dummy = Dummy + TMR1Reload ' + additionlatency if not added before
    TMR1L = Dummy.lowbyte
    TMR1H = Dummy.highbyte
    T1CON.0 = 1 'Start timer1 again

    /Ingvar

  11. #11
    barkerben's Avatar
    barkerben Guest


    Did you find this post helpful? Yes | No

    Default

    Hi - thanks. Yes I realised that if I'm resetting the timer each tine it interrupts, then thyere will be some innacuracy as the service rouyting takes finite time. However, accuracy is not that important - consistency is more important - so hopefully this wil be fine.

    I'm away fromn the lab at the mo, but will hope to get this implemented by the start of Jan, and ill let you know hoe it goes.

    Just hoping PICBasic is up to the job - probably should have used Assembler or C, but the latter is unavailable, and the former is scary!


    Cheers,


    Ben

Similar Threads

  1. mS Timer
    By whmeade10 in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 8th September 2020, 13:12
  2. Help me with interupt
    By azmax100 in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 3rd February 2009, 01:17
  3. Handling External/Timer Interrupts
    By Tacky3000 in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 3rd December 2008, 12:09
  4. Timers !
    By n qwerty in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 22nd August 2007, 12:39
  5. '628 tmr1 interrupts
    By jpeakall in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 27th February 2004, 09:06

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

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