Lecture: 4
Objectives:C looping structures, for and while.

C looping statements

Loops repeat the execution of a collection of statements (called the body) until some condition is met. Today we will examine two of the more useful looping structures in C, the for and while loops.

For-loops

A for-loop generally is used when you need a counting variable along with iteration. The counting variable is often referred to as the loop variable. The for statement itself has three components separated by semicolons as shown in the following figure and a body.




The flow-chart to the right of the for-loop shown in the figure above describes the relationship between these four statements graphically. Hopefully you can put together these pieces to figure out that the for-loop given at left in the figure above executes the body 10 times.

Let's explore the operation of another for-loop with the following example.
    uint8_t i;
    uint8_t sum = 0;
    uint16_t prod = 1;

    for (i=0; i<10; i++) {
	sum += i;
	if (i>0) prod *= i;
	// now record value of i, sum and prod in the table
    } // end for
Fill in the following table with the values of the three values at the line indicated in the program above. Make sure to respect the data type!
i sum prod
0    
1    
2    
3    
4    
5    
6    
7    
8    
9    
If your for-loop is acting strangely, make sure that you have not inadvertently done something to the loop variable in the body of your for-loop. A C compiler would have no problem with allowing you to decrement the i variable (subtracting 1 from it) in the body of the for-loop above.

Count down loops

There will be times when you need a index variable that goes from a large value to a small value. This is especially common when working with arrays. Let's look at an example program to see how to make a for-loop count down.

The for loop i the following code snippet initialize the loop counting variable i to 10. The comparision will stop the for-loop iterating when the index variable i equals 0. The trick to making the count down work is the decrement operation i--. This operator decrements i, subtracts 1, on every iteration of the loop. So, what would the value of sum equal to after the execution of the following code snippet?
sum = 10 + 9 + … 1 = 55.
    uint8_t i;
    uint8_t sum;

    for (i=10; i>0; i--) {
        sum += i;
    } // end for

Infinite loops and the superloop

Before we leave this section there is one very special for-loop that I would like to present before we leave.
    for(;;) {
	body;
    }    
This for-loop has no initialization, condition or increment statements. The most important in this case is that it lacks a condition. When left blank, the condition field is assumed to be TRUE. Hence, this for-loop never terminates. This is an infinite loop, meaning that once execution enters this for-loop, the program will forever execute the body. In your previous programming courses, you probably would avoid a structure like this because you would want your program to end so that the computer could do other things. Well in our environment, our computer is embedded into an application and has nothing else to do expect the application we are designing it into. For example, imagine if a vending machine with an embedded processor reached the end of its program and then just stopped running! This would not be acceptable, so we design the main program as an infinite loop, checking for money, dispensing beverages and then going back to check for money.

The vending machine is a good example of the structure that we will use for most of our programs this term, the super-loop. A super-loop is an infinite loop that contains a set of tasks that are performed over and over again. For eample
    for(;;) {
	if (current_temperature > highSetPoint) {
	    TURN_ON_COMPRESSOR();
	}

	if (current_temperature < lowSetPoint) {
	    TURN_OFF_COMPRESSOR();
	}

	if (coinDeposit == TRUE) {
	    switch(grade) {
		case NICKLE:
		    total += 5;
		    break;
		case DIME:
		    total += 10;
		    break;
		case QUARTER:
		    total += 25;
		    break;
	    } // end switch
	    coinDeposit = FALSE;
	}

	if (total >= 100) {
	    DISPENSE_SODA();
	    total = 0;
	}

    } // end super-loop
It's pretty easy to read through this list of tasks and figure out what the vending machine is doing. In the case of a super-loop you are expecting that the loop is executed quickly enough that the user will sense that the machine acts instantously to any input, when in fact we know that the machine is doing one thing at a time.

Later in the semester, we will add interrupts to the super-loop software architecture so that the microcontoller can really do several things at the same time.

While loops

While loops are structurally more simple than for-loop, having a single condition, that while true, allows the body of the while-loop to execute. So, for example, the following while loop produces the same iterative behavior as the first for-loop.
    uint8_t i;
    uint8_t sum = 0;
    uint16_t prod = 1;

    i = 0;
    while(i < 10) {
	sum += i;
	if (i > 0) prod *= i;
	i += 1;
    }
However, a while-loop like this is of little practical use because this loop structure is more naturally realized using a for-loop. However, there is one very important use of while-loop that we will use extensively and that is to wait for some external event to happen.

Delay loops

A delay loop is a loop constructed to have the embedded processor wait for some event. Lets look at a concrete example that we will work with in lab 2, controlling an LED with a push button. To accomplish this task we will need to make some assumption here that will be justified later on.
First, we will connect our push button to our PIC and that associated with this push button we have a variable called "buttonPressed". This variable is TRUE when the user presses on the push button and FALSE when the user is not pressing the button.
Second, we will connect an LED to out PIC and that associated with the LED is a variable called "LED". Assigning this variable the value of 0 will turn the LED off, assigning a 1 will turn the LED on.
Finally, we need to recognize that the microcontroller is executing the instructions many millions of times faster than a user can press or release the button. With these assumptions in place lets look at a practical delay loop that you will see many times in our course.

1.    LED = 0;				// turn off the LED
2.    for(;;) {
3.    	while(buttonPressed == FALSE);	// wait for a button press
4.    	while(buttonPressed == TRUE);	// wait for a button release
5.	LED ^= 1;			// toggle the LED
6.    }


Let's walk through the program from top to bottom. To facilitate this discussion, I have added line numbers in the far left; please understand that these are not actually part of the program.
Line 1 turns the LED off. While not strictly part of the problem statement, its often a good idea to put indicators like LEDs into a know initial state at the start of a program.
Lines 2-6 form an infinite loop. Meaning that our computer will forever be checking the state of the button and turning the LED on and off.
Line 3 is a while-loop that executes its (empty) body while the button is not pressed. There are two important points to make here. First, this while loop may get stuck executing this while loop many millions of times before the button is pressed. This is because the PIC is running at 64 MHz, meaning that its executing 64 million (assembly) instructions per second. Hence, it can do a lot of checks every second. Second, while our program is executing this while loop it is doing absolutely nothing except checking that button. This is the quintessential delay loop, synchronizing the execution of our program to the user's input by waiting and doing nothing until the user performs some task. You rarely see these types of statements in other programming classes because variables in those classes only change under your programs control, but in this class we will have variables that change based on actions performed outside your program.
Line 4 is a while-loop that executes its (empty) body while the button is pressed. Once again, the PIC is executing statements millions of times faster than the user can release the button. Hence, our program needs to wait until the button has been released before continuing.
Line 5 toggle the state of the LED after the button has been pressed and then released.

Test your understanding

You can find the solutions embedded in the "source code" for this web page by right mouse clicking on this web page and selecting "view source". The solutions are in HTML comments.
  1. Write a for loop that starts at 3, counts up by 5 and ends before reaching 105.
  2. Write a for loop that counts up from 1 to 4096 (inclusive) by powers of 2.
  3. Write a for loop that counts down from 88 to no less than 42 by 2's.
  4. Write a loop that counts up by one while a button is being held down. Since the while-loop would be executing so much faster than the user could respond this would make a reasonablly good random number generator. The counter should be type uint8_t. I would expect that this counter variable would roll-over many, many times while the button is pressed. This is not a problem as again, we are expect to end up with a random number.
  5. Write a loop that counts up by one everytime a button is pressed.
  6. A linear feedback shift register (LFSR) is a general techanique that has been used with great success in generating pseudo-random number. A pseudo-random number is a number that looks random to someone who does not know how they are produced, but is in fact generated by a deterministic procedure (an algorithm).

    A pseudo-random number generator starts with a seed valuye (any non-zero number) and generates a sequence of numbers that look like they have no relationship to one another. To generate a sequence of pseudo-random 16-bit numbers using an LFSR with current varX16. To do this:
    • Step 1: xor the bits in positions 15,13,12,10 and 0 (start indexing your bits starting at position 0),
    • Step 2: shift varX16 left one bit,
    • Step 3: put the xor bit into the LSB of varX16.
    Write a program to generate pseudo-random numbers using a LFSR.
  7. Embedded C programs will let you get away with some pretty weird stuff. Sometimes this is really helpful, but when you are starting out, this will allow you to make some pretty horrible mistakes. The following program will run and terminate. What value will the count variable have when it does and explain how it got that way.
        uint8_t i, count = 0;
        for(i=200; i>100; i++) {
    	count += 1;
        }
    
  8. Here is another weird one. What does count equal when the loop terminates?
        uint8_t i, count = 0;
        for(i=200; i != 100; i++) {
    	count += 1;
        }
    
  9. Here is another weird one. Does the loop terminate and if so, what does count equal when it does?
        uint8_t i, count = 0;
        for(i=200; i <= 300; i++) {
    	count += 1;
        }
    
  10. Here is another weird one. Does the loop terminate and if so, what does count equal when it does?
        uint8_t i, count = 0;
        for(i=200; i != -1; i++) {
    	count += 1;
        }
    
  11. Here is an interesting loop. What does count equal when the loop terminates?
        uint8_t i, count = 0;
        for(i=43; i != 171; i*=3) {
            count += 1;
        }