0

I'm using a PIC18 with Fosc = 10MHz. So if I use Delay10KTCYx(250), I get 10,000 x 250 x 4 x (1/10e6) = 1 second.

How do I use the delay functions in the C18 for very long delays, say 20 seconds? I was thinking of just using twenty lines of Delay10KTCYx(250). Is there another more efficient and elegant way?

Thanks in advance!

Michael Reed
  • 13
  • 1
  • 5
  • Yeah: `for (int i = 0; i < 20; i++) { delay_1_sec(); }` –  Jun 30 '13 at 14:11
  • @H2CO3 So can I write for (int i = 0; i < 20; i++) { Delay10KTCYx(250); } within a while loop? – Michael Reed Jun 30 '13 at 14:26
  • Why couldn't you? (But why "within a while loop"? Isn't the for loop enough? It already does exactly what you want...) –  Jun 30 '13 at 14:26
  • Actually I'm running a calibration routine which requires me to rotate the sensor for 20 seconds. So basically I have a while(1) loop which enters calibration mode, delays for 20 seconds to rotate the sensor, exits calibration mode and delays for 50 seconds before the loop starts all over again. – Michael Reed Jun 30 '13 at 14:33
  • and what's the problem? –  Jun 30 '13 at 14:33
  • it can't compile now. says syntax error with the code you gave me – Michael Reed Jun 30 '13 at 14:39
  • does the while(1) affect it? – Michael Reed Jun 30 '13 at 14:39
  • that's unfortunate. That code doesn't have no syntax errors. I suggest you learn debugging. –  Jun 30 '13 at 14:39

2 Answers2

2

It is strongly recommended that you avoid using the built-in delay functions such as Delay10KTCYx()

Why you might ask?

These delay functions are very inaccurate, and they may cause your code to be compiled in unexpected ways. Here's one such example where using the Delay10KTCYx() function can cause problems.

Let's say that you have a PIC18 microprocessor that has only two hardware timer interrupts. (Usually they have more but let's just say there are only two).

Now let's say you manually set up the first hardware timer interrupt to blink once per second exactly, to drive a heartbeat monitor LED. And let's say you set up the second hardware timer interrupt to interrupt every 50 milliseconds because you want to take some sort of digital or analog reading at exactly 50 milliseconds.

Now, lastly, let's say that in your main program you want to delay 100,000 clock cycles. So you put a call to Delay10KTCYx(10) in your main program. What happenes do you suppose? How does the PIC18 magically count off 100,000 clock cycles?

One of two things will happen. It may "hijack" one of your other hardware timer interrupts to get exactly 100,000 clock cycles. This would either cause your heartbeat sensor to not clock at exactly 1 second, or, cause your digital or analog readings to happen at some time other than every 50 milliseconds.

Or, the delay function will just call a bunch of Nop() and claim that 1 Nop() = 1 clock cycle. What isn't accounted for is "overheads" within the Delay10KTCYx(10) function itself. It has to increment a counter to keep track of things, and surely it takes more than 1 clock cycle to increment the timer. As the Delay10KTCYx(10) loops around and around it is just not capable of giving you exactly 100,000 clock cycles. Depending on a lot of factors you may get way more, or way less, clock cycles than you expected.

The Delay10KTCYx(10) should only be used if you need an "approximate" amount of time. And pre-canned delay functions shouldn't be used if you are already using the hardware timer interrupts for other purposes. The compiler may not even successfully compile when using Delay10KTCYx(10) for very long delays.

I would highly recommend that you set up one of your timer interrupts to interrupt your hardware at a known interval. Say 50,000 clock cycles. Then, each time the hardware interrupts, within your ISR code for that timer interrupt, increment a counter and reset the timer over again to 0 cycles. When enough 50,000 clock cycles have expired to equal 20 seconds (or in other words in your example, 200 timer interrupts at 50,000 cycles per interrupt), reset your counter. Basically my advice is that you should always manually handle time in a PIC and not rely on pre-canned Delay functions - rather build your own delay functions that integrate into the hardware timer of the chip. Yes, it's going to be extra work - "but why can't I just use this easy and nifty built-in delay function, why would they even put it there if it's gonna muck up my program?" - but this should become second nature. Just like you should be manually configuring EVERY SINGLE REGISTER in your PIC18 upon boot-up, whether you are using it or not, to prevent unexpected things from happening.

You'll get way more accurate timing - and way more predictable behavior from your PIC18. Using pre-canned Delay functions is a recipe for disaster... it may work... it may work on several projects... but sooner or later your code will go all buggy on you and you'll be left wondering why and I guarantee the culprit will be the pre-canned delay function.

0

To create very long time use an internal timer. This can helpful to avoid block in your application and you can check the running time. Please refer to PIC data sheet on how to setup a timer and its interrupt.

If you want a very high precision 1S time I suggest also to consider an external RTC device or an internal RTC if the micro has one.

Lorenzo
  • 3,293
  • 4
  • 29
  • 56