Hello,

I need to implement long timer which should time say 234 375 ticks (using prescaler = 7). So I decided to divide whole period to 4 segments of length: 65 535, 65 535 ,65 535 and 37 770 (that is 234 375 total). These values will be stored in modulo register of my timer, each time the timer overflows the modulo will be updated by the next modulo value.

I assumed that modulo registers are updated only after timer overflows (so when I change modulo register, timer should count with old modulo value till next overflow, then the modulo is updated)

// counter (long) variable stores information about ticks left on the next overflow// moduloSet (long) variable stores all ticks, ie. 234 375interrupt VectorNumber_Vtpm2ovf TPM2OVFISR(void) { (void) TPM2SC; TPM2SC_TOF = 0; if(counter == 0) { // time to do some action (234 375 ticks should be gone) counter = moduloSet; } // compute ticks left after next overflow // timer now counts with modulo value stored in TPM2MOD, so subtract it from counter variable if(counter > TPM2MOD) { counter = counter - 1 - TPM2MOD; } else { counter = 0; } // compute next modulo, update it // timer should time with old modulo value till next overflow if(counter == 0) { // whole timer will count down on the next overflow if(moduloSet > 0x1FFFF) { TPM2MOD = 0xFFFF; } else if(moduloSet <= 0xFFFF) { TPM2MOD = (unsigned int) (moduloSet - 1); } else { TPM2MOD = (unsigned int) (moduloSet / 2) - 1; } } else if(counter <= 0xFFFF) { // only few ticks left TPM2MOD = (unsigned int) (counter - 1); } else { // many ticks left TPM2MOD = 0xFFFF; } }

But It doesn't work... I can see (when debugging) that modulo registers stores values 0xFFFF, 0xFFFF, 0xFFFF, 0x9386 (that's 234 375 in total) but in real, I can see my actions are done with longer period (of about 30%) than 234 375 should be.

Please, can you give me any advice how to implement long timer? The timer must be very accurate.

My MCU is SH4.

Hi Gaminn,

I extend the timer to either 24-bits or 32-bits. Here is how I do it:

First, You extend the timer to 24-bits with one byte of ram. Increment that extended-timer byte in each timer-overflow.

Then:

1) When you need to to set a timer, calculate where the whole 24-bit timer would be at time-out, and load the low 16-bits into the output-compare register. Save the high 8bits.

2) On each output-compare interrupt, compare those saved 8-bits with the high byte of your (extended) timer. If they don't match, just clear the interrupt flag and exit.

3) When the two high-bytes match, your time-out has occurred.

I have used this approach to run multiple timers concurrently, using a timer queue, with time-outs as long as a day.