8051 Programming Using Embedded C
8051 Programming Using Embedded C
PROGRAMMING
USING
EMBEDDED C
Training Material
1
INDEX
1 Introduction 1
5 Keyboard Interfacing 15
8 Basic Programs 23
9 LED Toggling 27
11 Keyboard Interfacing 31
13 Interrupt programs 38
Introduction
What is an Embedded System?
An Embedded System can be best described as a system which has both the
hardware and software and is designed to do a specific task. A good example for
an Embedded System, which many households have, is a Washing Machine.
All these devices have one thing in common: they are programmable i.e., we can
write a program (which is the software part of the Embedded System) to define
how the device actually works.
Size: The memory that the program occupies is very important as Embed-
ded Processors like Microcontrollers have a very limited amount of ROM
(Program Memory).
Speed: The programs must be very fast i.e., they must run as fast as possi-
ble. The hardware should not be slowed down due to a slow running soft-
ware.
Portability: The same program can be compiled for different processors.
Ease of Implementation
Ease of Maintenance
Readability
registers and data RAM locations, using the int in place of char can lead to a larger size
hex file. This is not a significant issue in high level language.
unsigned int: The unsigned int is a 16-bit data type that takes a value in the range of 0 to
65535 (0000 – FFFFH). This is used to define 16-bit variables such as memory addresses,
set counter values of more than 256. Since registers and memory accesses are in 8-bit
chunks, the misuse of int variables will result in a larger hex file. However, for 8051
programming, do not use unsigned int in place where unsigned char will do the job. Also
in situations where there is no need for signed data we should use unsigned int instead of
signed int. Remember, C compiler uses signed int as default if unsigned keyword is not
used.
signed int: Signed int is a 16-bit data type that uses the MSB D15 to represent – or +value.
We have 15 bits for the magnitude of the number from –32768 to +32767.
sbit (Single bit): The 8 bit keyword is a widely used 8051 C data types which is used to
access single-bit addressable register. It allows access to the single bits of the SFR
registers. As we know and have studied, some of the SFRs are bit addressable. Among
the SFRs that are widely used are also bit addressable ports P0-P3.
bit and sfr: The bit data type allows access to single bits of bit-addressable memory
spaces 20 – 2FH. To access the byte-size SFR registers, we use the sfr data type. Table 1
summaries the different data types used for 8051 programming in C
Time Delays
There are two ways to create a time delay in 8051 C:
1. Using the 8051 timer
2. Using a simple for loop
In either case, the delays can be observed either on the oscilloscope or using a simulator.
for loop is carried out. In creating a time delay using for loop three factors need to be
considered that can affect the accuracy of the delay.
1. Number of machine cycles and number of clocks period per machine cycle. 2. Crystal
frequency connected between XTAL1 and XTAL
2. Duration of the clock period for the machine cycle is the function of crystal frequency.
3. Compiler choice. The third factor that affects the accuracy of the time delay is the
compiler used to compile the C program. In assembly language programming, we can
know and control the delay generated, as, the number of instructions and the cycles per
instruction is known to us. In case of C program, the C compiler will convert the C
statements and functions to assembly language instructions. Hence, different compilers
produce different code.
Delay using for loop:
void MSDelay(unsigned int dtime)
{
unsigned int i, j;
for (i = 0; i < dtime; i++)
for (j = 0; j< 1275; j++);
}
Programming 8051 Timers:
The 8051 has two timers/counters; they can be used either as Timers to generate a time
delay or as event counters to count events happening outside the microcontroller.
Basic Timers of 8051: Both Timer 0 and Timer 1 are 16 bits wide. Since 8051 has an 8-
bit architecture, each 16-bits timer is accessed as two separate registers of low byte and
high byte. The low byte register is called TL0/TL1 and the high byte register is called
TH0/TH1.
ALGORITHM
1. Start.
2. Make All Pins High.
3. Make Column 1 pin low.
4. Check if Row 1 is low, if yes then Switch 1 has been pressed.
5. Check if Row 2 is low, if yes then Switch 4 has been pressed.
6. Check if row 3 is low if yes then Switch 7 has been pressed.
7. Check if row 4 is low if yes then Switch 10 has been pressed.
8. Make Column 1 Pin high & Column 2 Pin Low.
9. Check if Row 1 is low, if yes then Switch 2 has been pressed.
10. Check if Row 2 is low, if yes then Switch 5 has been pressed.
11. Check if row 3 is low if yes then Switch 8 has been pressed.
12. Check if row 4 is low if yes then Switch 11 has been pressed.
13. Make Column 2 Pin high & Column 3 Pin Low.
14. Check if Row 1 is low, if yes then Switch 3 has been pressed.
15. Check if Row 2 is low, if yes then Switch 6 has been pressed.
16. Check if row 3 is low if yes then Switch 9 has been pressed.
17. Check if row 4 is low if yes then Switch 12 has been pressed.
18. Make column 3 pin high.
19. Stop.
Please make sure at any time only one column Pin should remain Low
An electronic device that is used to display data and the message is known as
LCD 16×2. As the name suggests, it includes 16 Columns & 2 Rows so it can
display 32 characters (16×2=32) in total & every character will be made with 5×8
(40) Pixel Dots. So the total pixels within this LCD can be calculated as 32 x 40
otherwise 1280 pixels.
Pin
Function Name
No.
RS
4 Selects command register when low, and data register when high (Register
Select )
Read/writ
5 Low to write to the register; High to read from the register
e
Sends data to data pins when a high to low pulse is given; Extra
voltage push is required to execute the instruction and EN(enable)
6 signal is used for this purpose. Usually, we set en=0, when we want Enable
to execute the instruction we make it high en=1 for some
milliseconds. After this we again make it ground that is, en=0.
7 DB0
8 DB1
9 DB2
10 DB3
8-bit data pins
11 DB4
12 DB5
13 DB6
14 DB7
Sr. Hex
Command to LCD instruction Register
No. Code
2 02 Return home
Data Register: The data register stores the data to be displayed on the LCD.
The data is the ASCII value of the character to be displayed on the LCD.
When we send data to LCD it goes to the data register and is processed
there.
PROGRAMMS
void delay()
{
unsigned int i,j;
for(i=0;i<500;i++)
for(j=0;j<5000;j++);
}
2) Write an 8051 C program to send hex values for ASCII characters of 0, 1, 2, 3,
4, 5, A, B, C, D to port P1.
#include <reg51.h>
void main(void)
{
unsigned char mynum[]="012345ABCD";
unsigned char z;
for (z=0;z<=10;z++)
P1=mynum[z];
}
3)Write an 8051 C program to send values of –4 to +4 to port P1
#include <reg51.h>
void MSDelay(unsigned int);
void main(void)
{
char mynum[]={+1,-1,+2,-2,+3,-3,+4,-4};
unsigned char z;
for (z=0;z<8;z++)
{
P1=mynum[z];
MSDelay(2500);
}
}
void MSDelay(unsigned int itime)
{
unsigned int i, j;
for (i = 0; i < itime; i++)
for (j = 0; j< 1275; j++);
}
Note: The negative values will be displayed in the 2’s complement for as 1, FFH, 2,
FEH, 3, FDH, 4, FCH.
4)Write an 8051 C program to get a byte of data form P1, wait ½ second (i.e., 500
ms) and then send it to P2.
#include <reg51.h>
void MSDelay(unsigned int);
void main( )
{
unsigned char mybyte;
P1= 0xFF; //make P1 input port
while (1)
{
mybyte = P1; //get a byte from P1
MSDelay(500); //wait for ½ second.
P2 = mybyte; //send it to P2
}
}
void MSDelay(unsigned int itime)
{
unsigned int i, j;
for (i = 0; i < itime; i++)
for (j = 0; j< 1275; j++);
}
5)Write an 8051 C program to toggle bit 0 of the port P1 (P1.0) 50,000 times
#include <reg51.h>
void MSDelay(unsigned int);
sbit MYBIT=P1^0;
void main(void) {
unsigned int z;
for (z=0;z<50000;z++) {
MYBIT=0;
MSDelay();
MYBIT=1;
MSDelay();
}
}
void MSDelay(unsigned int itime)
{
unsigned int i, j;
for (i = 0; i < itime; i++)
for (j = 0; j< 1275; j++);
}
#include <reg51.h>
void MSDelay(unsigned int); //delay routine definition
void main( )
{
while (1) //repeat forever
{
P3= 0xFF;
MSDelay(250);
P3= 0x00;
MSDelay(250);
}
}
// delay routine implimentation
void MSDelay(unsigned int itime)
{
unsigned int i, j;
for (i = 0; i < itime; i++)
for (j = 0; j< 1275; j++);
}
lcd_command(0X0C);
lcd_command(0X06);
lcd_command(0X01);
delay(5);
lcd_data('R');
lcd_data('A');
lcd_data('J');
lcd_data('E');
lcd_data('E');
while(1){}
}
void delay (char x)
{
int i,j;
for(j=0;j<x;j++)
for(i=0;i<3000;i++);
}
void lcd_command(char c)
{
P3=c;
P2&=~(1<<6);
P2|=(1<<7);
delay(2);
P2&=~(1<<7);
}
void lcd_data(char d)
Indian Institute of Embedded Systems – IIES (Koramangala – Bangalore)
30
{
P3=d;
P2|=(1<<6);
P2|=(1<<7);
delay(2);
P2&=~(1<<7);
}
#include <reg51.h>
void delay (char x);
void lcd_command (char c);
void lcd_data (char d);
int main(void)
{
char i;
lcd_command(0X38);
lcd_command(0X80);
lcd_command(0X0C);
lcd_command(0X06);
lcd_command(0X01);
delay(2);
while(1)
{
P1=0x7f;
i=P1 & 0X0F;
switch(i)
{
case 0x0E:
lcd_data('7');
break;
case 0x0D:
lcd_data('4');
break;
case 0x0B:
lcd_data('1');
break;
case 0x07:
lcd_data('N');
break;
}
P1=0XBF;
i=P1 & 0X0F;
switch(i)
{
case 0x0E:
lcd_data('8');
break;
case 0x0D:
lcd_data('5');
break;
case 0x0B:
lcd_data('2');
break;
Indian Institute of Embedded Systems – IIES (Koramangala – Bangalore)
33
case 0x07:
lcd_data('0');
break;
}
P1=0XDF;
i=P1& 0X0F;
switch(i)
{
case 0x0E:
lcd_data('9');
break;
case 0x0D:
lcd_data('6');
break;
case 0x0B:
lcd_data('3');
break;
case 0x07:
lcd_data('=');
break;
}
P1=0XEF;
i=P1& 0X0F;
switch(i)
{
case 0x0E:
lcd_data('/');
break;
case 0x0D:
lcd_data('*');
break;
case 0x0B:
lcd_data('-');
break;
case 0x07:
lcd_data('+');
break;
}
}
}
for(i=0;i<3000;i++);
}
void lcd_command(char c)
{
P3=c;
P2&=~(1<<6);
P2|=(1<<7);
delay(2);
P2&=~(1<<7);
}
void lcd_data(char d)
{
P3=d;
P2|=(1<<6);
P2|=(1<<7);
delay(14);
P2&=~(1<<7);
}
while(1)
{
for(i=0;i<10;i++)
{
P2=arr[i];
delay(100);
}
}
}
void main()
{
IE=0X81;
IT0=1;
MYBIT=0;
while(1)
{}
}
11)Write an 8051 C program to toggle all the bits of port P1 continuously with
some delay in between. Use Timer 0, 16-bit mode to generate the delay .
#include <reg51.h>
void T0Delay(void);
void main(void)
{
while (1) { //repeat forever
P1=0x55;
T0Delay(); //toggle all the bits of P1
P1=0xAA; // delay unknown
T0Delay();
Indian Institute of Embedded Systems – IIES (Koramangala – Bangalore)
40
}
}
void T0Delay()
{
TMOD=0x01; // timer 0 mode 1
TL0=0x00;
TH0=0x35; // load TH and TL
TR0=1; // turn on T0
while (TF0==0); // wait for TF0 to roll over
TR0=0; // turn off T0
TF0=0; // clear TF0
}
12)Write an 8051 C program to toggle all bits of P2 continuously every 500 ms. Use
Timer 1, mode 1 to create the delay.
Assume XTAL=11.0592 MHz=> T=1.085μs Count=500ms/1.085μs =460829 >65536 Let
us divide this delay as = 20x25ms, hence count for 25ms can be calculated. Count =
25ms/1.085μs = 23042 Initial count = 65536 – 23042= 42494 Count in hex = A5FEH
#include <reg51.h>
void T1M1Delay(void);
void main(void)
{
unsigned char x;
P2=0x55;
while (1)
{
P2=~P2;
for (x=0;x<20;x++)
T1M1Delay();
}}
void T1M1Delay(void)
{
TMOD=0x10;
TL1=0xFE;
TH1=0xA5;
TR1=1;
while (TF1==0);
TR1=0;
TF1=0;
}
Proteus Software
Steps:
Now open the Nuvoton ISP-ICP Utility software and follow the below
steps.
1. Select the ISP by COM port option for flashing the .hex file
through COM port.
2. Select the COM port from the drop down. Check device
manager for the com port number.
3. Choose the required controller. In this case, it is
W78E052D.
4. Browse and select the .hex file by clicking on Load File.
5. Finally click on Update chip to flash the .hex file.
----------------------------------------------------------------------------------------------------------