Professional Documents
Culture Documents
Embedded C Programming
Embedded C Programming
0FFFFH
80H
8051 Memory
segment (64kB).
The 8051 Memory Space
data type memory
• The data type memory is a 128 byte on-chip memory
segment with an address starting at 000H(0) and
ending at 07FH(127).
• This directly accessible internal memory segment is
mostly used to store frequently used variables in the
program such as parameter variables, temp
variables, function variables and especially interrupt
service variables which must be quickly accessible
otherwise program performance will be affected.
• From 080H(128) to 0FFH(255) in RAM is the Special
Function Register (SFR) memory segment which are
used to control timer/counter, Acc, interrupts, and
I/O ports.
Bdata, idata, xdata
• Within the data segment there is a 16-byte special segment
called bdata with an address from 020H to 02FH which is
bit addressable. Each individual bit in this segment has its
unique bit address for fast access and manipulation.
• The idata segment (128 byte) is the second memory
segment at 080H-0FFH available in the extended on-chip
RAM(8052). It is indirect accessible. it must be accessed
with the indirect address mode (address is held in a
register).
• The xdata segment (64KB) from 00000H-0FFFFH (65,535) is
available on off-chip RAM which augments the internal
memory.
pdata
main()
{
while(1)
myBit = !myBit;
}
Contd.
ISR 0
Interrupt
Level 0
Interrupt ISR 1
Level 1
Interrupt Example
ISR 0
FUN 1
Simple interrupt application
• with an external interrupt #2 which is connected to
p3^2 (bit 3 of pin 2 for INT0, see reg51.h). Once
there is an interrupt caused by a edge trigger, the
interrupt 0 event is fired and ISR myISR ( ) is called.
#include <reg51.h>
void myISR() interrupt 0
{
...
}
main()
{
EA = 1; // enable global interrupt
EX0 = 1; // enable external interrupt 0
IT0 = 1; // 0 level triggered, 1 edge triggered
while(1)
{
...
}
}
Contd.
sub(unsigned char x)
{
#pragma ASM
mov A, #x //or use R7 register to get the value of
//parameter and put in Acc
mov @R0, A // put it in buffer
#pragma ENDASM
}
calling an assembly code from C51 program.
extern void a_func(unsigned int x);
void main()
{
int y;
y =_func();
}
Create a separate C file with the definition of a_fun() as follows:
#pragma SRC //let C compiler generate a .src file
//instead of obj file
unsigned int a_func(unsigned int x)
{ return x-1; //this may be a fake statement,
//the purpose of it to generate a skeleton
//for your true assembly code replacement
}
• Then use c51 compiler command to compile this C
file with option of src to generate the assembly
source code in a .src file.
• Modify the source code in assembly to fit your need
and rename it to .a51 file and use a51 command
assemble it into objective code.
• Finally, link this object code with the object code
from the main program to get the target code.
Modular Programming in C
• It is clear that a single source file or “module” is
sufficient to hold the entire C program.
• Modular programming, however, is a “divide and
conquer” software design and programming
technique which breaks up a large program into
manageable subprogram units such as functions and
subroutines. Each module represents a
separation of concerns which improves software
maintainability and reusability by enforcing logical
boundaries between modules.
Contd.
}
MyHeader.h
#ifndef _MYHEADER_H
#define _MYHEADER_H
#DEFINE PI 3.14259 //
typedef double Real; //
#include <stdio.h>
#include <math.h>
#include "MyHeader.h"
void f( int x )
{
int i;
for (i=1; i<x; i++) circle(i);;
}
static void circle( Real R ) // internal scoped function
{
Static count; //static variable
count ++;
Printf(“%f %d”, PI*sqr(R), count);
}
Because neither main.c nor module1.c has the _MYHEADER_H identifier
defined, the header file will be included and compiled.
• For a large embedded system it is not practical to
have a single header file incorporated in each source
file regardless of whether the incorporated files need
them or not.
• A good practical solution is to generate module-
specific include header files as shown in the next
diagram. Each module is paired with its
corresponding header file.
Module1.h Module2.h Module3.h
CC *.C
Executable code
• The header file consists of two parts:
• Part1: original data, type, macro definitions and function
prototypes used for host modules
• Part2: external references to the items listed in part1 for
referencing modules
• The template for module1.c is shown below:
//conditional compilation
// part1
#else
//part2
#endif
Assume there are two modules, module1.c and
module2.c.
#endif
The module2.c is shown as below.
#define _module1_
#include <module1.h>
#include <module2.h>
...
Function1(){ . . .; function2(); }
// call function2 in the definition of function1
• The header file for module2.c is listed below.
#ifdef _module2_ //_module_ is a identifier used for
//conditional compilation
function2(); // prototype of function2
#else
extern function2();
#endif
• Although both header files are included in both
modules, the original function prototype
declarations are compiled in the host modules and
external references are compiled in the referencing
modules by the conditional compilation directives in
the header files.