Logo Banner

ELECTRONICS - [PIC applications]- [waiting loops]

Waiting loops with a time-out in High-Tech C


It often happens a microcontroller application needs to wait for a certain condition. In these cases you could create a polling loop that cycles until the required condition is met.

Let's assume a sample application where the microcontroller communicates with an external digital temperature sensor: The microcontroller sends a request to retrieve the current temperature, and then wait until the sensor responds.

You should always assume there could be a temporary communication error between the sensor and the microcontroller (for example due to an electro magnetic influence). Generally it is a good idea to add a time-out function to all waiting loop that possibly could "hang". Otherwise the software in the microcontroller could cycle the loop indefinately - it would cause the microcontroller to appear locked up.

This page describes some possible ways to implement a waiting loop with a time-out protection. The examples are designed for small microcontroller applications. Larger applications usually needs to handle a lot of I/O simultaneous and can't afford to wait on a single polling loop because the software has to perform other tasks as well.

The examples are written in High-Tech C and were targetted to be used with the PIC 16F628A.

A basic waiting loop

It is very easy to build a basic waiting loop, just use the while() construction of the C-language. Let's assume a PIC application that waits for a positive signal in port RB0 (bit 0 of PORT B):

      while (RB0==0);

The loop will cycle over and over again, until RB0 becomes "1". If this condition doesn't occur, the loop just cycles indefinitely. In some applications this could mean you have to press the reset-button.

The waiting loop with a time-out

The following code demonstrates a similar waiting loop, but now I have added a variable named time-out. This integer variable is assigned with a value of 1000 (decimal).

      unsigned int timeout=1000;
      while (RB0==0 && (--timeout > 0));

The loop still waits for RB0 to become "1". But each time the loop is cycled, the value of the timeout variable is decreased. Eventually the timeout variable will reach 0 and the waiting loop will be exited.

You now can question yourself: was the required condition met, or did the loop just time-out? This can be verified very quickly by evaluating the current value of the timeout-variable. In case of a time out, you will find the value of the variable will be zero. You just need to add some code that can check this:

      unsigned int timeout=1000;
      while (RB0==0 && (--timeout > 0));
      if (timeout==0)
      	// loop ended because of time out
      	// loop ended because RB0 became "1"

With the code above the total number of cycles equals (timeout-1). So when you assign the number 1000 to the timeout variable, the loop will be cycled 999 times.

Using an even longer time-out

The sample above used a timeout variable of the (unsigned) integer-type. You can assign a value of up to 65535 to this variable. Some applications will require an even higher time-out value. This is possible if we replace the int data type by a long data type. A long variable uses 32 bits to represent the integer value. This means we can set the variable to a very high number: 4,294,967,295 to be exact. Now let's rewrite our loop:

  	unsigned long timeout=4294967295;
  	while (RB0==0 && (--timeout > 0));

How long does it take for the loop to time-out?

Now we just designed a loop with a time-out function. One big question emerges: how much time does it take for the loop to timeout?

The answer to this question is rather complicated. It depends on a number of factors:

  1. The running frequency of the PIC microcontroller
  2. The value you assign to the timeout variable
  3. The true size/execution time of each loop

The C-language sample program will be compiled and converted to machine-code, which can be understood by the PIC-microcontroller. The generated machine code depends on the used compiler (and the used compiler settings). So it's almost impossible to predict the actual time-out.

To give you an idea of the actual time-out, I wrote a little javascript application that calculates your own timeout loop. All you need to do is to enter the PIC's frequency and the desired time-out:

PIC Frequency (MHz)
desired time-out

Important notice

I wrote this tool by investigating the machine-code that was generated from the C-language code above. This tool is far from accurate. There might be a significant difference between the calculated time-out and the actual time-out you will find when you implement this code into your own application.

Please do not completely rely on this code!

The alternative: time-out with a timer

If timing is critical, you shouldn't be using the code from above. Alternatively you could use one of the build-in timers of the PIC microcontroller. Using a timer offers a lot of advantages, because it's very easy to predict the duration of the timer.

The High-Tech C source code below demonstrates a possible way to implement a waiting loop with a running background timer. The program assumes a PIC 16F628A with a 4 MHz oscillator, a switch (towards VCC) on port RB0 and an output LED on port RB3. The program has a loop that waits for a pulse on the port RB0. The background timer makes sure the loop times-out after a certain time. The LED will light up continuously when a pulse was detected, it will flash when the loop timed-out.

The time-out duration depends on the frequency of the PIC, the timer1's initial value (TMR1H and TMR1L) and the timer1's prescaler setting (T1CKPS0 and T1CKPS1). In my example the time-out is approximately 0.524 seconds: 1 Ás * 8 * 65536. (One instruction cycle takes 1 Ás, the prescaler is set to 8 and the timer1 is 16 bit so it has 65536 possible values).

Copyright ©1998-2022 Vanderhaegen Bart - last modified: November 01, 2013