Academic Year 2024–2025

Real Time & Embedded Systems

Practical Journal — 8051 Microcontroller experiments using Keil µVision5 and Proteus Simulation

Jayesh H. Chouhan M.Sc. Computer Science (Sem-4) Roll No: 4723

Index

01

Interfacing LCD

Display "JAYESH" on a 16×2 LCD using 8-bit mode with AT89C51

This code is written for an 8051 microcontroller to control a 16×2 LCD display using the 8-bit interface method. The microcontroller displays the text "JAYESH" on the screen via commands and data instructions.

Ports and Pins:

rs (Register Select), rw (Read/Write), and en (Enable) are control pins on P1. Port P2 (data lines D0–D7) sends 8-bit data/commands to the LCD.

Key Functions:

lcdcmd() — Sends a command byte (rs=0, rw=0, en pulse).
lcddata() — Sends a character (rs=1, rw=0, en pulse).
delay() — Simple for-loop delay for LCD processing time.

LCD Commands:

0x38 — 8-bit mode, 5×7 matrix  |  0x01 — Clear screen  |  0x10 — Cursor blink  |  0x0C — Display ON  |  0x81 — Cursor line 1, pos 1

AT89C51 LM016L (16×2 LCD)

Keil µVision5

  1. Project → New Project → select AT89C51.
  2. Save file with .c extension. Add to Source Group.
  3. Rebuild (F7). Fix any errors.
  4. Target Options → Clock: 11.0592 MHz.
  5. Output → check Create HEX file. Rebuild again.

Proteus 8.13 SP0

  1. File → New Project → create PCB/Schematics.
  2. Create Firmware Project for 8051 AT89C51.
  3. Pick components: AT89C51, LM016L from library.
  4. Wire connections: P2 → LCD data, P1.0–P1.2 → rs/rw/en.
  5. Add VCC and GND terminals.
  6. Double-click controller → load .hex file → clock 11.0592 MHz.
  7. Click Play ▶ to simulate.
C — 8051
#include<reg51.h>

sbit rs= P1^0;
sbit rw= P1^1;
sbit en= P1^2;

void lcdcmd(unsigned char);
void lcddata(unsigned char);
void delay();

void main()
{
    P2=0x00;         // output declaration

    while(1)
    {
        lcdcmd(0x38);   // 5x7 matrix
        delay();
        lcdcmd(0x01);   // clear screen
        delay();
        lcdcmd(0x10);   // cursor blinking
        delay();
        lcdcmd(0x0c);   // display on
        delay();
        lcdcmd(0x81);   // cursor 1st line 1st pos
        delay();

        lcddata('J');
        delay();
        lcddata('A');
        delay();
        lcddata('Y');
        delay();
        lcddata('E');
        delay();
        lcddata('S');
        delay();
        lcddata('H');
        delay();
    }
}

void lcdcmd(unsigned char val)
{
    P2=val;
    rs=0;
    rw=0;
    en=1;
    delay();
    en=0;
}

void lcddata(unsigned char val)
{
    P2= val;
    rs= 1;
    rw=0;
    en= 1;
    delay();
    en=0;
}

void delay()
{
    unsigned int i;
    for(i=0; i<12000; i++);
}
LCD Output
LCD displaying "JAYESH" — Proteus Simulation

This program demonstrates interfacing an 8051 microcontroller with a 16×2 LCD using basic commands to display "JAYESH". The program initializes the LCD, clears the screen, enables the cursor, and continuously displays the text.

02

Traffic Control System

Control two sets of traffic lights using AT89C51

Controls two sets of traffic lights (red, yellow, green) using Port 1. The lights cycle through standard sequences with timing delays.

Pins:

r1, y1, g1 — Set 1 (P1.0–P1.2)  |  r2, y2, g2 — Set 2 (P1.3–P1.5)

Sequence:

Both red → Set 2 green → Set 1 yellow → Set 1 green (Set 2 red) → Repeat. Delay uses nested for-loops (60,000 iterations).

AT89C51 Traffic Light ×2

Keil µVision5

  1. Create project → AT89C51. Save as .c. Add to Source Group. Rebuild.
  2. Clock: 11.0592 MHz. Enable HEX. Rebuild.

Proteus 8.13 SP0

  1. Add AT89C51 and 2× TRAFFIC LIGHT.
  2. Connect P1.0–P1.2 → Light 1, P1.3–P1.5 → Light 2.
  3. Add VCC/GND. Load HEX. Clock 11.0592 MHz. Play ▶.
C — 8051
#include<reg51.h>

sbit r1=P1^0;
sbit y1=P1^1;
sbit g1=P1^2;
sbit r2=P1^3;
sbit y2=P1^4;
sbit g2=P1^5;

void main()
{
    unsigned int i;
    r1=y1=g1=0;
    r2=y2=g2=0;

    while(1)
    {
        r1=1; r2=1;
        y1=0; g1=0; y2=0; g2=0;
        for(i=0;i<60000;i++);
        for(i=0;i<60000;i++);

        g2=1; r2=0;
        for(i=0;i<60000;i++);
        for(i=0;i<60000;i++);

        r1=0; y1=1;
        for(i=0;i<60000;i++);

        g1=1; y1=0; r1=0;
        r2=1; g2=0; y2=0;
        for(i=0;i<60000;i++);

        r1=1; r2=0;
        y1=0; y2=0;
        g1=0; g2=1;
    }
}
Traffic Light State 1
Traffic Light — State 1
Traffic Light State 2
Traffic Light — State 2

This program simulates a traffic light system using the 8051. It controls two sets of lights cycling through red, yellow, and green phases with timed delays.

03

Matrix Keyboard + 7-Segment Display

Interface 4×3 keypad and show pressed key on 7-segment display

A 4×3 keypad is interfaced via Port 1 using row-column scanning. Each row is set low; columns are checked. The matching 7-segment hex code is sent to Port 2.

Keypad → 7-Segment Mapping:

0xF9→1 | 0x99→2 | 0xB8→3 | 0xA4→4 | 0x92→5 | 0x80→6 | 0xB0→7 | 0x82→8 | 0x98→9 | 0xC0→0

AT89C51 Keypad (Phone type) 7SEG-MPX1-CA VCC

Keil µVision5

  1. Create project → AT89C51. Save .c, rebuild. Clock 11.0592 MHz. HEX output.

Proteus 8.13 SP0

  1. Add AT89C51, KEYPAD-PHONE, 7SEG-MPX1-CA, VCC.
  2. Connect P1.0–P1.3 → Rows, P1.4–P1.6 → Columns.
  3. Port 2 → 7-segment data pins. Load HEX. Run.
C — 8051
#include<reg51.h>

sbit R0 = P1^0;
sbit R1 = P1^1;
sbit R2 = P1^2;
sbit R3 = P1^3;
sbit C0 = P1^4;
sbit C1 = P1^5;
sbit C2 = P1^6;

void seg(unsigned int);

void main()
{
    R0=R1=R2=R3=1; R0=0;
    if(C0==0) seg(0xF9);    // 1

    R0=R1=R2=R3=1; R0=0;
    if(C1==0) seg(0xA4);    // 4

    R0=R1=R2=R3=1; R0=0;
    if(C2==0) seg(0xB0);    // 7

    R0=R1=R2=R3=1; R1=0;
    if(C0==0) seg(0x99);    // 2

    R0=R1=R2=R3=1; R1=0;
    if(C1==0) seg(0x92);    // 5

    R0=R1=R2=R3=1; R1=0;
    if(C2==0) seg(0x82);    // 8

    R0=R1=R2=R3=1; R2=0;
    if(C0==0) seg(0xB8);    // 3

    R0=R1=R2=R3=1; R2=0;
    if(C1==0) seg(0x80);    // 6

    R0=R1=R2=R3=1; R2=0;
    if(C2==0) seg(0x98);    // 9

    R0=R1=R2=R3=1; R3=0;
    if(C1==0) seg(0xC0);    // 0
}

void seg(unsigned int ch)
{
    P2 = 0x00;
    P2 = ch;
}
Keypad Circuit
Keypad + 7-Segment Circuit
Key Output
Key Press Display

Demonstrates interfacing a 4×3 keypad with the 8051 to display digits on a 7-segment display using row-column scanning and hex-encoded segment values.

04

PWM Based Motor Control

Control DC motor speed (Low / Average / High) via switches using PWM

A DC motor on P2.0 is driven via an L293D motor driver. Three switches on Port 3 select speed by varying the PWM duty cycle.

Duty Cycle = T_on / (T_on + T_off) × 100%

Low — ON:10, OFF:90 (≈10%) | Average — ON:50, OFF:50 (≈50%) | High — ON:90, OFF:10 (≈90%)

AT89C51Button ×3DC MotorL293DVCC / GND

Keil µVision5

  1. Create project → AT89C51. Write code, save .c. Rebuild. Clock 11.0592 MHz. HEX output.

Proteus 8.13 SP0

  1. Add AT89C51, 3× BUTTON, DC MOTOR, L293D.
  2. Buttons → P3.0 (Low), P3.1 (Avg), P3.2 (High). P2.0 → L293D → Motor.
  3. Load HEX. Run. Press buttons to test speeds.
C — 8051
#include<reg51.h>

sbit mot = P2^0;
sbit low = P3^0;
sbit avg = P3^1;
sbit high = P3^2;

void delay(unsigned int);

void main()
{
    mot = 0;
    while(1)
    {
        if(low == 0)        // ~10% duty cycle
        {
            mot=1; delay(10);
            mot=0; delay(90);
        }
        if(avg == 0)        // ~50% duty cycle
        {
            mot=1; delay(50);
            mot=0; delay(50);
        }
        if(high == 0)       // ~90% duty cycle
        {
            mot=1; delay(90);
            mot=0; delay(10);
        }
    }
}

void delay(unsigned int d1)
{
    unsigned int d2;
    for(d2=0; d2<d1; d2++);
}
PWM Diagram
PWM Duty Cycle Diagram
Low Speed
Low Speed
Avg Speed
Average Speed
High Speed
High Speed

Demonstrates PWM-based DC motor speed control. Three switches select low (~10%), average (~50%), and high (~90%) duty cycles to vary motor speed.

05

Serial Communication (UART)

Transmit character 'M' via UART at 9600 baud

Configures the 8051 UART and continuously transmits 'M'.

Registers:

SCON=0x50 — Mode 1, receiver enabled | TMOD=0x20 — Timer 1 Mode 2 (auto-reload) | TH1=-3 (0xFD) → 9600 baud

Baud Rate:

Timer Rate = 11.0592 MHz ÷ 12 = 921,600 Hz → Baud = (2×921,600) ÷ (32×3) = 9600

AT89C51Virtual Terminal
  1. Keil: Create project, compile, generate HEX at 11.0592 MHz.
  2. Proteus: Add AT89C51 + VIRTUAL TERMINAL.
  3. Connect TXD (P3.1) → Virtual Terminal RXD. Set baud 9600.
  4. Load HEX. Run — 'M' appears repeatedly on terminal.
C — 8051
#include<reg51.h>

void main()
{
    SCON = 0x50;     // Mode 1, 8-bit UART, REN enabled
    TMOD = 0x20;     // Timer 1, Mode 2 (auto-reload)
    TH1  = -3;       // 9600 baud at 11.0592 MHz
    TR1  = 1;        // Start Timer 1

    while(1)
    {
        SBUF = 'M';          // Transmit 'M'
        while(TI == 0);      // Wait for completion
        TI = 0;              // Clear flag
    }
}
Serial Output
Virtual Terminal receiving 'M'

Demonstrates UART serial communication at 9600 baud using Timer 1 auto-reload mode. Character 'M' is continuously transmitted via SBUF.

06

Read Analog Voltage & Display

Alternating LED patterns on Port 1 and Port 2

Port 1 and Port 2 toggle between 0xAA (10101010) and 0x55 (01010101), creating alternating LED blink patterns.

0xAA — Even pins ON | 0x55 — Odd pins ON. Patterns alternate with delay(500).

AT89C51Logic Probe (BIG)LED ×8330Ω Resistor ×8GND
  1. Keil: Create project, compile HEX at 11.0592 MHz.
  2. Proteus: Add AT89C51, 8× LED, 8× 330Ω resistors.
  3. Connect P1 & P2 → resistors → LEDs → GND.
  4. Load HEX. Run — LEDs alternate 0xAA / 0x55.
C — 8051
#include<reg51.h>

void delay(unsigned int time)
{
    unsigned int i, j;
    for(j=0; j<time; j++)
    {
        for(i=0; i<1275; i++);
    }
}

void main()
{
    while(1)
    {
        P1 = 0xAA;       // 10101010
        P2 = 0xAA;
        delay(500);

        P1 = 0x55;       // 01010101
        P2 = 0x55;
        delay(500);
    }
}
LED Pattern
Alternating LED Pattern

Demonstrates port manipulation and timed output patterns. Ports toggle between 0xAA and 0x55, creating alternating LED effects useful for visual indicators.

07

Elevator Prototype

Stepper motor elevator with floor selection via buttons

Controls a stepper motor elevator. Buttons on Port 0 select floors (0–5). Motor steps via Port 3. Current floor shown on Port 2 → 7447 decoder → 7-segment display.

Functions:

up(b) — Move up b floors (P3: 1→2→4→8→16) | down(b) — Move down (reverse) | control(a) — Calculate diff and call up/down

Input Mapping:

P0=1→Floor 0 | P0=2→Floor 1 | P0=4→Floor 2 | P0=8→Floor 3 | P0=16→Floor 4 | P0=32→Floor 5

AT89C51Stepper Motor (Unipolar)7447 BCD DecoderButton ×6VCC ×3ULN2003A7SEG Common Anode

Keil µVision5

  1. Create project → AT89C51. Compile. Clock 11.0592 MHz. Generate HEX.

Proteus 8.13 SP0

  1. Add all components: AT89C51, Stepper Motor, ULN2003A, 7447, 7SEG, 6× Buttons.
  2. Port 0 → 6 buttons (floor selection).
  3. Port 3 → ULN2003A → Stepper Motor coils.
  4. Port 2 → 7447 BCD → 7-segment display.
  5. Add VCC/GND. Load HEX. Run. Press buttons to move elevator.
C — 8051
#include<REG51.H>
#include<stdio.h>

int p, q, r;
q = 10;       // motor freezing count
r = 10;       // rotation speed

delay(c)
{
    int i, j;
    if(c == 0)
    {
        for(i=0; i<500; i++)
        {
            for(j=0; j<r; j++);
        }
    }
    return(c);
}

// Elevator UP
up(b)
{
    int i, j;
    for(i=1; i<=b; i++)
    {
        for(j=0; j<=10; j++)
        {
            P3=1;  delay(0);
            P3=2;  delay(0);
            P3=4;  delay(0);
            P3=8;  delay(0);
            P3=16; delay(0);
        }
        P2 = p + i;
    }
    p = p + b;
    return b;
}

// Elevator DOWN
down(b)
{
    int i, j;
    for(i=1; i<=b; i++)
    {
        for(j=0; j<=q; j++)
        {
            P3=16; delay(0);
            P3=8;  delay(0);
            P3=4;  delay(0);
            P3=2;  delay(0);
            P3=1;  delay(0);
        }
        P2 = p - i;
    }
    p = p - b;
    return b;
}

control(a)
{
    int diff;
    if(a > p) { diff=a-p; up(diff); }
    if(a < p) { diff=p-a; down(diff); }
    return a;
}

main()
{
    int p1;
    p = 0;
    P2 = p;

    while(1)
    {
        if(P0==2)  { p1=1; control(1); }  // Floor 1
        if(P0==4)  { p1=2; control(2); }  // Floor 2
        if(P0==8)  { p1=3; control(3); }  // Floor 3
        if(P0==16) { p1=4; control(4); }  // Floor 4
        if(P0==32) { p1=5; control(5); }  // Floor 5
        if(P0==1)  { p1=0; control(0); }  // Ground
    }
}
Elevator Circuit
Elevator — Circuit
Elevator Running
Elevator — Running

Provides elevator control using the 8051 with a stepper motor. Buttons on Port 0 select floors; the motor moves up/down accordingly; the current floor is displayed on a 7-segment display via a 7447 BCD decoder.