You are on page 1of 14

Keil Compiler

Lecture Notes #2
We are going to look at, analyze and hopefully understand the structure of a Keil
C program.

Several basics we need to understand.

DATA TYPES
The C51 supports the following data types:

Data Type Bits Bytes Value Range


Bit 1 0 to 1
Signed char 8 1 -126 to +127
Unsigned char 8 1 0 to 256
Enum 16 2 -32768 to +32767
Signed short 16 2 -32768 to +32767
Unsigned short 16 2 0 to 65535
Signed int 16 2 -32768 to +32767
Unsigned int 16 2 0 to 65535
Signed long 32 4 -2147483648 to +2147483647
Unsigned long 32 4 0 to 4294967295
Float 32 4 +/-1.7549E+38 to +/-3.402823E+38
Sbit 1 0 to 1
Sfr 8 1 0 to 256
Sfr16 16 2 0 to 65535

The sbit, sfr, and sfr16 data types are included to allow access to the special
function registers that are available on the 8051.

For example, the declaration: sfr P0 = 0x80, declares the variable p0 and assigns
it the special function address of 0x80. This is the address of PORT 0 on the
8051.

The C51 compiler automatically converts between data types when the result
implies a different data type. For example, a bit variable used in an integer
assignment is converted to an integer.

1
Memory Types

The C51 compiler supports the architecture of the 8051 and its derivatives and
provides access to all memory areas of the 8051. Each variable may be explicitly
assigned to a specific memory space.

Following are the memory types supported by the C51 compiler:

Memory Type Description


Code Program memory (64 Kbytes; accessed by opcode MOVC @A+DPTR
Data Directly addressable internal data memory; fastest access to
variables (128 bytes).
Idata Indirectly addressable internal data memory; accessed across the
full internal address space (256 bytes).
Bdata Bit-addressable internal data memory; allows bit and byte access
(16 bytes).
Xdata External data memory (64Kbytes); accessed by opcode MOVX
@DPTR
Pdata Paged (256 bytes) external data memory; accessed by opcode
MOVX @Rn

Accessing the internal data memory is considerably faster than accessing the
external data memory. For this reason, you should place frequently used variables
in internal data memory and less frequently used variables in external data
memory.

By including a memory type specifier in the variable declaration, you can specify
where variables are stored.

As with the signed and unsigned attributes, you may include memory type
specifiers in the variable declaration. For example:

Char data var1; ; Data type char, memory type data


Char code text [] = “Enter Parameter;”;
Data type char, memory type code
Unsigned long xdata array [100]
Float idata x,y,z
Uinsigned int pdata dimension
Char bdata flags

2
If the memory type specifier is omitted in a variable declaration, the default or
implicit memory type is automatically selected. Function arguments and automatic
variables which cannot be located in registers are also stored in the default
memory area.

MEMORY MODELS
The memory model determines the default memory type used for function
arguments, automatic variable, and variables declared with no explicit memory
type. You specify the memory model on the command line using the SMALL,
COMPACT, and LARGE control directives.

SMALL: Total RAM 128 bytes


Restricting with the 8051/31. Will support code sizes up to about 4K but
a constant check must be kept on stack usage. The number of global
variables must be kept to a minimum to allow the linker OVERLAYER to
work to best effect. With the 8052/32 versions, the manual use of the
128 byte IDATA area above 80H can allow applications up to about 10-
12K but again stack position must be kept in mind.

Compact Total RAM 256 bytes off-chip, or 128 or 256 bytes on-chip
Suitable for programs where, for example, the on-chip memory is applied
to an operating system. The compac5t model is rarely used on its own
but more usually in combination with the SMALL switch reserved for
interrupt routines.

Especially useful for programs with a large number of medium speed 8 bit
variables, for which the MOVX A, @R0 is very suitable.

Large Total RAM up to 64Kb, 128 or 256 on-chip


Permits slow access to a very large memory space and is perhaps the
easiest model to use. Again, not often used on its own but in combination
with SMALL. As with COMPACT, register variables are still used and so
efficiency remains reasonable.

Specify Model size with directive:

#PragmaSMALL

3
REG51.H
Header file for 8051.
/* BYTE Register */ /* SCON */
sfr P0 = 0x80; sbit SM0 = 0x9F;
sfr P1 = 0x90; sbit SM1 = 0x9E;
sfr P2 = 0xA0; sbit SM2 = 0x9D;
sfr P3 = 0xB0; sbit REN = 0x9C;
sfr PSW = 0xD0; sbit TB8 = 0x9B;
sfr ACC = 0xE0; sbit RB8 = 0x9A;
sfr B = 0xF0; sbit TI = 0x99;
sfr SP = 0x81; sbit RI = 0x98;
sfr DPL = 0x82; /* BIT Register */
sfr DPH = 0x83; /* PSW */
sfr PCON = 0x87; sbit CY = 0xD7;
sfr TCON = 0x88; sbit AC = 0xD6;
sfr TMOD = 0x89; sbit F0 = 0xD5;
sfr TL0 = 0x8A; sbit RS1 = 0xD4;
sfr TL1 = 0x8B; sbit RS0 = 0xD3;
sfr TH0 = 0x8C; sbit OV = 0xD2;
sfr TH1 = 0x8D; sbit P = 0xD0;
sfr IE = 0xA8; /* TCON */
sfr IP = 0xB8; sbit TF1 = 0x8F;
sfr SCON = 0x98; sbit TR1 = 0x8E;
sfr SBUF = 0x99; sbit TF0 = 0x8D;
sbit TR0 = 0x8C;
sbit ET0 = 0xA9; sbit IE1 = 0x8B;
sbit EX0 = 0xA8; sbit IT1 = 0x8A;
/* IP */ sbit IE0 = 0x89;
sbit PS = 0xBC; sbit IT0 = 0x88;
sbit PT1 = 0xBB; /* IE */
sbit PX1 = 0xBA; sbit EA = 0xAF;
sbit PT0 = 0xB9; sbit ES = 0xAC;
sbit PX0 = 0xB8; sbit ET1 = 0xAB;
/* P3 */ sbit EX1 = 0xAA;
sbit RD = 0xB7; sbit INT0 = 0xB2;
sbit WR = 0xB6; sbit TXD = 0xB1;
sbit T1 = 0xB5; sbit RXD = 0xB0;
sbit T0 = 0xB4;
sbit INT1 = 0xB3;

4
Example 1

Write a program that reads data in from 8 switches connected to P0,


stores the readings in a 10-byte array, shows the most recent
reading on 8 LEDs connected to P2, and waits 1/10 second to repeat
the process. Write the program first in assembly language then in C.
Part 1 Assembly Language
EXTRN CODE (MSEC)
MYCODE SEGMENT CODE
MYDATA SEGMENT DATA

RSEG MYDATA
ARRAY: DS 10

RSEG MYCODE
START: MOV R0,#ARRAY ;SET ARRAY POINTER
AGAIN: MOV ACC,P0
MOV P2,ACC
MOV @R0,ACC ;STORE IN ARRAY
MOV R2,#0 ;HIGH BYTE
MOV R1,#100 ;LOW BYTE
LCALL MSEC
INC R0 ;POINT TO NEXT LOC.
CJNE R0,#ARRAY+10, AGAIN ;END?
SJMP START ;RESET TO START
END
Part 2 “C”
#include <reg51.h>
void msec (unsigned int);
void main() {
unsigned char array [10];
unsigned char I;
while (1) {
for (I=0; I<=0; I++){
array[I]=p2=p0;
msec(100)
}
}
}

5
Example 2

This example counts up in binary and displays the result on eight LEDs connected
to port 1. The data is displayed with about 1 second delay between each output.

#include <reg51.h>
/* Function to wait about 1 second*/
void wait_a_second()
{
unsigned int x;
for(x=0;x<3300;x++);
}

/* Start of main program */


main()
{
int LED=1 /*initialize count to 1*/
for(;;) /*start of endless loop*/
{
P1=~LED; /*invert and output*/
LED++ /*increment the count*/
Wait_a_second(); /*wait about a second*/
}
}

6
Example 3
This example is a dice simulator project. Seven LED’s are connected to port 1 of
the microcontroller. A push-button switch is connected to bit 0 of port 3 and
when this switch is depressed, a new number is obtained between 1 and 6 and the
corresponding LED’s are turned on to simulate a dice. After 2 seconds delay, all
LED’s are turned off and the user can throw a dice again.

#include <reg51.h>
#define ALL_OFF 0xFF

sbit button = P3.0 /*bit p3.0 is the push-button*/

/*function to delay about a second*/


void wait_a_second()
{
unsigned int x;
for(x=0;x<33000;x++);
}
/*start of mian program*/
main()
{
int DICE=0 /*initialize to 0*/
int DICE_ARRAY[6]={0x08,0x14,0x1c,0x63,0x6b,0x77};

for(;;) /*start of loop*/


{
if(button==0) /*button pressed?*/
{
P!=~DICE_ARRAY[DICE-1];
wait_a_second(); /*wait 2 seconds*/
wait_a_second();
P1=ALL_OFF; /*turn off LED’s*/
}
else
{
DICE++; /*inc DICE*/
If(DICE==7)DICE=1; /*set to 0 if 7*/
}
}
}

7
Example 4: Implementing a 4 bit Counter using an 8051 and
Interfacing it to an LCD
(Modified from example from Prof. Frank Vahid’s web site)
Purpose:
In this example, you will learn how to write a simple C program for 80X51 micro-
controller, compile it using C51 compiler, and emulate it on an emulator. The
program will be used to control a simple 4-bit up-down counter, capable of
counting from 0 to 15. At each step the count should be displayed in decimal
format on the LCD.
Assignment:
In this lab :
• You will design a 4-bit Up-Down counter using the C programming language
for the 8051 micro-controller and display the count on an LCD.
• You will then test and run your program on the 8051.
1.The 4 bit counter has the following functionality:
• The counter has the following input pins :
a.Reset : when high resets the counter dataout to ``0000''
b.Updown : decides whether the counter counts up or down.
c.Load : makes the counter count from the 4 bit input Datain
d.Datain : which is a 4 bit input count
• The counter has a 4 bit Dataout to reflect the count.
• The count has to be sent to the LCD and displayed in decimal format.
Apparatus Required:
1.4.7k resistors(8)
2.1k resistor(1)
3.DIP switch
4.LCD
5.5V power supply
6.8051 Development system

8
Schematic:

9
10
Program:

#pragma SMALL DB OE
#include <reg51.h>
#include "io.h"

/* P0, P1, P2 and P3 are predefined port names and are bit addressable */

sbit reset = P0^4; /* bit 4 of Port 0 */


sbit up_down = P0^5;
sbit load = P0^6;
sbit Start_LCD = P3^7; /* bit 7 of Port 3 */

/* Delay function */
void delay() {

int i, j;

for(i=0; i<1000; i++)


for(j=0; j<100; j++)
i = i + 0;
}

/* Function to output the decimal value of the count on the LCD */


void PrintInt(unsigned char i) {
char ch[4];

/* Write code to convert the count to a string value and use the
PrintString function provided in io.c */

PrintString(ch);
}

void main(void) {

unsigned char count = 0;

InitIO(); /* Initialize the LCD */


while (1) {
if (Start_LCD == 1) {
ClearScreen();
PrintString("Ready...");
delay();
11
}
else if (reset == 1) {

/* Output 0 on the LCD */

}
else if (load == 1) {

/* Output the current value of Datain on the LCD */

}
else {
/* Check the Up/Down pin for 1 or 0 count up or down
accordingly. Display each value on the LCD */
}
}
}

EXAMPLE 5

/* CIO.C */
/* PROGRAM TO LEARN THE KEIL C DEVELOPMENT ENVIRONMENT
Program counts up Port-2 when any key is pressed.
Then counts down when "00" is pressed.
Then returns to counting up when "FF" is pressed.
Program prints to screen using short ASCII input and output routines. */

#pragma DEBUG OBJECTEXTEND CODE

#include <reg51.h>
/* #include <stdio.h> */

/***************************/
/* main program */
void delayloop(unsigned int); /* settable delay loop */
unsigned int getchr(void); /* read serial port */
void sndchr(unsigned int);

void main(void) /* execution begins here after stack init */


{
unsigned int intvar, carvar;
12
unsigned int result = 0x41;
unsigned int lch, rch = 0x41;

SCON = 0x50; /* mode 1, 8-bit uart, enable receiver */


TMOD = 0x20; /* timer 1, mode 2, 8-bit reload */
TH1 = 0xF3; /* reload value for 2400 baud */
TR1 = 1; /* timer 1 run */
TI = 1; /* set TI to send first char of uart */

while (1) /* main loop */


{
intvar = 00; /* set P2 = 00 */
P2 = intvar;
while (!RI) {} /* Wait for serial input */
carvar = getchr(); /* get char from serial port */
sndchr(carvar);
while (1)
{
if(result == 0x41) intvar++; /* increment after first
keystroke */
if(result == 0x46) intvar--; /* decrement P2 if "FF" */
if(result == 0x30) intvar++; /* increment P2 if "00" */
P2 = intvar; /* send intvar to I/O port */
delayloop(0xcc);
delayloop(0x11);
carvar = getchr(); /* get char from serial port */
if(carvar != 0x41) /* shift & save if new keystroke */
{
lch = rch;
rch = carvar;
sndchr(carvar);
}
if((lch == 0x46)&&(rch == 0x46)) /* check for "FF" */
{result = 0x46;}
if((lch == 0x30)&&(rch == 0x30)) /* check for "00" */
{result = 0x30;}
}
}
}

/* Delay loop */
void delayloop(x)
13
unsigned int x;
{
unsigned int loop1, loop2;
for (loop1 = 01; loop1 <=x; loop1++)
{
for (loop2 = 01; loop2 <=0xff; loop2++)
{}
}
}

/* Read whatever is in serial port buffer */


/* Return "A" if re-entered before next keystroke */
unsigned int getchr(void)
{
unsigned int chr, ch1;
ch1 = SBUF; /* get character */
chr = ch1 & 0x7f; /* mask off 8t bit */
if(!RI) {chr = 0x41;} /* return "A" if no new keystroke */
RI = 0; /* clear serial status bit */
if(chr == 0x0d)
{
sndchr(chr);
chr = 0x0a;
}
return(chr);
}

/* Send a character to the serial port */


void sndchr(x)
unsigned int x;
{
SM1 = 0; /* clear the tx buffer full flag */
SBUF = x;
while (SM1){}
}

14

You might also like