# How to create 5 second hw delay for PIC18f

Discussion in 'Embedded Systems and Microcontrollers' started by newbieEm, Oct 14, 2013.

Not open for further replies.
1. ### newbieEm Thread Starter New Member

Jun 8, 2010
7
0
I am trying to create 5 sec hw delay using Timer0 for PIC18f4550 microcontroller.

I am using 16 bit mode timer. My understanding is:

Fosc = 48 mhz/4 = 12 mhz
using 256 prescaler, brings frequency to 12,000,000/256 = 46875
so period = 1/f = 1/ 46875 = 0.00002133

so to create 5 sec delay , frequency has to be 5 sec/ 0.00002133 = 234411

now what I am confused is: using 16 bit register,

So the value to be filled in Timers 16 bit register = 65,535 - 234,411
since the register rolls over up to FFFF.

or should it be 234,411 - 65535

uiTime = (234411 - 65535));
ucTimeLo = uiTime % 256;
ucTimeHi = uiTime/256;
TMR0H = ucTimeHi;
TMR0L = ucTimeLo;

2. ### shteii01 AAC Fanatic!

Feb 19, 2010
3,519
515
How many oscillator periods in one machine cycle of your uC?

Last edited: Oct 14, 2013
3. ### THE_RB AAC Fanatic!

Feb 11, 2008
5,435
1,305
Your system has issues because it still involves multiple overflows of the 16bit timer.

I would suggest an alternative system, run the timer at 12Mhz (prescaler = 1:1) to give better resolution and eliminate/reduce the need to deal with a fractional timer value.

Then a 5 second period can be made by counting X number of timer0 overflows (you can test the TMR0IF overflow flag).

1 sec = 12 million counts of TMR0
5 sec = 60 million counts
number of overflows = (60 mil / 16bits)
= (60 mil / 65536)
= 915.5 overflows

so just let TMR0 free run, and count the number of times the overflow flag was set, and after that count >=915 you have a 5 second delay.

absf likes this.
4. ### MaxHeadRoom Expert

Jul 18, 2013
10,873
2,529
Why not use a \$2.00 32Khz watch crystal on T1OSC input and detect the 1 sec rollover, It will not matter what your system clock is.
Max.

5. ### ErnieM AAC Fanatic!

Apr 24, 2011
7,447
1,628
Your calculations all seem correct.

You want the timer to count just 65,535 - 234,411 times.

You can think of it this way: say you have a 4 bit timer that wraps at 15. If you want it to count 5 periods you load it with 15-5=10, so 5 counts later it wraps around.

But there is a problem here: you want to delay more cycles then the register can handle!

So you have to count roll overs of the register (or some other technique). That timer rolls over at a rate of 12MHz/256/65535 = 183.1 Hz So if you count about 915 roll overs you get your 5 seconds.

Personally I would use another timer, as I remember it is Timer2 that you can compare to a register and get very nice 1 mS timing intervals. I use that to trigger an interrupt which updates a tick counter; 5,000 ticks would be 5 seconds.

6. ### John P AAC Fanatic!

Oct 14, 2008
1,639
225
If this were my project, I'd set the timer to maximum prescale, 256:1. That gives an increment rate of 12000000/256, or 46875/second. Then I'd turn on interrupts from T0 rollover, but for every interrupt I'd reset the T0 counter so that the count to the next rollover would be 1172 (I believe that would be done by subtracting 1172 from the count during the interrupt--there may need to be a minor adjustment which means it's not exactly 1172, but that's the desired effect).

What this does is give you an interrupt rate of 46875/1172, or 40/sec (actually 39.996, hope that's OK). That's chosen so you can count interrupts in an 8-bit register, and reach 5 seconds of total time--just count up to 200, and there you are. If anything in your program needs a 40/second counter, you're free to use it for other things too.

7. ### MrChips Moderator

Oct 2, 2009
12,657
3,461
There is no need to settle for inaccurate times if your application requires more exact timing. Simply divide your clock frequency to give exact integer values. For example, set the timer prescale value to 120.

8. ### John P AAC Fanatic!

Oct 14, 2008
1,639
225
RTM, Chips. The prescaler can only be set to powers of 2.

But I should have thought of something--the final count could be more accurate if you use a prescaler lower than 256 but reset the count to something higher than 1172, and try to get the product of the two as close to 300000 as possible (that's 12000000/40). It looks as if 32 and 9375 are good candidates for an exact count.

9. ### MrChips Moderator

Oct 2, 2009
12,657
3,461
There you go. Glad that you can find a way to solve your problem.

The mcu I use allows a prescaler value from 1 to 65536!

10. ### ErnieM AAC Fanatic!

Apr 24, 2011
7,447
1,628
You can get exact intervals using Timer2:

Prescaler to 1/32 so the clock is 125KHz, then set the PR2 value to 125...

even rollovers every 1 mS without any fancy coding.

You can additionally set the Postscaler for longer intervals from 1 to 16 mS (that divisor is 1,2,3,4,...14,15,16).

11. ### newbieEm Thread Starter New Member

Jun 8, 2010
7
0
>>You can think of it this way: say you have a 4 bit timer that wraps at 15. If you want it to count 5 periods you load it with 15-5=10, so 5 counts later it wraps around.

I must be missing something. why are you substracting 5 from 15? 5 is less than 15 (overfill value). if we had a value more than 15 for example 17..then we would do 17 - 15 = 2 and counts 2 after it goes all the way to 15 and wraps around.

I think ideally I needed to use Timer2 since it works with PWM. but Timer2 working with PWM is little convoluted. For example Microchip publishes following two formulas. I know Fosc is 48 mhz (using external crystal) not sure what Tosc is and what TMR2 prescale values I should use if I have to go 5 sec 50% duty cycle and 5 sec 10% duty cycle.

PWM Period = [(PR2) + 1] • 4 • TOSC •
(TMR2 Prescale Value)

PWM Duty Cycle = (CCPRXL:CCPXCON<5:4>) •
TOSC • (TMR2 Prescale Value)

Thanks all...

12. ### RG23 Active Member

Dec 6, 2010
301
2
you did the correct calculations before.

In the timer subroutine, introduce a btg (bit toggle)instruction

for example btg PORTC,2 (use any unused output port pin)

Using the oscilloscope you will see the exact time after which the bit toggles. For instance you see the bit PORTC,2 toggling after every 500 ms.

After doing this, use a counter variable, initialise its value to 10 to get the 5 sec interval.

You may need to add the nop instructions in your subroutine to meet the accuracy.

You can always modify the prescaler settings in the timer register,the counter variable and the number of nop instructions to meet the desired timing requirements.

Last edited: Oct 16, 2013
13. ### colinb Active Member

Jun 15, 2011
351
35
Do tell... what MCU is that? Sounds like a great feature. I think I've seen it before...

14. ### ErnieM AAC Fanatic!

Apr 24, 2011
7,447
1,628
Probably I made some mistake. It happens when you post work without a proof reader.

15. ### MrChips Moderator

Oct 2, 2009
12,657
3,461
I am referring to an STM32 MCU.