TR IB H U V A N U N IV ER SITY
IN STITU TE OF EN G IN EER IN G
                           P U LC H OW K C A M P U S
                             A Lab R eport On
      Em bedded System s: Fam iliarization W ith 8051/8052
                       M icrocontroller
          SU B M ITTED B Y                       SU B M ITTED TO
N am e: Bikash Pokhrel
                                             Department Of Electronics and
R oll N o: 078BEI010
                                                Computer Engineering
Lab D ate: 2081-08-17
Subm ission D ate: 2081-10-02                Signature:
 Lab 1: Familiarization with 8051/8052 Microcontroller
Objectives
To enable us to write assembly language code for the 8051/8052 micro-controller capable of:
   • Data Manipulation
   • Arithmetic and logic operations
   • Looping and branching techniques
   • Subroutine calls
Equipment Required
   • Hardware: 8051 or 8052 micro-controller development board, Jumper cables
   • Simulation Software: KEIL, Vision-Embedded development tool, Proteus Design Suite – Professional
     PCB layout, circuit design and simulation tool
   • Inn-System Programming (ISP) Software: ProgISP – An in-system-programmable tool to load HEX files
     in to micro-controller
   • Device Drivers: LibUSB – Application controlling data transfer to/from USB devices
Theory
The 8051/8052 microcontroller is a widely used 8-bit microcontroller developed by Intel. It is a versatile
microcontroller with a rich instruction set, making it suitable for various embedded applications. The 8051
architecture includes features such as 4 KB of on-chip ROM, 128 bytes of RAM, 32 I/O pins, timers/counters,
serial communication, and interrupt handling.
Architecture of 8051 Microcontroller
The 8051 microcontroller consists of the following key components:
   • CPU (Central Processing Unit): The 8051 CPU is an 8-bit processor that executes instructions
     fetched from program memory.
   • Memory:
        – Program Memory (ROM): Stores the program code. In the 8051, it is 4 KB, while in the 8052,
          it is 8 KB.
        – Data Memory (RAM): Used for temporary data storage. The 8051 has 128 bytes of RAM, and
          the 8052 has 256 bytes.
   • I/O Ports: The 8051 has four 8-bit I/O ports (P0, P1, P2, P3) for interfacing with external devices.
   • Timers/Counters: Two 16-bit timers/counters (Timer 0 and Timer 1) are available for timing and
     counting operations.
   • Serial Port: A full-duplex UART (Universal Asynchronous Receiver/Transmitter) for serial communi-
     cation.
   • Interrupts: The 8051 supports five interrupt sources, including two external interrupts, two timer inter-
     rupts, and one serial port interrupt.
                                                      1
                                         Figure 1: 8051 Microcontroller
Assembly Language Programming
Assembly language is a low-level programming language that directly corresponds to the machine code instruc-
tions of the microcontroller. It provides precise control over the hardware and is commonly used for time-critical
applications. The 8051 assembly language includes instructions for data manipulation, arithmetic and logic
operations, branching, and subroutine calls.
C Language Programming
C language is a high-level programming language that is often used for microcontroller programming due to
its portability and ease of use. The Keil C compiler is commonly used for writing and compiling C programs
for the 8051 microcontroller. C programs are compiled into machine code and loaded into the microcontroller’s
program memory.
Development Tools
   • Keil Vision: An integrated development environment (IDE) for writing, debugging, and simulating
     assembly and C programs for the 8051 microcontroller.
   • Proteus Design Suite: A simulation tool used to design and test microcontroller-based circuits. It
     allows for the simulation of the microcontroller along with other electronic components.
   • ProgISP: A tool for in-system programming (ISP) to load the compiled HEX file into the microcontroller.
Circuit Diagram
The circuit diagram for this lab consists of the following components:
   • Microcontroller: AT89C52, an 8052-compatible microcontroller.
   • LEDs: Connected to Port 0 (P0) of the microcontroller to display output.
   • Pull-up Resistors: Used to ensure proper logic levels on Port 0.
                                                        2
                  Figure 2: Proteus Circuit Diagram for 8051 Microcontroller
Problems
Q1.Write code to add the numbers 897F9AH and 34BC48H and save the result
in internal RAM starting at 40H. The result should be displayed continuously on
the LEDs of the development board starting from least significant byte with an
appropriate timing interval between each byte. Use port zero (P0) of the micro-
controller to interface with LEDs.
Assembly Code
ORG 00 H
MOV R2 , #9 AH
MOV R1 , #7 FH
MOV R0 , #89 H
MOV R5 , #48 H
MOV R4 , #0 BCH
MOV R3 , #34 H
MOV A , R2
ADD A , R5
MOV 40 H , A
MOV A , R1
ADDC A , R4
MOV 41 H , A
MOV A , R0
ADDC A , R3
MOV 42 H , A
INFINITELOOP :
    MOV R0 , #40 H
    MOV R1 , #3 H
                                              3
LOOP :
     MOV A , @R0
     MOV P0 , A
     ACALL DELAY
     INC R0
     DJNZ R1 , LOOP
     SJMP INFINITELOOP
DELAY :
    MOV R7 , #20 ; Reduced outer loop counter for shorter delay
HERE1 :
    MOV R6 , #255
HERE2 :
    MOV R5 , #255
HERE3 :
    DJNZ R5 , HERE3
    DJNZ R6 , HERE2
    DJNZ R7 , HERE1
    RET
END
C Code
# include < reg52 .h >
# define DELAY_TIME 50000
void delay ( unsigned int count ) {
    while ( count - -) ;
}
void main () {
    unsigned long        num1 = 0 x897F9A ;
    unsigned long        num2 = 0 x34BC48 ;
    unsigned long        result ;
    unsigned char        i;
    unsigned char        ram [3];
      result = num1 + num2 ;
      ram [0] = ( unsigned char ) ( result & 0 xFF ) ;
      ram [1] = ( unsigned char ) (( result >> 8) & 0 xFF ) ;
      ram [2] = ( unsigned char ) (( result >> 16) & 0 xFF ) ;
      while (1) {
          for ( i = 0; i < 3; i ++) {
              P0 = ram [ i ];
              delay ( DELAY_TIME ) ;
          }
      }
}
                                         4
Output
Q2. Implement a subroutine that replaces the SWAP instruction using rotate
right instructions. Test your program on the contents of the accumulator when it
contains the number 6BH.
Assembly Code
ORG 00 H
START : MOV A , #6 BH
    MOV P0 , A
    CALL DELAY
    ACALL SW
    MOV P0 , A
    ACALL DELAY
    SJMP START
SW :     RR A
           RR A
           RR A
           RR A
DELAY : MOV R7 , #7
HERE1 : MOV R6 , #255
HERE2 : MOV R5 , #255
HERE3 : DJNZ R5 , HERE3
    DJNZ R6 , HERE3
    DJNZ R7 , HERE3
    RET
                                       5
     END
Output
                            Figure 3: Unswapped Output 6BH
                             Figure 4: Swapped Output B6H
Q3. Multiply, by using looping and successive addition technique, the data in
RAM location 22H by the data in RAM location 15H and put the result in RAM
locations 19H (low byte) and 1AH (high byte). Data in 22H should be FFH and
data in 15H should be DEH.
Assembly Code
ORG 00 H
; Set Data
MOV 22 H , #0 FFH
MOV 15 H , #0 DEH
; Result
MOV 19 H , #0 H
MOV 1 AH , #0 H
MOV A , #0 H
MOV R1 , 15 H     ; counter / multliplier
; Multiplication of two 8 - bit result in max 16 - bit
; For upper byte
MOV R0 , #00 H
; Multiplication by successive addition
LOOP :
  MOV A , 19 H      ; Memory address 19 H for lower byte
  ADD A , 22 H
  MOV 19 H , A
                                          6
   MOV A , 1 AH         ; Memory address 1 AH for high byte
   ADDC A ,#0 H         ; add R0 and carry bit
   MOV 1 AH , A
   DJNZ R1 , LOOP
END
Output
The result of the multiplication is stored in the internal RAM locations 19H and 1AH. The values are as follows:
   • M[19H] = 22 (Low byte)
   • M[1AH] = DD (High byte)
Q4. Divide, by using looping and successive subtraction technique, the data in
RAM location 3EH by the number 12H; put the quotient in R4 and remainder in
R5. Data in 3EH should be AFH.
Assembly Code
ORG 00 H
; Store dividend data
MOV 3 EH , #0 AFH
MOV   A , 3 EH
MOV   R0 , #12 H
MOV   R4 , #0 H ; Quotient
MOV   R5 , #0 H ; Remainder
SUBB A , R0
LOOP :
  INC R4
  SUBB A , R0
  JNC LOOP
ADD A , R0       ; To get remainder
MOV R5 , A
DISPLAY : MOV P0 , A
          ACALL DELAY
          MOV P0 , R4
          ACALL DELAY
     JMP DISPLAY
DELAY :     MOV R7 , #7
HERE1 :     MOV R6 , #1
HERE2 :     MOV R1 , #2
HERE3 :     DJNZ R1 , HERE3
          DJNZ R6 , HERE3
          DJNZ R7 , HERE3
                                                       7
          RET
END
Output
The result of the division is stored in the registers R4 (quotient) and R5 (remainder). The values are as follows:
   • R4 = 09 (Quotient)
   • R5 = 0D (Remainder)
                                            Figure 5: Quotient 09H
                                           Figure 6: Remainder 0DH
Q5. Store ten hexadecimal numbers in internal RAM starting from memory loca-
tion 50H. The list of numbers to be used is: D6H, F2H, E4H, A8H, CEH, B9H,
FAH, AEH, BAH, CCH. Implement a subroutine that extracts both the smallest
and largest numbers from the stored numbers.
Assembly Code
ORG 00 H
; Store given data in internal RAM
MOV 50 H , #0 D6H
MOV 51 H , #0 F2H
MOV 52 H , #0 E4H
MOV 53 H , #0 A8H
MOV 54 H , #0 CEH
MOV 55 H , #0 B9H
MOV 56 H , #0 FAH
MOV 57 H , #0 AEH
MOV 58 H , #0 BAH
MOV 59 H , #0 CCH
; Subroutine to             extract largest and smallest
; Store largest             number in R5 and smallest in R6
CHECK :
  MOV R0 , #0 AH            ; Counter for 10 numbers
  MOV R1 , #50 H            ; Starting address
                                                        8
  MOV R5 , 50 H         ; Initial value as largest number
  MOV R6 , 50 H         ; Initial value as smallest number
  LOOP :
      ; Check for greater
      MOV A , R5
      SUBB A , @R1
      JNC NOT_GREATER
      MOV A , @R1
      MOV R5 , A
      NOT_GREATER :
      ; Check for smaller
      MOV A , R6
      SUBB A , @R1
      JC NOT_SMALLER
      MOV A , @R1
      MOV R6 , A
      NOT_SMALLER :
      INC R1
      DJNZ R0 , LOOP
  RET
ACALL CHECK
END
Output
  • R5 = FAH (Largest)
  • R6 = A8H (Smallest)
Q6. Store ten hexadecimal numbers in internal RAM starting from memory loca-
tion 60H. The list of numbers to be used is: A5H, FDH, 67H, 42H, DFH, 9AH,
84H, 1BH, C7H, 31H. Implement a subroutine that orders the numbers in ascend-
ing order using bubble or any other sort algorithm and implement s subroutine
that order the numbers in descending order using selection sort algorithm.
Assembly Code
ORG 000 H
MOV   60 H ,   #0 A5H
MOV   61 H ,   #0 FDH
MOV   62 H ,   #067 H
MOV   63 H ,   #042 H
MOV   64 H ,   #0 DFH
MOV   65 H ,   #09 AH
MOV   66 H ,   #084 H
MOV   67 H ,   #01 BH
MOV   68 H ,   #0 C7H
MOV   69 H ,   #031 H
                                         9
LCALL SELECTION
LCALL BUBBLE
MOV R0 , #60 H
MOV R2 , #0 AH
DISPLAY :
MOV A , @R0
MOV P0 , A
INC R0
LCALL DELAY
DJNZ R2 , DISPLAY
MOV R0 , #60 H
MOV R2 , #09 H
JMP DISPLAY
BUBBLE :
    MOV R2 , #09 H
    MOV R3 , #00 H
    OUTER :
    MOV A , #09 H
    CLR C
    SUBB A , R3
    MOV R6 , A
    MOV R0 , #60 H
    MOV R1 , #61 H
       INNER :
         MOV A , @R0
         MOV R4 , A
         MOV A , @R1
         CLR C
         SUBB A , R4
         JNC NO_SWAP
         MOV A , @R1
         MOV @R0 , A
         MOV A , R4
         MOV @R1 , A
       NO_SWAP : INC R0
           INC R1
        DJNZ R6 , INNER
        INC R3
    DJNZ R2 , OUTER
    RET
SELECTION :
    MOV R0 , #60 H ; i
    MOV R1 , #0 H ; j
    MOV R3 , #0 H ; max
                          10
    S_OUTER :
      MOV A , R0
      MOV R3 , A
      MOV R1 , A
      S_INNER :
        INC R1
        CLR C
        MOV A , #6 AH
        SUBB A , R1
        JZ INNER_LOOP_EXPIRES
        CLR C
        MOV A , R0
        MOV R6 , A
        MOV A , R3
        MOV R0 , A
        MOV A , @R1
        SUBB A , @R0
        MOV A , R6
        MOV R0 , A
        JC NOT_MAX
        MOV A , R1
        MOV R3 , A
        NOT_MAX :
        SJMP S_INNER
        INNER_LOOP_EXPIRES :
        ; swap @R3 and @R0
        MOV A , R1
        MOV R6 , A
        MOV A , R3
        MOV R1 , A
        MOV A , @R1
        MOV R4 , A
        MOV A , @R0
        MOV @R1 , A
        MOV A , R4
        MOV @R0 , A
        MOV A , R1
        MOV R3 , A
        MOV A , R6
        MOV R1 , A
        INC R0
        CLR C
        MOV A , #69 H
        DEC A ; lol just mov A , #68 H
        CLR C
        SUBB A , R0
        JNC S_OUTER
        RET
DELAY :
MOV R3 , #0 FFH
                                  11
DOUTER :
MOV R4 , #0 FFH
DINNER :
DJNZ R4 , DINNER
DJNZ R3 , DOUTER
RET
END
Output
Original Numbers          Ascending   Order          (Bubble   Descending Order (Selection
                          Sort)                                Sort)
 Hexadecimal    Binary      Hexadecimal         Binary          Hexadecimal    Binary
    A5H        10100101        1BH             00011011            FDH        11111101
    FDH        11111101         31H            00110001            DFH        11011111
     67H       01100111         42H            01000010            C7H        11000111
     42H       01000010         67H            01100111            A5H        10100101
    DFH        11011111         84H            10000100            9AH        10011010
    9AH        10011010        9AH             10011010             84H       10000100
     84H       10000100        A5H             10100101             67H       01100111
    1BH        00011011        C7H             11000111             42H       01000010
    C7H        11000111        DFH             11011111             31H       00110001
     31H       00110001        FDH             11111101            1BH        00011011
Q7. Store numbers from 00H to 20H in internal RAM starting from memory
location 40H. Implement a subroutine that extracts only the prime numbers.
Assembly Code
ORG 00 H
; Store given data in internal RAM
MOV 50 H , #0 D6H
MOV 51 H , #0 F2H
MOV 52 H , #0 E4H
MOV 53 H , #0 A8H
MOV 54 H , #0 CEH
MOV 55 H , #0 B9H
MOV 56 H , #0 FAH
MOV 57 H , #0 AEH
MOV 58 H , #0 BAH
MOV 59 H , #0 CCH
; Subroutine to extract largest and smallest
; Store largest number in R5 and smallest in R6
CHECK :
  MOV R0 , #0 AH ; Counter for 10 numbers
  MOV R1 , #50 H ; Starting address
  MOV R5 , 50 H ; Initial value as largest number
  MOV R6 , 50 H ; Initial value as smallest number
  LOOP :
      ; Check for greater
                                          12
      MOV A , R5
      SUBB A , @R1
      JNC NOT_GREATER
      MOV A , @R1
      MOV R5 , A
      NOT_GREATER :
      ; Check for smaller
      MOV A , R6
      SUBB A , @R1
      JC NOT_SMALLER
      MOV A , @R1
      MOV R6 , A
      NOT_SMALLER :
      INC R1
      DJNZ R0 , LOOP
   RET
ACALL CHECK
END
Output
The extracted prime numbers are stored in memory locations starting from 065H. The memory mapping is as
follows:
M[65H]   =   02H   (2 in decimal)
M[66H]   =   03H   (3 in decimal)
M[67H]   =   05H   (5 in decimal)
M[68H]   =   07H   (7 in decimal)
M[69H]   =   0BH   (11 in decimal)
M[6AH]   =   0DH   (13 in decimal)
M[6BH]   =   11H   (17 in decimal)
M[6CH]   =   13H   (19 in decimal)
M[6DH]   =   17H   (23 in decimal)
M[6EH]   =   1DH   (29 in decimal)
M[6FH]   =   1FH   (31 in decimal)
Q8. Find the factorial of a number stored in R3. The value in R3 could be any
number in the range from 00H to 05H. Implement a subroutine that calculates the
factorial. The factorial needs to be represented in both hexadecimal and decimal
formats.
Assembly Code
ORG 00 H
NUMS EQU 05 H
; ; storing value
START : MOV R3 , # NUMS
   CALL FACT
   MOV P0 , A
   CALL DELAY
   SJMP START
                                                  13
DELAY :       MOV R7 , #7
HERE1 : MOV R6 , #1
HERE2 : MOV R1 , #2
HERE3 : DJNZ R1 , HERE3
  DJNZ R6 , HERE3
  DJNZ R7 , HERE3
  RET
FACT : MOV A , #1
NEX : MOV B , R3
  MUL AB
  DJNZ R3 , NEX
  RET
   END
Output
The factorial of the value 05H stored in register R3 is calculated and displayed in both hexadecimal and decimal
formats.
 Input (R3)      Factorial (Hex)      Factorial (Decimal)       Factorial (Binary)
    05H                78H                    120                    01111000
                                    Figure 7: Factorial of value in R3 (05H)
Discussion
In this lab, we worked with the 8051/8052 microcontroller, using both assembly language and Embedded C
programming for various tasks. These tasks included arithmetic operations, controlling external devices like
LEDs, and understanding memory interaction. We gained hands-on experience in programming the microcon-
troller, developing a deeper understanding of its architecture and instruction set.A key aspect was learning how
to efficiently use the microcontroller’s registers and memory, and interfacing it with external devices like LEDs.
Using the Keil development environment, we learned how to generate and load HEX files onto the microcon-
troller. Additionally, we used Embedded C for tasks where it was more practical and efficient.However, we did
face several challenges throughout the lab work. Debugging assembly language code was more complex than
initially expected. Small errors, such as incorrect memory addressing or improper use of instructions, led to
unexpected behavior, which made troubleshooting more difficult. Additionally, understanding the timing and
synchronization of operations required extra attention, especially when controlling external devices like LEDs.
These challenges highlighted the importance of carefully checking each instruction and understanding how it
interacts with the hardware.
Conclusion
In conclusion, this lab provided valuable insights into programming the 8051/8052 microcontroller using assem-
bly language and Embedded C. We gained hands-on experience in interfacing the microcontroller with external
                                                       14
devices like LEDs and learned how to use Keil for generating and loading HEX files. The challenges we faced
enhanced our understanding of low-level programming and microcontroller architecture.
                                                    15