seminar report keil

23
KEIL C Submitted by Suraj CR S8 EC SNGCE The use of C language to program microcontrollers is becoming too common. And most of the time its not easy to buld an application in assembly which instead you can make easily in C. So It’s important that you know C language for microcontroller which is commonly known as Embedded C. As we are going to use Keil C51 Compiler, hence we also call it Keil C. EMBEDDED SYSTEMS ABSTRACT : Embedded system encompasses a variety of hardware and software components, which perform specific functions in host systems. Embedded systems have become increasingly digital with a non-digital periphery and therefore, both hardware and software co-design is relevant. Majority of computers are used in such systems to distinguish them from standard main frames, workstations and pc’s. Advances in microelectronics have made possible applications that would have been impossible without an embedded system design. Embedded system applications have virtually entered every sphere of our lives embedded systems cover a broad of products that generalization is difficult. INTRODUCTION:

Upload: surangma-parashar

Post on 29-Nov-2014

249 views

Category:

Documents


10 download

TRANSCRIPT

Page 1: Seminar Report Keil

KEIL C Submitted by

Suraj CR

S8 EC

SNGCE

The use of C language to program microcontrollers is becoming too common.

And most of the time its not easy to buld an application in assembly which instead you

can make easily in C. So It’s important that you know C language for microcontroller

which is commonly known as Embedded C. As we are going to use Keil C51 Compiler,

hence we also call it Keil C.

EMBEDDED SYSTEMS

ABSTRACT:

Embedded system encompasses a variety of hardware and software

components, which perform specific functions in host systems. Embedded systems

have become increasingly digital with a non-digital periphery and therefore, both

hardware and software co-design is relevant. Majority of computers are used in such

systems to distinguish them from standard main frames, workstations and pc’s.

Advances in microelectronics have made possible applications that would have been

impossible without an embedded system design.

Embedded system applications have virtually entered every sphere of our lives

embedded systems cover a broad of products that generalization is difficult.

INTRODUCTION:

Page 2: Seminar Report Keil

An embedded system is a microprocessor- based system that is incorporated into a

device to monitor and control the functions of the components of the device. They are

used in many devices. Developments in microelectronics, processor speeds and

memory elements have resulted in power embedded systems with a number of

applications.

This paper seeks differences between embedded computer design and desktop design,

which also presents design challenges.

DEFINITION:

An embedded system is a type of computer system or computing device,

which performs a dedicated function and/or is designed for use with a specific

embedded software application.

COMPONENTS OF AN EMBEDDED SYSTEM:

Embedded systems have the following components.

PROCESSOR:

A processor fetches instructions from the memory unit and executes the

instructions. An instruction consists of an instruction code and the operands on which

the instruction should act upon. The format of instruction code and operands of a

processor is defined by the processor’s instruction set. Each type of processor has its

own instruction set. Performance of the system can be improved by dedicated

processors, which implement algorithms in hardware using building blocks such as

hardware counters and multipliers.

Some embedded processors have special fuzzy logic instructions. This is because

inputs to an embedded system are sometimes better represented as fuzzy variables.

Page 3: Seminar Report Keil

For instance, the mathematical model for a control system may not exist or may involve

expensive computing power. Fuzzy logic can be employed for such control systems to

provide a cost-effective solution.

MEMORY:

The memory unit in an embedded system should have low access time and high

density. (A memory chip- has greater density if it can store more bits in the same

amount of space. Memory in an embedded system consists of ROM and RAM .The

contents of ROM are non-volatile while RAM is volatile. ROM stores the program code

while RAM is used to store transient input or output data. Embedded systems generally

do not possess secondary storage devices such as magnetic disks. As programs of

embedded systems are small there is no need of virtual storage.

PERIPHERALS:

Peripherals are input and output devices connected to the serial and parallel

ports of the embedded system. Serial port transfers one bit at a time between the

peripheral and themicroprocessor. Parallel ports transfer an entire word consisting of

many bits simultaneously between the peripheral and the microprocessor.

Programmable interface devices that act as an interface between microprocessor

with peripherals provide flexibility since they can be programmed to perform I/O on

different peripherals. The microprocessor monitors the inputs from peripherals and

performs actions when certain events occur. For instance, when sensors indicate the

level of water in the washtub of a washing machine is above the present level, the

microprocessor starts the wash cycle.

Page 4: Seminar Report Keil

Introduction to the Keil 8051 ‘C’ Compiler

We will use the Keil ‘C’ cross compiler to develop our 8051 programs.

The Keil ‘C’ Compiler Directory Structure is as follows

C:\C51V4

\BIN : This contains the compiler .exe files

\INC : This contains the header files

\LIB : This contains the object libraries

\WORKING : All user programs reside here

\A51 : Assembler directory used by comp

Program Development Sequence

Before we can start writing our ‘C’ programs we must create the right

Programming environment. To do this, execute the following sequence.

1. Enter Windows:

2. Select and open the Main program group icon from the program manager.

3. Select and open the MSDOS icon from the main program group.

4. Press Alt+Enter to reduce the DOS Window to a DOS box with Windows

5. Select the DOS box using the mouse or by pressing ALT+TAB to sequence through

the currently opened windows until the DOS box is selected as active

Page 5: Seminar Report Keil

6. Change directory from C:\windows to C:\c51v4\bin.

7. Type START at the Command prompt C:\C51v4\bin:> START Press enter.

8. Change directory from C:\c51v4\bin to C:\c51v4\working

9. We are now ready to write our first program.

Creating ‘C’ Source Files

From within the directory C:\C51V4\WORKING you develop your ‘C’ programs.

You can create your programs using any ASCII text editor e.g. MSDOS ‘EDIT’ or the

Borland Editor within Borland ‘C’.

Windows Notepad may be used to create the source file, however, this source

file will still be required to be compiled in the DOS box at the DOS command prompt.

How to Compile Your ‘C’ Source File

1. Type COMP51 at the DOS prompt followed by the name of your file. NOTE DO

NOT include the filename extension .C . If you do the whole of your source file

will be corrupted.

2. C:\c51v4\working:> COMP51 test Press Enter.

3. This will call the compiler, assembler, linker and hex converter programs

automatically. Several files including .Hex will be created in the C:\c51v4\working

directory.

4. If you have any errors reported, you will find what they are by examining the .lst

file of your source file name, i.e. test.lst.

Page 6: Seminar Report Keil

5. When you have understood the errors, modify the ‘C’ source file and recompile

as part 2.

6. Once you have complete the compilation process you are ready the proceed with

download your .hex to the Flight32 board.

Keil c

The C programming language was designed for computers, though, and not

embedded systems. It does not support direct access to registers, nor does it allow for

the reading and setting of single bits, two very important requirements for 8051

software. In addition, most software developers are acustomed to writing programs that

will by executed by an operating system, which provides system calls the program may

use to access the hardware. However, much code for the 8051 is written for direct use

on the processor, without an operating system. To support this, the Keil compiler has

added several extensions to the C language to replace what might have normally been

implemented in a system call, such as the connecting of interrupt handlers.

The purpose of this manual is to further explain the limitations of the Keil compiler, the modifications it has made to the C language, and how to account for these in developing software for the 8051 microcontroller.

Mathematical operations:

The most basic concept about mathematical operations in programming languages, is the '=' operator which is used to store the content of the expression at its right, into the variable at its left. For example the following code will store the value of 'b' into 'a' : a = b; And subsequently, the following expression in totally invalid: 5 = b; Since 5 in a constant, trying to store the content of 'b' in it will cause an error. You can then perform all kind of mathematical operations, using the operators '+','-','*' and '/'. You can also use brackets '( )' when needed. Example:

Page 7: Seminar Report Keil

a =(5*b)+((a/b)*(a+b)); If you include 'math.h' header file, you will be able to use more advanced functions in your equations like Sin, Cos and Tan trigonometric functions, absolute values and logarithmic calculations like in the following example: a =(c*cos(b))+sin(b); To be able to successfully use those functions in your programs, you have to know the type of variables that those functions take as parameter and return as a result. For example a Cosine function takes an angle in radians whose value is a float number between -65535 and 65535 and it will return a float value as a result. You can usually know those data types from the 'math.h' file itself, for example, the cosine function, like all the others is declared in the top of the math header file, and you can read the line: extern float cos (float val); from this line you can deduce that the 'cos' function returns a float data type, and takes as a parameter a float too. (the parameter is always between brackets.). Using the same technique, you can easily know how to deal with the rest of the functions of the math header file. the following table shows a short description of those functions:

Function Description

char cabs (char val); Return an the absolute value of a char variable.

int abs (int val); Return an the absolute value of a int variable.

long labs (long val); Return an the absolute value of a long variable.

float fabs (float val); Return an the absolute value of a float variable.

float sqrt (float val); Returns the square root of a float variable.

float exp (float val); Returns the value of the Euler number 'e' to the power of val

float log (float val); Returns the natural logarithm of val

float log10 (float val); Returns the common logarithm of val

float sin (float val);

A set of standard trigonometric functions. They all take angles measured in radians whose value have to be between -65535 and 65535.

float cos (float val);

float tan (float val);

float asin (float val);

float acos (float val);

float atan (float val);

float sinh (float val);

float cosh (float val);

float tanh (float val);

float atan2 (float y, float x); This function calculates the arc tan of the ratio y / x, using the signs of both x and y to determine the quadrant of the angle and return a number ranging from -pi to pi.

float ceil (float val); Calculates the smallest integer that is bigger than val.

Page 8: Seminar Report Keil

Example: ceil(4.3) = 5.

float floor (float val); Calculates the largest integer that is smaller than val. Example: ceil(4.8) = 4.

float fmod (float x, float y); Returns the remainder of x / y. For example: fmod(15.0,4.0) = 3.

float pow (float x, float y); Returns x to the power y.

Logical operations: You can also perform logic operations with variables, like AND, OR and NOT operations, using the following operators:

Operator Description

! NOT (bit level) Example: P1_0 = !P1_0;

~ NOT (byte level) Example: P1 = ~P1;

& AND

| OR

Note that those logic operation are performed on the bit level of the registers. To understand the effect of such operation on registers, it's easier to look at the bits of a variable (which is composed of one or more register). For example, a NOT operation will invert all the bit of a register. Those logic operators can be used in many ways to merge different bits of different registers together. For example, consider the variable 'P1', which is of type 'char', and hence stored in an 8-bit register. Actually P1 is an SFR, whose 8 bits represents the 8 I/O pins of Port 1. It is required in that example to clear the 4 lower bits of that register without changing the state of the 4 other which may be used by other equipment. This can be done using logical operators according to the following code: P1 = P1 & 0xF0; (Adding '0x' before a number indicates that it is a hexadecimal one) Here, the value of P1 is ANDed with the variable 0xF0, which in the binary base is '11110000'. Recalling the two following relations: 1 AND X = X 0 AND X = 0 (where 'X' can be any binary value) You can deduce that the 4 higher bits of P1 will remain unchanged, while the 4 lower bits will be cleared to 0. By the way, note that you could also perform the same operation using a decimal variable instead of a hexadecimal one, for example, the following code will have exactly the same effect than the previous one (because 240 = F0 in HEX):

Page 9: Seminar Report Keil

P1 = P1 & 240; A similar types of operations that can be performed on a port, is to to set some of its bits to 1 without affecting the others. For example, to set the first and last bit of P1, without affecting the other, the following source code can be used: P1 = P1 | 0x81; Here, P1 is ORed with the value 0x81, which is '10000001' in binary. Recalling the two following relations: 1 OR X = 1 0 OR X = X (where 'X' can be any binary value) You can deduce that the first and last pins of P1 will be turned on, without affecting the state of the other pins of port 1. Those are just a few example of the manipulations that can be done to registers using logical operators. Logic operators can also be used to define very specific conditions, as you shall see in the next section. The last types of logic operation studied in this tutorial is the shifting. It can be useful the shift the bit of a register the right or to the left in various situations. this can be done using the following two operators:

Operator Description

>> Shift to the right

<< Shift to the left

The syntax is is quite intuitive, for example:

P1 = 0x01; // After that operation, in binary, P1 = 0000 0001

P1 = (P1 << 8) // After that operation, in binary P1 = 1000 0000

Data Types

The Cx51 Compiler provides several basic data types you may use in your C programs. The compiler supports the standard C data types as well as several data types that are unique to the Cx51 platform.

Data Types Bits Bytes Value Range

bit 1 0 to 1

Page 10: Seminar Report Keil

signed char 8 1 -128 — +127

unsigned char 8 1 0 — 255

enum 8 / 16 1 or 2 -128 — +127 or -32768 — +32767

signed short int 16 2 -32768 — +32767

unsigned short int 16 2 0 — 65535

signed int 16 2 -32768 — +32767

unsigned int 16 2 0 — 65535

signed long int 32 4 -2147483648 — +2147483647

unsigned long int 32 4 0 — 4294967295

float 32 4 ±1.175494E-38 — ±3.402823E+38

double 32 4 ±1.175494E-38 — ±3.402823E+38

sbit 1 0 or 1

sfr 8 1 0 — 255

sfr16 16 2 0 — 65535

Note

The bit, sbit, sfr, and sfr16 data types are not provided in ANSI C. They are unique

to the Cx51 Compiler.

Keil Limitations

There are several very important limitations in the evaluation version of Keil's

Developer's Kit that users need be aware of when writing software for the 8051.

Object code must be less than 2 Kbytes

The compiler will compile any-sized source code file, but the final object code

may not exceed 2 Kbytes. If it does, the linker will refuse to create a final binary

executable (or HEX file) from it. Along the same lines, the debugger will refuse any files

that are over 2Kbytes, even if they were compiled using a different software package.

Few student projects will cross this 2Kbyte threshold, but programmers should

be aware of it to understand why code may no longer compile when the project grows

too large.

Program code starts at address 0x4000

Page 11: Seminar Report Keil

All C code compiled and linked using the Keil tools will begin at address

0x4000 in code memory. Such code may not be programmed into devices with less

than 16Kbytes of Read-Only Memory. Code written in assembly may circumvent this

limitation by using the "origin" keyword to set the start to address 0x0000. No such

work-around exists for C programs, though. However, the integrated debugger in the

evaluation software may still be used for testing code. Once tested, the code may be

compiled by the full version of the Keil software, or by another compiler that supports

the C extensions used by Keil.

C Modifications

The Keil C compiler has made some modifications to anotherwise ANSI-

compliant implementation of the C programming language. These modifications were

made solely to facilitate the use of a higher-level language like C for writing programs

on microcontrollers.

Variable Types

The Keil C compiler supports most C variable types and adds several of its own.

Standard Types

The evaluation version of the Keil C compiler supports the standard ANSI C variable

types, with the exception of the floating point types. These types are summarized below.

Type Bits Bytes Range

char 8 1 -128 to +127

Page 12: Seminar Report Keil

unsigned char 8 1 0 to 255

enum 16 2 -32,768 to +32,767

short 16 2 -32,768 to +32,767

unsigned short 16 2 0 to 65,535

int 16 2 -32,768 to +32,767

unsigned int 16 2 0 to 65,535

long 32 4 -2,147,483,648 to

+2,147,483,647

unsigned long 32 4 0 to 4,294,697,295

In addition to these variable types, the compiler also supports the struct and union

data structures, as well as type redefinition using typedef.

Keil Types

To support a microcontroller and embedded systems applications, Keil added

several new types to their compiler. These are summarized in the table below.

Type Bits Bytes Range

bit 1 0 0 to 1

Page 13: Seminar Report Keil

sbit 1 0 0 to 1

sfr 8 1 0 to 255

sf16 16 2 0 to 65,535

Of these, only the bit type works as a standard variable would. The other three have

special behavior that a programmer must be aware of.

Bit

This is a data type that gets allocated out of the 8051's bit-addressable on-chip

RAM. Like other data types, it may be declared as either a variable. However, unlike

standard C types, if may not be used as a pointer. An example of its usage follows. /*

declare two bit variables - the compiler will decide which */

Page 14: Seminar Report Keil

sbit, sfr, and sf16

These are special types for accessing 1-bit, 8-bit, and 16-bit special function

registers. Because there is no way to indirectly address registers in the 8051, addresses

for these variables must be declared outsite of functions within the code. Only the data

addressed by the variable may be manipulated in the code. An example follows.

/* create an sbit variable that points to pin 0 of port 1 */

/* note that this is done outside of any functions! */

/* declare two bit variables - the compiler will decide which */

/* addresses they are at. Initialize them to 0 and 1. */

bit testbit1 = 0;

bit testbit2 = 1;

/* set testbit1 to the value in testbit2 */

testbit1 = testbit2;

/* clear testbit2 */

testbit2 = 0;

/* testbit1 is now a 1, and testbit2 is now a 0 */

/* Note that the assignment of testbit2 to testbit1 only copied */

/* the contents of testbit2 into testbit1. It did *not* change */

/* the location of testbit1 to be the same as testbit2. */

Page 15: Seminar Report Keil

sbit P10 = 0x90;

/* now the functions may be written to use this location */

void main (void)

{

/* forever loop, toggling pin 0 of port 1 */

while (1==1)

{

P10 = !P10;

delay (500); /* wait 500 microseconds */

}

}

Conveniently, the standard special function registers are all defined in the reg51.h file

that any developer may include into their source file. Only registers unique to the

particular 8051-derivative being used for the project need have these variable declared,

such as registers and bits related to a second on-chip serial port.

Keil Variable Extensions

In writing applications for a typical computer, the operating system handles manages

memory on behalf of the programs, eliminating their need to know about the memory

structure of the hardware. Even more important, most computers having a unified

memory space, with the code and data sharing the same RAM. This is not true with the

8051, which has separate memory spaces for code, on-chip data, and external data.

To accommodate for this when writing C code, Keil added extensions to variable

declarations to specify which memory space the variable is allocated from, or points to.

Page 16: Seminar Report Keil

The most important of these for student programmers are summarized in the following

table.

Extension Memory Type Related ASM

data

Directly-addressable data memory

(data memory addresses 0x00-

0x7F)

MOV A, 07Fh

idata

Indirectly-addressable data memory

(data memory addresses 0x00-

0xFF)

MOV R0, #080h

MOV A, R0

xdata External data memory MOVX @DPTR

code Program memory MOVC

@A+DPTR

These extensions may be used as part of the variable type in declaration or casting

by placing the extension after the type, as in the example below. If the memory type

extension is not specified, the compiler will decide which memory type to use

automatically, based on the memory model (SMALL, COMPACT, or LARGE, as

specified in the project properties in Keil).

/* This is a function that will calculate and return a checksum of */

/* a range of addresses in code memory, using a simple algorithm

*/

/* that simply adds each consecutive byte together. This could be

*/

/* useful for verifying if the code in ROM got corrupted (like if */

/* the Flash device were wearing out). */

Page 17: Seminar Report Keil

unsigned int checksum (unsigned int start, unsigned int end)

{

/* first, declare pointers to the start and end of */

/* the range in code memory. */

unsigned int code *codeptr, *codeend;

/* now declare the variable the checksum will be */

/* calculated in. Because direct-addressable data */

/* is faster to access than indirect, and this */

/* variable will be accessed frequently, we will */

/* declare it in data memory (instead of idata). */

/* In reality, if left unspecified, the compiler */

/* would probably leave it in the accumulator for */

/* even faster access, but that would defeat the */

/* point of this example. */

unsigned int data checksum = 0;

/* Initialize the codestart and codeend pointers to */

/* the addresses passed into the function as params. */

/* because start and end are passed in as values, */

/* not pointers, they must be cast to the correct */

/* pointer type */

codeptr = (unsigned int code *)start;

codeend = (unsigned int code *)end;

Page 18: Seminar Report Keil

/* Now perform the checksum calculation, looping */

/* until the end of the range is reached. */

while (codeptr <= codeend)

{

checksum = checksum + (unsigned int data)*codeptr;

codeptr++; /* go to the next address */

}

return (checksum);

}

Keil Function Extensions

As in most other C compilers, functions may be declared in one of two fashions:

unsigned int functionname

(unsigned int var)

{

....

return (var);

}

functionname (var)

unsigned int var

{

....

return (var);

}

Page 19: Seminar Report Keil

Most modern programmers use the first syntax, as do the examples in this document.

Keil provides two important extensions to the standard function declaration to allow for

the creation of interrupt handlers and reentrant functions.

Interrupt

In writing applications for a typical computer, the operating system provides system

calls for setting a function, declared in the standard manner, as the handler for an

interrupt. However, in writing code for an 8051 without an operating system, such a

system would not be possible using solely C code. To eliminate this problem, the Keil

compiler implements a function extension that explicitly declares a function as an

interrupt handler. The extension is interrupt, and it must be followed by an integer

specifying which interrupt the handler is for. For example:

/* This is a function that will be called whenever a serial */

/* interrupt occurs. Note that before this will work, interrupts */

/* must be enabled. See the interrupt example in the appendix. */

void serial_int (void) interrupt 4

{

...

}

In the example, a function called serial_int is set as the handler for interrupt 4, which is

the serial port interrupt. The number is calculated by subtracting 3 from the interrupt

vector address and dividing by 8. The five standard interrupts for the 8051 are as

follows:

Interrupt Vector Interrupt

Page 20: Seminar Report Keil

address number

External 0 0003h 0

Timer 0 000Bh 1

External 1 0013h 2

Timer 1 001Bh 3

Serial 0023h 4

Other interrupts are dependent on the implementation in the particular 8051-derivative

being used in the project, but may be calculated in the same manor using the vector

addresses specified by the manufacturer.

Using

Since the processor only save the current program counter before executing an

interrupt handler, the handler can potentially damage any data that was in the registers

prior to the interrupt. This in turn would corrupt the program once the processor goes

back to where it left off. To avoid this, the Keil compiler determines which registers will

be used by the interrupt handler function, pushes them out to the stack, executes the

handler, and then restores the registers from the stack, before returning to the

interrupted code. However, this incurs extra time, especially if a lot of registers will be

used. It is preferred that as little time be spent in interrupts as possible. To decrease this

time, Keil provides an optional extension, using, to the interrupt extension that tells the

compiler to simple change to a new register bank prior to executing the handler, instead

of pushing the registers to the stack.

/* This is a function that will be called whenever a serial */

/* interrupt occurs. Prior to executing the handler, the */

/* processor will switch to register bank 1

Page 21: Seminar Report Keil

void serial_int (void) interrupt 4 using 1

{

...

}

In the 8051, interrupts have two possible priorities: high and lo. If, during the

processing of an interrupt, another interrupt of the same priority occurs, the processor

will continue processing the first interrupt. The second interrupt will only be processed

after the first has finished. However, if an interrupt of a higher priority arrives, the first

(low priority) interrupt will itself be interrupted, and not resume until the higher priority

interrupt has finished. Because of this, all interrupts of the same priority may use the

same register bank.

The using extension should be used when quick execution time is of high

importance, or when other functions are called from the interrupt handler, as it would

otherwise push all of the registers on to the stack prior to calling the function, incurring

more time penalties.

Reentrant

Similar to the case described for interrupts above, it is possible for a single function

to be interrupted by itself. For example, in the middle of normal execution of the

function, the interrupt occurs, and that interrupt makes a call to the same function. While

the interrupt handler will save the registers before entering this function, no protective

measures are taken from overwriting the contents of local variables allocated in data

memory. When the interrupt is serviced and control is passed back to normal execution,

the corrupted data in those variables could ruin the entire program.

The general term for a function that may be called more than once simultaneously is

"reentrant." Accordingly, the reentrant extension may be used in a function declaration

to force the compiler to maintain a separate data area in memory for each instance of

the function. While safe, this does have the potential to use large area of the rather

limited data memory. An example of such a function follows.

Page 22: Seminar Report Keil

/* Because this function may be called from both the main program */

/* and an interrupt handler, it is declared as reentrant to */

/* protect its local variables. */

int somefunction (int param) reentrant

{

...

return (param);

}

/* The handler for External interrupt 0, which uses somefunction() */

void external0_int (void) interrupt 0

{

...

somefunction(0);

}

/* the main program function, which also calls somefunction() */

void main (void)

{

while (1==1)

{

...

Page 23: Seminar Report Keil

somefunction();

}

}