OPTIONS: An Exploration of Possibilities

EE/CS: Keil C Programming Notes

Summer 2002

This handout is a tutorial on how to write a program for the University of Evansville 8051 controller board (Version 6) using Keil C uvision-2 and Philips WINISP version 2.26. It assumes you have logged into a computer with these programs.

Creating a Keil C program

Keil C is launched by double-clicking on the icon on that says Keil uvision2. After it comes up, you should maximize the window if it is not full size. If there are already files open, go to the Project menu and select Close Project.


Every time you want to create a program and download it into the controller board, you must create a project that tells the compiler which files belong to your program, write the program, then compile and link the program. This section will explain each of these steps. The next section will explain how to download the program to the controller board.

Setting up a project

To set up a project, do the following steps:

  1. Create a folder on the local hard drive (C:) for your project files. For the LEGO project, you will need the robotics library files. These are available by web browser at
    
         http://csserver.evansville.edu/~lego101
    
    under the OPTIONS 2002 heading. Save robotics6b.h and robotics6b.c to your project folder by right-clicking on the link and choosing Save Target As (in Internet Explorer).

    The LEGO robotics library is a collection of routines that give the UE controller board an API (Application Programmer's Interface) for using it as a robot controller. The interface is found in robotics6b.h. The implementations of these routines and some notes are found in robotics6b.c. You are welcome to read these files, and if you want to know more about this code just ask an instructor.

  2. Keil C requires a file to exist before you can add it to your project, so if you do not have a main program file, you need to create it first. Do this going to the File menu and choosing New. This will give you an untitled, empty edit window. Save the empty file using File$\vert$Save As into the project folder. For this tutorial, use example.c.

  3. Click on the Project menu and choose New Project. Set the directory to your project folder. Set the name of the project. For this tutorial, use example. The software will automatically add a .prj extension. Click OK.

    A Select Device dialog box will appear. Double-click on Philips, then choose 89C51RD2. (This is processor chip is installed on the controller board. If this chip is not listed choose 89C51RD+.) Click OK.

  4. In the left window will be a list of files in your project. Currently, there are none. Right click on the Source Group 1 node and choose Add Files to Group. This will bring up the Add Files dialog box. Find the project folder with your files.

    Select the C source files you want to add. For this project you will always need the source file with your main program in it, example.c for this tutorial, and robotics6b.c. (You do not add robotics6b.h, but you need to have this file in your project folder.)

    Click on Close to get rid of the Add Files dialog box.

  5. One last step in project creation is to tell compiler to produce a HEX file for downloading. Do this by right-clicking on the Target 1 node in the left window and choose Options for Target 1. Click on the Output tab, check Create HEX file, and click OK.

Writing a program

You can open any of the files you have added to your project by double-clicking in the file list window or using File$\vert$Open. For this tutorial, you can double-click example.c. Here is the example program that you can type into the edit window.


/* ------------------------------------------------------------------------
File: example.c
This program demonstrates motors, LEDs, and buzzer
---------------------------------------------------------------------------*/

#include "robotics6b.h"

/* Constant declarations */
#define DELAY_TIME 20   /* about 1 sec */
#define LIGHT_PULSE 20  /* About 1 sec */

void main (void)
{ 
   /* Variable declarations */
   unsigned char i;

   /* Initialization */
   InitializeMotors();
   InitializeIO();
   Delay (DELAY_TIME);  /* Wait about 1 sec */

   while (1)  /* Repeat forever */
   {
      /* Test LEDs */
      for (i = 11; i <= 14; i++)   /* 4 middle ports */
      {
         Beep(1);
         SetOutputPort(i, LOW);    /* Turn on LED i */
         Delay (LIGHT_PULSE);
         SetOutputPort (i, HIGH);  /* Turn off LED i */
         Delay (LIGHT_PULSE);
      }
   
      /* Forward */
      Beep (2);
      SetMotor (1, 255);
      SetMotor (2, -255);
      Delay (DELAY_TIME*5);
      AllStop();

      /* Left Turn */
      Beep(3);
      SetMotor (1, 255);
      SetMotor (2, 255);
      Delay (DELAY_TIME*2);
      AllStop();

      /* Reverse */;
      Beep(2);
      SetMotor (1, -255);
      SetMotor (2, 255);
      Delay (DELAY_TIME*5);
      AllStop();

      /* Right Turn */;
      Beep(3);
      SetMotor (1, -255);
      SetMotor (2, -255);
      Delay (DELAY_TIME*2);
      AllStop();

      Beep (5);
      Delay (DELAY_TIME*2);
   }
}

Building a program

Once we have written a program, we need to build it. Go to the Project menu and choose Build Target. The window at the bottom of the screen should inform you of the progress being made.


First it will compile your source files. If you have any syntax errors, the window will contain a list of errors and the line numbers. Double-clicking on an error message will cause the corresponding line in the source edit window to be highlighted. Correct any errors and do Project$\vert$Build Target again.


If the compilation phase is successful, an object file will be created (with .obj extension) for each source file. The compiler also produces a listing file (with .lst extension) for each source file. Then the system will link them into a combined hex file (with .hex extension) suitable for downloading. In this tutorial, the files robotics6b.obj, robotics6b.lst, example.obj, example.lst, and example.hex are created. You may ignore the warnings it gives about uncalled segments being ignored.

Loading a program into the controller board

Once our program has been compiled into a HEX file, we need to download it into the controller board. For this step we need to use a different program called WINISP. It is probably easiest to minimize Keil C at this time.


To load our program into the controller board we need to following steps:

  1. The controller board needs to be plugged into the computer. Switch it on (the red LED will come one) and switch it into program mode (green LED will come on). Then push the reset button.
  2. The WINISP program can be launched by going to the Start Menu, then Programs, then Winisp, then WINISP. (Or use the shortcut if there is one.)
  3. Set the WINISP parameters. For Chip, choose 89C51RD2. For Port, choose Com 1 (or whichever com port the board is connected to). Type in 12 for Osc(illator).
  4. Under Misc, click on Read. Vector should be FC and Status should be 0. If they are not, change them and click on Write. If they are correct, you do not need to do anything.
  5. Before we load our program, we need to erase any program that is already in the processor. Do this by clicking on Erase Blocks. In the dialog box, click on the first 8K block (our programs are short), then ERASE!. The window should close when its done.
  6. Now we load the program into WINISP by clicking on Load File. Find the project folder with your program, select example.hex, and click OK.
  7. Finally, click on Program Part. This will download the file into the processor.
To have the controller board run the program, disconnect the cord to the computer, press the reset button on the back of the display, then switch the board into run mode (the green LED will turn off) and press the reset button.


If your vehicle does what is expected, great! Otherwise, compare the behavior with your program, make changes using Keil C, and repeat the build and load processes. (Sometimes the program is ``right'' and the hardware is wired ``wrong,'' so be sure to ask an instructor if you do not understand why your vehicle behaves the way it does.)


When you are done, exit WINISP by clicking on Close. In Keil C, close your project by using Project$\vert$Close Project, then exit using File$\vert$Exit.


To work on this program later, start up Keil C again. If you did not close your project previously, it will probably load your project back. If not, go to the Project menu and choose Open Project. Set the directory to your project folder, and select example.prj. To open the files in the project, you can double-click in the file list.

Another test program


/* ------------------------------------------------------------------------
File: atodtest.c
This program demonstrates A to D converter and LEDs.
---------------------------------------------------------------------------*/

#include "robotics6b.h"

/* Constant declarations */
#define DELAY_TIME 20   /* about 1 sec */

void main (void)
{ 
   /* Variable declarations */
   unsigned char channel0, channel1;  /* A to D channels */

   /* Initialization */
   InitializeMotors();
   InitializeIO();

   while (1)
   {
      Delay (DELAY_TIME);
      Beep (1);
      channel0 = GetAtoD (0);
      channel1 = GetAtoD (1);
      Delay (DELAY_TIME*2);

      if (channel0 > channel1 + 20)
      {
         Beep(2);
         SetOutputPort (11, LOW);
         SetOutputPort (12, HIGH);
      }
      else if (channel1 > channel0 + 20)
      {
         Beep(3);
         SetOutputPort (11, HIGH);
         SetOutputPort (12, LOW);
      }
      else
      {
         Beep(4);
         SetOutputPort (11, LOW);
         SetOutputPort (12, LOW);
      }

      Delay (DELAY_TIME*2);
      if ((channel0 < 128) && (channel1 < 128))
      {
         Beep(2);
         SetOutputPort (13, HIGH);
         SetOutputPort (14, HIGH);
      }
      else if ((channel0 >= 128) && (channel1 >= 128))
      {
         Beep(3);
         SetOutputPort (13, LOW);
         SetOutputPort (14, LOW);
      }
      else if ((channel0 < 128) && (channel1 >= 128))
      {
         Beep(4);
         SetOutputPort (13, HIGH);
         SetOutputPort (14, LOW);
      }
      else  /* channel0 >= 128 && channel1 < 128 */
      {
         Beep(5);
         SetOutputPort (13, LOW);
         SetOutputPort (14, HIGH);
      }
   }
}



Converted using latex2html on Wed Jun 26 13:35:26 CDT 2002