I've looked through several of the equations on converting timer to wall time, and have composed the equations serveral ways, getting preloads that make sense.. so there's obviously something I'm missing here.. DIV_8 works, DIV_64 or DIV_256 run too slow. Is my calculation totally wrong and by some dumb luck DIV_8 is working but for the wrong reasons?

The Fosc/2 is a PIC24 thing (seeing most examples is /4)
Timer 3 - Type C timer, which is the back 16-bit of a 32-bit timer ;

Then use CLOCK_VALUE_TICKS in your set_timer3() function. After all, the value isn't going to change so there's no point in computing it in your program. Using a #define forces the compiler to compute it and then it's just a constant in your program - nothing to compute.

Setting timers 'to' a value is always inaccurate. On the PIC24/30 etc., you don't ever have to do this. Let the timer reload itself.
Then remember that the timer is not fed off the CPU clock. It is fed off the peripheral clock. Normally Fcpu/2.
So:
128MHz/2 = 64MHz.
64000000/1000 = 64000.

So /64 with a 1000 counts is perfect:

setup_timer3(TMR_INTERNAL | TMR_DIV_BY_64,999);

The actual period is always the period register+1, so 999, gives 1000 counts.

Get rid of the code setting the timer 'to' values, and your interrupt will be at 1000Hz.

setup_timer3(TMR_INTERNAL | TMR_DIV_BY_64);
set_timer3( 65536 - PERIOD ); // and set again in ISR

So, dunno.. I'm happy to take the answer and run but there seems to be a lot of historical posts about the 65536 - X approach, is it something about the PIC24?

Ttelmah

Joined: 11 Mar 2010Posts: 12643

Posted: Tue Feb 06, 2018 3:36 pm

The 65536-X approach is the only way you can do it on the PIC16/18. It is always less good than using a genuine division. so you are better off either using the 'increment by cycles' approach (in the code library), or Timer2 on these PIC's (the only timer with a programmable period on most of these).

newguy

Joined: 24 Jun 2004Posts: 1447Location: Edmonton, Alberta

Posted: Tue Feb 06, 2018 4:38 pm

sd_tom wrote:

Thanks the period works perfectly. I guess what I don't get is what's the difference (I know one is more accurate, but order of magnitudes seems off)

While not wrong, this makes me very nervous because it assumes that the divisions will be done in a certain order (left to right). It may never change, but explicitly grouping all the denominators together into one factor (using * and ()) forces the math to progress in one way only which assures that the result will always be what you expect.

Ttelmah

Joined: 11 Mar 2010Posts: 12643

Posted: Wed Feb 07, 2018 8:14 am

C, and it's preprocessor explicitly do evaluate left to right unless there is a precedence rule involved. It ought to be right, but I would prefer some form of sanity checking. Particularly for another reason: While in the example given, the result should always be <65536, if used for a less frequent interrupt and it gives a result that is larger than this the result could well be screwed...