Introduction to Embedded C
Looking around, we find ourselves to be surrounded by various types of embedded
systems. Be it a digital camera or a mobile phone or a washing machine, all of them has
some kind of processor functioning inside it. Associated with each processor is the
embedded software. If hardware forms the body of an embedded system, embedded
processor acts as the brain, and embedded software forms its soul. It is the embedded
software which primarily governs the functioning of embedded systems.
During infancy years of microprocessor based systems, programs were developed
using assemblers and fused into the EPROMs. There used to be no mechanism to find
what the program was doing. LEDs, switches, etc. were used to check correct execution
of the program. Some ‘very fortunate’ developers had In-circuit Simulators (ICEs), but
they were too costly and were not quite reliable as well.
As time progressed, use of microprocessor-specific assembly-only as the programming
language reduced and embedded systems moved onto C as the embedded
programming language of choice. C is the most widely used programming language
for embedded processors/controllers. Assembly is also used but mainly to implement
those portions of the code where very high timing accuracy, code size efficiency, etc.
are prime requirements.
As assembly language programs are specific to a processor, assembly language didn’t
offer portability across systems. To overcome this disadvantage, several high level
languages, including C, came up. Some other languages like PLM, Modula-2, Pascal,
etc. also came but couldn’t find wide acceptance. Amongst those, C got wide
acceptance for not only embedded systems, but also for desktop applications. Even
though C might have lost its sheen as mainstream language for general purpose
applications, it still is having a strong-hold in embedded programming. Due to the wide
acceptance of C in the embedded systems, various kinds of support tools like
compilers & cross-compilers, ICE, etc. came up and all this facilitated development
of embedded systems using C.
Subsequent sections will discuss what is Embedded C, features of C language,
similarities and difference between C and embedded C, and features of embedded
C programming.
EMBEDDED SYSTEMS PROGRAMMING
Embedded systems programming is different from developing applications on a desktop
computers. Key characteristics of an embedded system, when compared to PCs, are as
follows:
· Embedded devices have resource constraints(limited ROM, limited RAM, limited
stack space, less processing power)
· Components used in embedded system and PCs are different; embedded systems
typically uses smaller, less power consuming components. · Embedded systems are
more tied to the hardware.
Two salient features of Embedded Programming are code speed and code
size. Code speed is governed by the processing power, timing constraints, whereas
code size is governed by available program memory and use of programming language.
Goal of embedded system programming is to get maximum features in minimum space
and minimum time.
Embedded systems are programmed using different type of languages:
· Machine Code
· Low level language, i.e., assembly
· High level language like C, C++, Java, Ada, etc.
· Application level language like Visual Basic, scripts, Access, etc.
Assembly language maps mnemonic words with the binary machine codes that the
processor uses to code the instructions. Assembly language seems to be an obvious
choice for programming embedded devices. However, use of assembly language is
restricted to developing efficient codes in terms of size and speed. Also, assembly
codes lead to higher software development costs and code portability is not there.
Developing small codes are not much of a problem, but large programs/projects
become increasingly difficult to manage in assembly language. Finding good assembly
programmers has also become difficult nowadays. Hence high level languages are
preferred for embedded systems programming.
Use of C in embedded systems is driven by following advantages
· It is small and reasonably simpler to learn, understand, program and debug.
· C Compilers are available for almost all embedded devices in use today, and there is a
large pool of experienced C programmers.
· Unlike assembly, C has advantage of processor-independence and is not specific to
any particular microprocessor/ microcontroller or any system. This makes it convenient
for a user to develop programs that can run on most of the systems.
· As C combines functionality of assembly language and features of high level languages,
C is treated as a ‘middle-level computer language’ or ‘high level assembly language’
· It is fairly efficient
· It supports access to I/O and provides ease of management of large embedded
projects.
Many of these advantages are offered by other languages also, but what sets C apart
from others like Pascal, FORTRAN, etc. is the fact that it is a middle level language; it
provides direct hardware control without sacrificing benefits of high level languages.
Compared to other high level languages, C offers more flexibility because C is relatively
small, structured language; it supports low-level bit-wise data manipulation.
Compared to assembly language, C Code written is more reliable and scalable, more
portable between different platforms (with some changes). Moreover, programs
developed in C are much easier to understand, maintain and debug. Also, as they can
be developed more quickly, codes written in C offers better productivity. C is based on
the philosophy ‘programmers know what they are doing’; only the intentions are to be
stated explicitly. It is easier to write good code in C & convert it to an efficient assembly
code (using high quality compilers) rather than writing an efficient code in assembly
itself. Benefits of assembly language programming over C are negligible when we
compare the ease with which C programs are developed by programmers.
Objected oriented language, C++ is not apt for developing efficient programs in
resource constrained environments like embedded devices. Virtual functions &
exception handling of C++ are some specific features that are not efficient in terms of
space and speed in embedded systems. Sometimes C++ is used only with very few
features, very much as C.
Ada, also an object-oriented language, is different than C++. Originally designed by the
U.S. DOD, it didn’t gain popularity despite being accepted as an international standard
twice (Ada83 and Ada95). However, Ada language has many features that would
simplify embedded software development.
Java is another language used for embedded systems programming. It primarily finds
usage in high-end mobile phones as it offers portability across systems and is also
useful for browsing applications. Java programs require Java Virtual Machine (JVM),
which consume lot of resources. Hence it is not used for smaller embedded devices.
Dynamic C and B# are some proprietary languages which are also being used in
embedded applications.
Efficient embedded C programs must be kept small and efficient; they must be
optimized for code speed and code size. Good understanding of processor architecture
embedded C programming and debugging tools facilitate this.
DIFFERENCE BETWEEN C AND EMBEDDED C
Though C and embedded C appear different and are used in different contexts, they
have more similarities than the differences. Most of the constructs are same; the
difference lies in their applications.
C is used for desktop computers, while embedded C is for microcontroller based
applications. Accordingly, C has the luxury to use resources of a desktop PC like
memory, OS, etc. While programming on desktop systems, we need not bother about
memory. However, embedded C has to use with the limited resources (RAM, ROM,
I/Os) on an embedded processor. Thus, program code must fit into the available
program memory. If code exceeds the limit, the system is likely to crash.
Compilers for C (ANSI C) typically generate OS dependant executables. Embedded
C requires compilers to create files to be downloaded to the
microcontrollers/microprocessors where it needs to run. Embedded compilers give
access to all resources which is not provided in compilers for desktop computer
applications.
Embedded systems often have the real-time constraints, which is usually not there with
desktop computer applications.
Embedded systems often do not have a console, which is available in case of desktop
applications.
So, what basically is different while programming with embedded C is the mindset; for
embedded applications, we need to optimally use the resources, make the program
code efficient, and satisfy real time constraints, if any. All this is done using the basic
constructs, syntaxes, and function libraries of ‘C’.
Programming using Embedded C
PROGRAMMING USING EMBEDDED C
Embedded C use most of the syntax and semantics of standard C, e.g., main() function,
variable definition, datatype declaration, conditional statements (if, switch. case), loops
(while, for), functions, arrays and strings, structures and union, bit operations, macros,
etc. In addition, there are some specifics to embedded C which are mentioned below:
1. Low Level Codes
Embedded programming requires access to underlying hardware, i.e., timers, memory,
ports, etc. In addition, it is often needed to handle interrupts, manage job queues, etc.
As C offers pointers and bit manipulation features, they are extensively used for direct
hardware access.
2. In-line Assembly Code
For a particular embedded device, there may be instructions for which no equivalent C
code is available. In such cases, inline assembly code, i.e., assembly code embedded
within C programs is used; the syntax depends upon the compiler. An example for ‘gcc’
is shown here.
int a=10, b;
asm (“movl %1, %%eax;
movl %%eax, %0;”
:”=r”(b) /* output */
:”r”(a) /* input */
:”%eax” /* clobbered register */
);
Assembly code is written in C program itself. Above code assigns ‘a’ to ‘b’. Writing
inline assembly code is much easier than writing full fledged assembly code.
3. Features like Heap, recursion
Embedded devices have no or limited heap area (where dynamic memory allocation
takes place). Hence, embedded programs do not use standard C functions
like malloc. Structures like linked lists/trees are implemented using static allocation only.
Similarly, recursion is not supported by most embedded devices because of its
inefficiency in terms of space and time.
Such other costly features of standard C which consume space and execution time are
either not available or not recommended
4. I/O Registers
Microcontrollers typically have I/Os, ADCs, serial interfaces and other peripherals in-
built into the chips. These are accessed as IO Registers, i.e., to perform any operation
on these peripherals, bits in these registers are read/written.
Special function registers (SFRs) are accessed as shown below:
SFR portb = 0x8B;
It is used to declare portB at location 0x8B.
Some embedded processors have separate IO space for such registers. Since there are
no such concepts in C, compilers provide special mechanisms to access them
unsigned char portB @portB 0x8B;
In this example, ‘@portB <address>’ declares portB at location 0x8B by the variable
portB.
Such extensions are not a part of standard C, syntax and semantics differ in various
embedded C compilers.
5. Memory Pointers
Some CPU architectures allow us to access IO registers as memory addresses. This
allows treating them just like any other memory pointers.
6. Bit Access
Embedded controllers frequently need bit operations as individual bits of IO registers
corresponds to the output pin of an I/O port. Standard C has quite powerful tools to do
bitwise operations. However, care must be taken while using them in structures
because C standard doesn’t define the bitfield allocation order and C compilers may
allocate bitfields either from left to right or from right to left.
7. Use of Variable data type
In C, datatypes can be simply declared, and compiler takes care of the storage
allocation as well as that of code generation. But, datatypes usage should be carefully
done to generate optimised code. For most 8-bit C compilers, ‘char’ is 8-bits, ‘short’ and
‘int’ are 16-bits, long is ’32-bits’.
Some embedded processors favour use of unsigned type. Use of ‘long’ and floating
variable should be avoided unless it is very necessary. Using long data types increase
code size and execution time. Use of floating point variables is not advised due to
intrinsic imprecise nature of floating point operations, alongside speed and code
penalty.
8. Use of Const and Volatile
Volatile is quite useful for embedded programming. It means that the value can change
without the program touching it. Consequently, the compiler cannot make any
assumptions about its value. The optimizer must reload the variable every time it is
used instead of holding a copy in a register.
Const is useful where something is not going to change, for e.g., function declarations,
etc.
Initially C was developed by Kernighan and Ritchie to fit into the space of 8K and to
write (portable) operating systems. Originally it was implemented on UNIX operating
systems. As it was intended for operating systems development, it can manipulate
memory addresses. Also, it allowed programmers to write very compact codes. This has
given it the reputation as the language of choice for hackers too.
Create header files for AT89C51
AIM: To help you understand how the header files and source files are made for ease of
programming.
I've been asked questions many time regarding the header files and custom functions created for
your own purpose say for Eg. to turn a port ON or to turn a particular port pin OFF. This basics
extend so far you can create functions to most of the registers in 89C51 or any other microcontroller
you want.
To begin with lets make sure you learn something useful at the end so I will have to explain you with
some example. I'll start with PORTS. I'll create a header and a source file for PORTS of 89C51. This
both files which also will be also knows as custom library files for your ease will help you make
programming easy then before.
Lets create a project in keil for 89C51-> So here it goes. So open keil. This is how it looks,
Then Create a new project for your testing purpose. I have named the project as port. Select 89c51
as CPU. Then click ok.
Now this is important part. I like to separate headers and source files into separate folders. Makes
easy to know where they are located when the project is large. So Click on target and you will
find Source Group 1 so Right click on that folder then Remove Source Group 1. Now right click on
target and create two new folders called Source and Header by selecting add group. Check the
image below: (Check Left side for source and header folders inside target 1)
Click on Target 1-> Options for Target 1.
This are my settings for Target. 12MHz crystal, Use on - chip ROM. Check the image below:
Click on Output Tab later after this settings, tick mark on create HEX file. (HEX-80) format. Now you
are ready to start with programming.
Now create new files main.c , port.h , and port.c .
In C programming "filename.h" files are basically called header files. This file contains mostly include
files, variable declarations, function declarations, defines, etc. "port.h" will contain your function
declarations and some include files needed to make those functions work. "port.c" file will contains
the definitions of that function. This functions will resemble same as you will write in main.c so lets
start with them. Create these three files and add them in respective folders. Check image below:
So to work with 89C51 microcontroller in Keil. First you need to know the include file made by keil
itself. The register addresses are defined by keil header file. I mostly read "REGX51.h" It is in include
folder inside keil compiler files (Folder Keil -> C51 ->Atmel ->REGX51.h). Please do read it.
Because I will be using the same registers below.
So what functions do we want for the port? I have created these so far. Check below: (port.h below)
The above picture clearly explains what will be header file for your custom functions. You can name
your function whatever you want. Plus you can do as many possible logic with it to get a outcome.
Here I did few functions to set and clear port, also to set and clear pin on the port. So to make these
functions work we need to create the definitions. So lets start with port.c:
So did you see what changes I have done. I have included port.h file in port.c file. It has to be done
since the declarations have been defined there. Also notice the port.c file contains most of the
definitions similar to main.c . Now lets use these header and source files for our multipurpose use.
So I'll create a basic routine to test these functions on each port.
Did you see the changes I did in the main loop? Now I don't need to think much behind what ports
are. Just my own functions are enough to know that this will set port and clear port.
You can view the files here: ( main.c) ( port.h) ( port.c)
What are the advantages behind this technique?
1. Reduces code lines shows less complexity.
2. Very easy to debug and find errors.
3. The files can be copied and pasted into another project and can be used.
To make the code more fancy you can use this #define technique.
Right now you will write the function as port_set(1);
So,
#define PORT1 1
This by putting in port.h you can now write the above function as port_set(PORT1);
That makes code more user friendly and understandable.
Also case 1: in switch statement can be now replaced with above technique as case PORT1:
So apply this technique and create header and source files for each hardware unit of 8051. (timer,
port, uart) etc.
So hope you learned how to create header and source files. This will also help you understand how
the header and source files are made and to be used which are included inside the compilers and
libraries itself.

Introduction to embedded c

  • 1.
    Introduction to EmbeddedC Looking around, we find ourselves to be surrounded by various types of embedded systems. Be it a digital camera or a mobile phone or a washing machine, all of them has some kind of processor functioning inside it. Associated with each processor is the embedded software. If hardware forms the body of an embedded system, embedded processor acts as the brain, and embedded software forms its soul. It is the embedded software which primarily governs the functioning of embedded systems. During infancy years of microprocessor based systems, programs were developed using assemblers and fused into the EPROMs. There used to be no mechanism to find what the program was doing. LEDs, switches, etc. were used to check correct execution of the program. Some ‘very fortunate’ developers had In-circuit Simulators (ICEs), but they were too costly and were not quite reliable as well. As time progressed, use of microprocessor-specific assembly-only as the programming language reduced and embedded systems moved onto C as the embedded programming language of choice. C is the most widely used programming language for embedded processors/controllers. Assembly is also used but mainly to implement those portions of the code where very high timing accuracy, code size efficiency, etc. are prime requirements. As assembly language programs are specific to a processor, assembly language didn’t offer portability across systems. To overcome this disadvantage, several high level languages, including C, came up. Some other languages like PLM, Modula-2, Pascal, etc. also came but couldn’t find wide acceptance. Amongst those, C got wide acceptance for not only embedded systems, but also for desktop applications. Even though C might have lost its sheen as mainstream language for general purpose applications, it still is having a strong-hold in embedded programming. Due to the wide acceptance of C in the embedded systems, various kinds of support tools like compilers & cross-compilers, ICE, etc. came up and all this facilitated development of embedded systems using C.
  • 2.
    Subsequent sections willdiscuss what is Embedded C, features of C language, similarities and difference between C and embedded C, and features of embedded C programming. EMBEDDED SYSTEMS PROGRAMMING Embedded systems programming is different from developing applications on a desktop computers. Key characteristics of an embedded system, when compared to PCs, are as follows: · Embedded devices have resource constraints(limited ROM, limited RAM, limited stack space, less processing power) · Components used in embedded system and PCs are different; embedded systems typically uses smaller, less power consuming components. · Embedded systems are more tied to the hardware. Two salient features of Embedded Programming are code speed and code size. Code speed is governed by the processing power, timing constraints, whereas code size is governed by available program memory and use of programming language. Goal of embedded system programming is to get maximum features in minimum space and minimum time. Embedded systems are programmed using different type of languages: · Machine Code · Low level language, i.e., assembly · High level language like C, C++, Java, Ada, etc. · Application level language like Visual Basic, scripts, Access, etc. Assembly language maps mnemonic words with the binary machine codes that the processor uses to code the instructions. Assembly language seems to be an obvious choice for programming embedded devices. However, use of assembly language is restricted to developing efficient codes in terms of size and speed. Also, assembly codes lead to higher software development costs and code portability is not there. Developing small codes are not much of a problem, but large programs/projects become increasingly difficult to manage in assembly language. Finding good assembly programmers has also become difficult nowadays. Hence high level languages are preferred for embedded systems programming.
  • 3.
    Use of Cin embedded systems is driven by following advantages · It is small and reasonably simpler to learn, understand, program and debug. · C Compilers are available for almost all embedded devices in use today, and there is a large pool of experienced C programmers. · Unlike assembly, C has advantage of processor-independence and is not specific to any particular microprocessor/ microcontroller or any system. This makes it convenient for a user to develop programs that can run on most of the systems. · As C combines functionality of assembly language and features of high level languages, C is treated as a ‘middle-level computer language’ or ‘high level assembly language’ · It is fairly efficient · It supports access to I/O and provides ease of management of large embedded projects. Many of these advantages are offered by other languages also, but what sets C apart from others like Pascal, FORTRAN, etc. is the fact that it is a middle level language; it provides direct hardware control without sacrificing benefits of high level languages. Compared to other high level languages, C offers more flexibility because C is relatively small, structured language; it supports low-level bit-wise data manipulation. Compared to assembly language, C Code written is more reliable and scalable, more portable between different platforms (with some changes). Moreover, programs developed in C are much easier to understand, maintain and debug. Also, as they can be developed more quickly, codes written in C offers better productivity. C is based on the philosophy ‘programmers know what they are doing’; only the intentions are to be stated explicitly. It is easier to write good code in C & convert it to an efficient assembly code (using high quality compilers) rather than writing an efficient code in assembly itself. Benefits of assembly language programming over C are negligible when we compare the ease with which C programs are developed by programmers. Objected oriented language, C++ is not apt for developing efficient programs in resource constrained environments like embedded devices. Virtual functions & exception handling of C++ are some specific features that are not efficient in terms of space and speed in embedded systems. Sometimes C++ is used only with very few features, very much as C.
  • 4.
    Ada, also anobject-oriented language, is different than C++. Originally designed by the U.S. DOD, it didn’t gain popularity despite being accepted as an international standard twice (Ada83 and Ada95). However, Ada language has many features that would simplify embedded software development. Java is another language used for embedded systems programming. It primarily finds usage in high-end mobile phones as it offers portability across systems and is also useful for browsing applications. Java programs require Java Virtual Machine (JVM), which consume lot of resources. Hence it is not used for smaller embedded devices. Dynamic C and B# are some proprietary languages which are also being used in embedded applications. Efficient embedded C programs must be kept small and efficient; they must be optimized for code speed and code size. Good understanding of processor architecture embedded C programming and debugging tools facilitate this. DIFFERENCE BETWEEN C AND EMBEDDED C Though C and embedded C appear different and are used in different contexts, they have more similarities than the differences. Most of the constructs are same; the difference lies in their applications. C is used for desktop computers, while embedded C is for microcontroller based applications. Accordingly, C has the luxury to use resources of a desktop PC like memory, OS, etc. While programming on desktop systems, we need not bother about memory. However, embedded C has to use with the limited resources (RAM, ROM, I/Os) on an embedded processor. Thus, program code must fit into the available program memory. If code exceeds the limit, the system is likely to crash. Compilers for C (ANSI C) typically generate OS dependant executables. Embedded C requires compilers to create files to be downloaded to the microcontrollers/microprocessors where it needs to run. Embedded compilers give access to all resources which is not provided in compilers for desktop computer applications.
  • 5.
    Embedded systems oftenhave the real-time constraints, which is usually not there with desktop computer applications. Embedded systems often do not have a console, which is available in case of desktop applications. So, what basically is different while programming with embedded C is the mindset; for embedded applications, we need to optimally use the resources, make the program code efficient, and satisfy real time constraints, if any. All this is done using the basic constructs, syntaxes, and function libraries of ‘C’. Programming using Embedded C PROGRAMMING USING EMBEDDED C Embedded C use most of the syntax and semantics of standard C, e.g., main() function, variable definition, datatype declaration, conditional statements (if, switch. case), loops (while, for), functions, arrays and strings, structures and union, bit operations, macros, etc. In addition, there are some specifics to embedded C which are mentioned below: 1. Low Level Codes Embedded programming requires access to underlying hardware, i.e., timers, memory, ports, etc. In addition, it is often needed to handle interrupts, manage job queues, etc. As C offers pointers and bit manipulation features, they are extensively used for direct hardware access. 2. In-line Assembly Code For a particular embedded device, there may be instructions for which no equivalent C code is available. In such cases, inline assembly code, i.e., assembly code embedded within C programs is used; the syntax depends upon the compiler. An example for ‘gcc’ is shown here. int a=10, b; asm (“movl %1, %%eax; movl %%eax, %0;” :”=r”(b) /* output */ :”r”(a) /* input */
  • 6.
    :”%eax” /* clobberedregister */ ); Assembly code is written in C program itself. Above code assigns ‘a’ to ‘b’. Writing inline assembly code is much easier than writing full fledged assembly code. 3. Features like Heap, recursion Embedded devices have no or limited heap area (where dynamic memory allocation takes place). Hence, embedded programs do not use standard C functions like malloc. Structures like linked lists/trees are implemented using static allocation only. Similarly, recursion is not supported by most embedded devices because of its inefficiency in terms of space and time. Such other costly features of standard C which consume space and execution time are either not available or not recommended 4. I/O Registers Microcontrollers typically have I/Os, ADCs, serial interfaces and other peripherals in- built into the chips. These are accessed as IO Registers, i.e., to perform any operation on these peripherals, bits in these registers are read/written. Special function registers (SFRs) are accessed as shown below: SFR portb = 0x8B; It is used to declare portB at location 0x8B. Some embedded processors have separate IO space for such registers. Since there are no such concepts in C, compilers provide special mechanisms to access them unsigned char portB @portB 0x8B; In this example, ‘@portB <address>’ declares portB at location 0x8B by the variable portB. Such extensions are not a part of standard C, syntax and semantics differ in various embedded C compilers. 5. Memory Pointers Some CPU architectures allow us to access IO registers as memory addresses. This allows treating them just like any other memory pointers.
  • 7.
    6. Bit Access Embeddedcontrollers frequently need bit operations as individual bits of IO registers corresponds to the output pin of an I/O port. Standard C has quite powerful tools to do bitwise operations. However, care must be taken while using them in structures because C standard doesn’t define the bitfield allocation order and C compilers may allocate bitfields either from left to right or from right to left. 7. Use of Variable data type In C, datatypes can be simply declared, and compiler takes care of the storage allocation as well as that of code generation. But, datatypes usage should be carefully done to generate optimised code. For most 8-bit C compilers, ‘char’ is 8-bits, ‘short’ and ‘int’ are 16-bits, long is ’32-bits’. Some embedded processors favour use of unsigned type. Use of ‘long’ and floating variable should be avoided unless it is very necessary. Using long data types increase code size and execution time. Use of floating point variables is not advised due to intrinsic imprecise nature of floating point operations, alongside speed and code penalty. 8. Use of Const and Volatile Volatile is quite useful for embedded programming. It means that the value can change without the program touching it. Consequently, the compiler cannot make any assumptions about its value. The optimizer must reload the variable every time it is used instead of holding a copy in a register. Const is useful where something is not going to change, for e.g., function declarations, etc. Initially C was developed by Kernighan and Ritchie to fit into the space of 8K and to write (portable) operating systems. Originally it was implemented on UNIX operating systems. As it was intended for operating systems development, it can manipulate memory addresses. Also, it allowed programmers to write very compact codes. This has given it the reputation as the language of choice for hackers too.
  • 8.
    Create header filesfor AT89C51 AIM: To help you understand how the header files and source files are made for ease of programming. I've been asked questions many time regarding the header files and custom functions created for your own purpose say for Eg. to turn a port ON or to turn a particular port pin OFF. This basics extend so far you can create functions to most of the registers in 89C51 or any other microcontroller you want. To begin with lets make sure you learn something useful at the end so I will have to explain you with some example. I'll start with PORTS. I'll create a header and a source file for PORTS of 89C51. This both files which also will be also knows as custom library files for your ease will help you make programming easy then before. Lets create a project in keil for 89C51-> So here it goes. So open keil. This is how it looks, Then Create a new project for your testing purpose. I have named the project as port. Select 89c51 as CPU. Then click ok.
  • 9.
    Now this isimportant part. I like to separate headers and source files into separate folders. Makes easy to know where they are located when the project is large. So Click on target and you will find Source Group 1 so Right click on that folder then Remove Source Group 1. Now right click on target and create two new folders called Source and Header by selecting add group. Check the image below: (Check Left side for source and header folders inside target 1)
  • 10.
    Click on Target1-> Options for Target 1. This are my settings for Target. 12MHz crystal, Use on - chip ROM. Check the image below:
  • 11.
    Click on OutputTab later after this settings, tick mark on create HEX file. (HEX-80) format. Now you are ready to start with programming. Now create new files main.c , port.h , and port.c . In C programming "filename.h" files are basically called header files. This file contains mostly include files, variable declarations, function declarations, defines, etc. "port.h" will contain your function declarations and some include files needed to make those functions work. "port.c" file will contains the definitions of that function. This functions will resemble same as you will write in main.c so lets start with them. Create these three files and add them in respective folders. Check image below:
  • 12.
    So to workwith 89C51 microcontroller in Keil. First you need to know the include file made by keil itself. The register addresses are defined by keil header file. I mostly read "REGX51.h" It is in include folder inside keil compiler files (Folder Keil -> C51 ->Atmel ->REGX51.h). Please do read it. Because I will be using the same registers below.
  • 13.
    So what functionsdo we want for the port? I have created these so far. Check below: (port.h below) The above picture clearly explains what will be header file for your custom functions. You can name
  • 14.
    your function whateveryou want. Plus you can do as many possible logic with it to get a outcome. Here I did few functions to set and clear port, also to set and clear pin on the port. So to make these functions work we need to create the definitions. So lets start with port.c: So did you see what changes I have done. I have included port.h file in port.c file. It has to be done since the declarations have been defined there. Also notice the port.c file contains most of the definitions similar to main.c . Now lets use these header and source files for our multipurpose use. So I'll create a basic routine to test these functions on each port.
  • 15.
    Did you seethe changes I did in the main loop? Now I don't need to think much behind what ports are. Just my own functions are enough to know that this will set port and clear port. You can view the files here: ( main.c) ( port.h) ( port.c)
  • 16.
    What are theadvantages behind this technique? 1. Reduces code lines shows less complexity. 2. Very easy to debug and find errors. 3. The files can be copied and pasted into another project and can be used. To make the code more fancy you can use this #define technique. Right now you will write the function as port_set(1); So, #define PORT1 1 This by putting in port.h you can now write the above function as port_set(PORT1); That makes code more user friendly and understandable. Also case 1: in switch statement can be now replaced with above technique as case PORT1: So apply this technique and create header and source files for each hardware unit of 8051. (timer, port, uart) etc. So hope you learned how to create header and source files. This will also help you understand how the header and source files are made and to be used which are included inside the compilers and libraries itself.