0% found this document useful (0 votes)
3 views27 pages

Microcontroller

This document discusses I/O bit manipulation programming for the 8051 microcontroller, emphasizing the ability to access individual bits of I/O ports without affecting others. It covers various instructions for setting, clearing, and toggling bits, as well as monitoring input bits and using the carry flag for status checks. Additionally, it highlights the read-modify-write feature and provides examples and exercises related to these concepts.

Uploaded by

Saadman Abeer
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views27 pages

Microcontroller

This document discusses I/O bit manipulation programming for the 8051 microcontroller, emphasizing the ability to access individual bits of I/O ports without affecting others. It covers various instructions for setting, clearing, and toggling bits, as well as monitoring input bits and using the carry flag for status checks. Additionally, it highlights the read-modify-write feature and provides examples and exercises related to these concepts.

Uploaded by

Saadman Abeer
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

1 I/O Bit Manipulation Programming

In this section we further examine 8051 I/O instructions. We pay special attention to I/O bit manipulation
since it is a powerful and widely used feature of the 8051 family.

1.1 I/O Ports and Bit-Addressability


Sometimes we need to access only 1 or 2 bits of the port instead of the entire 8 bits. A powerful feature of
8051 I/O ports is their capability to access individual bits of the port without altering the rest of the bits
in that port. Of the four 8051 ports, we can access either the entire 8 bits or any single bit without altering
the rest. When accessing a port in single-bit manner, we use the syntax “SETB X.Y” where X is the port
number 0, 1, 2, or 3, and Y is the desired bit number from 0 to 7 for data bits D0 to D7. For example,
“SETB P1.5” sets high bit 5 of port 1. Remember that D0 is the LSB and D7 is the MSB. For example, the
following code toggles bit P1.2 continuously.

Listing 1: Toggling P1.2


BACK: CPL P1.2 ; complement P1.2 o n l y
ACALL DELAY
SJMP BACK

; a n o t h e r v a r i a t i o n o f t h e a bo v e program f o l l o w s

AGAIN: SETB P1.2 ; change o n l y P1.2=h i g h


ACALL DELAY
CLR P1.2 ; change o n l y P1.2=low
ACALL DELAY
SJMP AGAIN
Notice that P1.2 is the third bit of P1, since the first bit is P1.0, the second bit is P1.1, and so on. Table 1
shows the bits of the 8051 I/O ports. See Example 1.1 for an example of bit manipulation of I/O bits. Notice
in Example 1.1 that unused portions of ports 1 and 2 are undisturbed. This single-bit addressability of I/O
ports is one of most powerful features of the 8051 microcontroller and is among the reasons that many
designers choose the 8051 over other microcontrollers. We will see the use of the bit-addressability of I/O
ports in future chapters.

Table 1: Single-Bit Addressability of Ports

P0 P1 P2 P3 Port Bit
P0.0 P1.0 P2.0 P3.0 D0
P0.1 P1.1 P2.1 P3.1 D1
P0.2 P1.2 P2.2 P3.2 D2
P0.3 P1.3 P2.3 P3.3 D3
P0.4 P1.4 P2.4 P3.4 D4
P0.5 P1.5 P2.5 P3.5 D5
P0.6 P1.6 P2.6 P3.6 D6
P0.7 P1.7 P2.7 P3.7 D7

[Example 4-2] Write the following programs.


(a) Create a square wave of 50% duty cycle on bit 0 of port 1.
(b) Create a square wave of 66% duty cycle on bit 3 of port 1.
Solution:
(a) The 50% duty cycle means that the “on” and “off” states (or the high and low portions of the pulse)
have the same length. Therefore, we toggle P1.0 with a time delay in between each state.

1
Listing 2: 50% Duty Cycle Square Wave on P1.0
HERE: SETB P1.0 ; set to high b i t 0 of port 1
LCALL DELAY ; c a l l the delay subroutine
CLR P1.0 ; P1.0=0
LCALL DELAY
SJMP HERE ; keep doing i t
Another way to write the above program is:

Listing 3: 50% Duty Cycle Using CPL


HERE: CPL P1.0 ; complement b i t 0 o f p o r t 1
LCALL DELAY ; c a l l the delay subroutine
SJMP HERE ; keep doing i t
(b) The 66% duty cycle means the “on” state is twice the “off” state.

Listing 4: 66% Duty Cycle Square Wave on P1.3


BACK: SETB P1.3 ; set port 1 b i t 3 high
LCALL DELAY ; c a l l the delay subroutine
LCALL DELAY ; c a l l the delay subroutine again
CLR P1.3 ; clear b i t 2 of p o r t 1( P1.3=low )
LCALL DELAY ; c a l l the delay subroutine
SJMP BACK ; keep doing i t

Table 2: Single-Bit Instructions

Instruction Function
SETB bit Set the bit (bit=1)
CLR bit Clear the bit (bit=0)
CPL bit Complement the bit (bit=NOT bit)
JB bit, target Jump to target if bit=1 (jump if bit)
JNB bit, target Jump to target if bit=0 (jump if no bit)
JBC bit, target Jump to target if bit=1, clear bit (jump if bit, then clear)

Table 2 lists the single-bit instructions for the 8051. We will see the use of these instructions throughout
future chapters.

1.2 Checking an Input Bit


The JNB (jump if no bit) and JB (jump if bit = 1) instructions are also widely used single-bit operations.
They allow you to monitor a bit and make a decision depending on whether it is 0 or 1. Instructions JNB
and JB can be used for any bits of I/O ports 0, 1, 2, and 3, since all ports are bit-addressable. However,
most of port 3 is used for interrupts and serial communication signals, and typically is not used for any I/O,
either single-bit or byte-wise. This is discussed in Chapters 10 and 11. Table 3 shows a list of instructions
for reading the ports.
[Example 4-3] Write a program to perform the following:
(a) keep monitoring the P1.2 bit until it becomes high

(b) when P1.2 becomes high, write value 45H to port 0


(c) send a high-to-low (H-to-L) pulse to P2.3
Solution:

2
Listing 5: Monitoring P1.2 and Sending H-to-L Pulse
SETB P1.2 ; make P1.2 an i n p u t
MOV A,#45H ;A=45H
AGAIN: JNB P1.2 ,AGAIN ; g e t o u t when P1.2=1
MOV P0 ,A ; i s s u e A t o P0
SETB P2.3 ; make P2.3 h i g h
CLR P2.3 ; make P2.3 low f o r H−to−L
In this program, instruction “JNB P1.2,AGAIN” (JNB means jump if no bit) stays in the loop as long
as P1.2 is low. When P1.2 becomes high, it gets out of the loop, writes the value 45H to port 0, and creates
an H-to-L pulse by the sequence of instructions SETB and CLR.

Table 3: Instructions For Reading an Input Port

Mnemonic Example Description


MOV A, PX MOV A, P2 Bring into A the data at P2 pins
JNB PX.Y, .. JNB P2.1, TARGET Jump if pin P2.1 is low
JB PX.Y, .. JB P1.3, TARGET Jump if pin P1.2 is high
MOV C, PX.Y MOV C, P2.4 Copy status of pin P2.4 to CY

[Example 4-5] A switch is connected to pin P1.7. Write a program to check the status of SW and perform
the following:
(a) If SW=0, send letter ‘N’ to P2.
(b) If SW=1, send letter ‘Y’ to P2.

Solution:

Listing 6: Checking a Switch on P1.7


SETB P1.7 ; make P1.7 an i n p u t
AGAIN: JB P1.2 ,OVER ; jump i f P1.7=1
MOV P2,# ’N ’ ;SW=0, i s s u e ’N ’ t o P2
SJMP AGAIN ; keep monitoring
OVER: MOV P2,# ’Y ’ ;SW=1, i s s u e ’Y ’ t o P2
SJMP AGAIN ; keep monitoring

1.3 Reading a Single Bit into the Carry Flag


We can also use the carry flag to save or examine the status of a single bit of the port. To do that, we use
the instruction “MOV C, Px.y” as shown in the next two examples.
[Example 4-6] A switch is connected to pin P1.7. Write a program to check the status of the switch and
perform the following:
(a) If switch = 0, send letter ‘N’ to P2.

(b) If switch = 1, send letter ‘Y’ to P2.


Use the carry flag to check the switch status. This is a repeat of the last example.
Solution:

Listing 7: Using Carry Flag to Check Switch


SETB P1.7 ; make P1.7 an i n p u t
AGAIN: MOV C, P1.2 ; read t h e SW s t a t u s i n t o CF
JC OVER ; jump i f SW = 1
MOV P2,# ’N ’ ;SW = 0 , i s s u e ’N ’ t o P2

3
4
SJMP AGAIN ; keep monitoring
OVER: MOV P2,# ’Y ’ ;SW = 1 , i s s u e ’Y ’ t o P2
SJMP AGAIN ; keep monitoring
[Example 4-7] A switch is connected to pin P1.0 and an LED to pin P2.7. Write a program to get the
status of the switch and send it to the LED.
Solution:

Listing 8: Reading Switch and Sending to LED


SETB P1.7 ; make P1.7 an i n p u t
AGAIN: MOV C, P1.0 ; read t h e SW s t a t u s i n t o CF
MOV P2.7 , C ; send t h e SW s t a t u s t o LED
SJMP AGAIN ; keep repeating
Note: The instruction “MOV P2.7, P1.0” is wrong since such an instruction does not exist. However,
“MOV P2, P1” is a valid instruction.
Notice in Examples 4-6 and 4-7 how the carry flag is used to get a bit of data from the port.

1.4 Reading Input Pins vs. Port Latch


In reading a port, some instructions read the status of port pins while others read the status of an internal
port latch. Therefore, when reading ports there are two possibilities:

1. Read the status of the input pin.


2. Read the internal latch of the output port.

We must make a distinction between these two categories of instructions since confusion between them is
a major source of errors in 8051 programming especially where external hardware is concerned. We discuss
these instructions briefly. However, readers must study and understand the material on this topic and on
the internal working of ports that is given in Appendix C.2.

1.5 Instructions for Reading Input Ports


As stated earlier, to make any bit of any 8051 port an input port, we must write 1 (logic high) to that bit.
After we configure the port bits as input, we can use only certain instructions in order to get the external
data present at the pins into the CPU. Table 4 shows the list of such instructions.

1.6 Reading Latch for Output Port


Some instructions read the contents of an internal port latch instead of reading the status of an external
pin. Table 4 provides a list of these instructions. For example, look at the “ANL P1, A” instruction. The
sequence of actions taken when such an instruction is executed is as follows.

1. The instruction reads the internal latch of the port and brings that data into the CPU.
2. This data is ANDed with the contents of register A.
3. The result is rewritten back to the port latch.

4. The port pin data is changed and now has the same value as the port latch.

Note: x is 0, 1, 2, or 3 for P0–P3.


From the above discussion, we conclude that the instructions that read the port latch normally read a
value, perform an operation (and possibly change it), then rewrite it back to the port latch. This is often
called “Read-Modify-Write”.

5
Table 4: Instructions Reading a Latch (Read-Modify-Write)

Mnemonic Example
ANL Px ANL P1,A
ORL Px ORL P2,A
XRL Px XRL P0,A
JBC PX.Y, TARGET JBC P1.1, TARGET
CPL PX.Y CPL P1.2
INC Px INC P1
DEC Px DEC P2
DJNZ PX.Y, TARGET DJNZ P1, TARGET
MOV PX.Y, C MOV P1.2, C
CLR PX.Y CLR P2.3
SETB PX.Y SETB P2.3

1.7 Read-Modify-Write Feature


The ports in the 8051 can be accessed by the read-modify-write technique. This feature saves many lines of
code by combining in a single instruction all three actions of (1) reading the port, (2) modifying its value, and
(3) writing to the port. The following code first places 01010101 (binary) into port 1. Next, the instruction
“XRL P1,#0FFH” performs an XOR logic operation on P1 with 1111 1111 (binary), and then writes the
result back into P1.

Listing 9: Read-Modify-Write Example


MOV P1,#55H ; P1 = 01010101
AGAIN: XRL P1,#0FFH ;EX−OR P1 w i t h 11111111
ACALL DELAY
SJMP AGAIN
Notice that the XOR of 55H and FFH gives AAH. Likewise, the XOR of AAH and FFH gives 55H. Logic
instructions are discussed in Chapter 6.

1.8 Review Questions


1. True or false. The instruction “SETB P2.1” makes pin P2.1 high while leaving other bits of P2
unchanged.
2. Show one way to toggle the pin P1.7 continuously using 8051 instructions.
3. Using the instruction “JNB P2.5, HERE” assumes that bit P2.5 is an (input, output).
4. Write instructions to get the status of P2.7 and put it on P2.0.
5. Write instructions to toggle both bits of P1.7 and P1.0 continuously.

CAUTION We strongly recommend that you study Section C.2 (Appendix C) if you are connecting any
external hardware to your 8051 system. Failure to use the right instruction or the right connection to port
pins can damage the ports of your 8051 system.

Chapter 4 Summary
This chapter focused on the I/O ports of the 8051. The four ports of the 8051, P0, P1, P2, and P3,
each use 8 pins, making them 8-bit ports. These ports can be used for input or output. Port 0 can be
used for either address or data. Port 3 can be used to provide interrupt and serial communication signals.
Then I/O instructions of the 8051 were explained, and numerous examples were given. We also showed the
bit-addressability of the 8051 ports.

6
Chapter 4 Problems
Section 4.1: 8051 I/O Programming
1. The 8051 DIP package is a -pin package.

2. Which pins are assigned to VCC and GND?


3. In the 8051, how many pins are designated as I/O port pins?
4. How many pins are designated as P0 and which number are they in the DIP package?

5. How many pins are designated as P1 and which number are they in the DIP package?
6. How many pins are designated as P2 and which number are they in the DIP package?
7. How many pins are designated as P3 and which number are they in the DIP package?
8. Upon RESET, all the bits of ports are configured as (input, output).

9. In the 8051, which port needs a pull-up resistor in order to be used as I/O?
10. Which port of the 8051 does not have any alternate function and can be used solely for I/O?
11. Write a program to get 8-bit data from P1 and send it to ports P0, P2, and P3.

12. Write a program to get 8-bit data from P2 and send it to ports P0 and P1.
13. In P3, which pins are for RxD and TxD?
14. At what memory location does the 8051 wake up upon RESET? What is the implication of that?
15. Write a program to toggle all the bits of P1 and P2 continuously (a) using AAH and 55H (b) using
the CPL instruction.

Section 4.2: I/O Bit Manipulation Programming


16. Which ports of the 8051 are bit-addressable?

17. What is the advantage of bit-addressability for 8051 ports?


18. When P1 is accessed as a single-bit port, it is designated as .
19. Is the instruction “CPL P1” a valid instruction?
20. Write a program to toggle P1.2 and P1.5 continuously without disturbing the rest of the bits.

21. Write a program to toggle P1.3, P1.7, and P2.5 continuously without disturbing the rest of the bits.
22. Write a program to monitor bit P1.3. When it is high, send 55H to P2.
23. Write a program to monitor the P2.7 bit. When it is low, send 55H and AAH to P0 continuously.

24. Write a program to monitor the P2.0 bit. When it is high, send 99H to P1. If it is low, send 66H to
P1.
25. Write a program to monitor the P1.5 bit. When it is high, make a low-to-high-to-low pulse on P1.3.
26. Write a program to get the status of P1.3 and put it on P1.4.

27. The P1.4 refers to which bit of P1?


28. Write a program to get the status of P1.7 and P1.6 and put them on P1.0 and P1.7, respectively.

7
Answers to Review Questions
Section 4.1: 8051 I/O Programming
1. 4, 8.

2. True
3. P0
4. False

5. MOV P1,#99H
MOV P2,#99H

Section 4.2: I/O Bit Manipulation Programming


1. True
2. H1: CPL P1.7
SJMP H1
3. Input

4. MOV C,P2.7
MOV P2.0,C
5. H1: CPL P1.7
CPL P1.0
SJMP H1

8051 Addressing Modes

Objectives
Upon completion of this chapter, you will be able to:

• List the five addressing modes of the 8051 microcontroller


• Contrast and compare the addressing modes
• Code 8051 Assembly language instructions using each addressing mode

• Access RAM using various addressing modes


• List the SFR (special function registers) addresses
• Discuss how to access the SFR
• Manipulate the stack using direct addressing mode

• Code 8051 instructions to manipulate a look-up table


• Access RAM, I/O, and ports using bit addresses
• Discuss how to access the extra 128 bytes of RAM space in the 8052

8
The CPU can access data in various ways. The data could be in a register, or in memory, or be provided
as an immediate value. These various ways of accessing data are called addressing modes. In this chapter
we discuss 8051/52 addressing modes in the context of some examples.
The various addressing modes of a microprocessor are determined when it is designed, and therefore
cannot be changed by the programmer. The 8051 provides a total of five distinct addressing modes. They
are as follows:

1. immediate

2. register
3. direct
4. register indirect
5. indexed

In Section 5.1 we look at immediate and register addressing modes. In Section 5.2 we cover accessing
memory using the direct, register indirect, and indexed addressing modes. Section 5.3 discusses the bit-
addressability of RAM, registers, and I/O ports. In Section 5.4 we show how to access the extra 128 bytes
of RAM in the 8052.

2 Immediate and Register Addressing Modes


In this section, first we examine immediate addressing mode and then register addressing mode.

2.1 Immediate Addressing Mode


In this addressing mode, the source operand is a constant. In immediate addressing mode, as the name
implies, when the instruction is assembled, the operand comes immediately after the opcode. Notice that
the immediate data must be preceded by the pound sign, “#”. This addressing mode can be used to load
information into any of the registers, including the DPTR register. Examples follow.

Listing 10: Immediate Addressing Mode Examples


MOV A,#25H ; l o a d 25H i n t o A
MOV R4,#62 ; l o a d t h e d e c i m a l v a l u e 62 i n t o R4
MOV B,#40H ; l o a d 40H i n t o B
MOV DPTR,#4521H ;DPTR=4512H
Although the DPTR register is 16-bit, it can also be accessed as two 8-bit registers, DPH and DPL,
where DPH is the high byte and DPL is the low byte. Look at the following code.

Listing 11: DPTR as Two 8-bit Registers


MOV DPTR,#2550H ; i s t h e same as :
MOV DPL,#50H
MOV DPH,#25H
Also notice that the following would produce an error since the value is larger than 16 bits.

Listing 12: Illegal Instruction Example


MOV DPTR,#68975 ; i l l e g a l ! ! v a l u e > 65535 (FFFFFH)
We can use the EQU directive to access immediate data as shown below.

Listing 13: Using EQU Directive


COUNT EQU 30
...

9
MOV R4,#COUNT ; R4=1E(30=1EH)
MOV DPTR,#MYDATA ;DPTR=200H
ORG 200H
YDATA: DB ” America ”
Notice that we can also use immediate addressing mode to send data to 8051 ports. For example, “MOV
P1,#55H” is a valid instruction.

2.2 Register Addressing Mode


Register addressing mode involves the use of registers to hold the data to be manipulated. Examples of
register addressing mode follow.

Listing 14: Register Addressing Mode Examples


MOV A, R0 ; copy t h e c o n t e n t s o f R0 i n t o A
MOV R2 ,A ; copy t h e c o n t e n t s o f A i n t o R2
ADD A, R5 ; add t h e c o n t e n t s o f R5 t o c o n t e n t s o f A
ADD A, R7 ; add t h e c o n t e n t s o f R7 t o c o n t e n t s o f A
MOV R6 ,A ; s a v e a c c u m u l a t o r i n R6
It should be noted that the source and destination registers must match in size. In other words, coding
“MOV DPTR,A” will give an error, since the source is an 8-bit register and the destination is a 16-bit
register. See the following.

Listing 15: Register Size Mismatch


MOV DPTR,#25F5H
MOV R7 ,DPL
MOV R6 ,DPH
Notice that we can move data between the accumulator and Rn (for n=0 to 7) but movement of data
between Rn registers is not allowed. For example, the instruction “MOV R4,R7” is invalid.
In the first two addressing modes, the operands are either inside one of the registers or tagged along with
the instruction itself. In most programs, the data to be processed is often in some memory location of RAM
or in the code space of ROM. There are many ways to access this data. The next section describes these
different methods.

2.3 Review Problems


1. Can the programmer of a microcontroller make up new addressing modes?
2. Show the instruction to load 1000 0000 (binary) into R3.
3. Why is the following invalid? “MOV R2,DPTR”
4. True or false. DPTR is a 16-bit register that is also accessible in low-byte and high-byte formats.

5. Is the PC (program counter) also available in low-byte and high-byte formats?

3 Accessing Memory Using Various Addressing Modes


We can use direct or register indirect addressing modes to access data stored either in RAM or registers of
the 8051. This topic will be discussed thoroughly in this section. We will also show how to access on-chip
ROM containing data using indexed addressing mode.

10
3.1 Direct Addressing Mode
As mentioned in Chapter 2, there are 128 bytes of RAM in the 8051. The RAM has been assigned addresses
00 to 7FH. The following is a summary of the allocation of these 128 bytes.

1. RAM locations 00–1FH are assigned to the register banks and stack.
2. RAM locations 20–2FH are set aside as bit-addressable space to save single-bit data. This is discussed
in Section 5.3.

3. RAM locations 30–7FH are available as a place to save byte-sized data.

Although the entire 128 bytes of RAM can be accessed using direct addressing mode, it is most often
used to access RAM locations 30–7FH. This is due to the fact that register bank locations are accessed by
the register names of R0–R7, but there is no such name for other RAM locations. In the direct addressing
mode, the data is in a RAM memory location whose address is known, and this address is given as a part
of the instruction. Contrast this with immediate addressing mode, in which the operand itself is provided
with the instruction. The “#” sign distinguishes between the two modes. See the examples below, and note
the absence of the “#” sign.

Listing 16: Direct Addressing Mode Examples


MOV R0 , 4 0H ; s a v e c o n t e n t o f RAM l o c a t i o n 40H i n R0
MOV 56H,A ; s a v e c o n t e n t o f A i n RAM l o c a t i o n 56H
MOV R4 , 7FH ; move c o n t e n t s o f RAM l o c a t i o n 7FH t o R4
As discussed earlier, RAM locations 0 to 7 are allocated to bank 0 registers R0–R7. These registers can
be accessed in two ways, as shown below.

Listing 17: Two Ways to Access Bank 0 Registers


MOV A, 4 ; i s t h e same as
MOV A, R4 ; which means copy R4 i n t o A
MOV A, 7 ; i s t h e same as
MOV A, R7 ; which means copy R7 i n t o A

Listing 18: More Direct Addressing Examples


MOV A, 2 ; i s t h e same as
MOV A, R2 ; which means copy R2 i n t o A
MOV A, 0 ; i s t h e same as
MOV A, R0 ; which means copy R0 i n t o A
The above examples should reinforce the importance of the “#” sign in 8051 instructions. See the
following code.

Listing 19: Importance of the # Sign


MOV R2,#5 ; R2 w i t h v a l u e 5
MOV A, 2 ; copy R2 t o A (A=R2=05)
MOV B, 2 ; copy R2 t o B (B=R2=05)
MOV 7 , 2 ; copy R2 t o R7
; s i n c e ”MOV R7 , R2” i s i n v a l i d
Although it is easier to use the names R0–R7 than their memory addresses, RAM locations 30H to 7FH
cannot be accessed in any way other than by their addresses since they have no names.

11
3.2 SFR Registers and Their Addresses
Among the registers we have discussed so far, we have seen that R0–R7 are part of the 128 bytes of RAM
memory. What about registers A, B, PSW, and DPTR? Do they also have addresses? The answer is yes.
In the 8051, registers A, B, PSW, and DPTR are part of the group of registers commonly referred to as
SFR (special function registers). There are many special function registers and they are widely used, as we
will discuss in future chapters. The SFR can be accessed by their names (which is much easier) or by their
addresses. For example, register A has address E0H, and register B has been designated the address F0H,
as shown in Table 5. Notice how the following pairs of instructions mean the same thing.

Listing 20: SFR Address vs. Name Equivalence


MOV 0E0H,#55H ; i s t h e same as
MOV A,#55H ; which means l o a d 55H i n t o A (A=55H)

MOV 0F0H,#25H ; i s t h e same as


MOV B,#25H ; which means l o a d 25H i n t o B (B=25H)

MOV 0E0H , R2 ; i s t h e same as


MOV A, R2 ; which means copy R2 i n t o A

MOV 0F0H , R0 ; i s t h e same as


MOV B, R0 ; which means copy R0 i n t o B

MOV P1 , A ; i s t h e same as
MOV 90H,A ; which means copy r e g A t o P1
Table 5 lists the 8051 special function registers (SFR) and their addresses. The following two points
should be noted about the SFR addresses.

1. The special function registers have addresses between 80H and FFH. These addresses are above 80H,
since the addresses 00 to 7FH are addresses of RAM memory inside the 8051.
2. Not all the address space of 80 to FF is used by the SFR. The unused locations 80H to FFH are
reserved and must not be used by the 8051 programmer.

Regarding direct addressing mode, notice the following two points: (a) the address value is limited to
one byte, 00–FFH, which means this addressing mode is limited to accessing RAM locations and registers
located inside the 8051. (b) if you examine the lst file for an Assembly language program, you will see that
the SFR registers’ names are replaced with their addresses as listed in Table 5.
[Example 5-1] Write code to send 55H to ports P1 and P2, using (a) their names, (b) their addresses.
Solution:
(a)

Listing 21: Sending 55H to Ports by Name


MOV A, #55H ;A=55H
MOV P1 ,A ; P1=55H
MOV P2 ,A ; P2=55H
(b) From Table 5, P1 address = 90H; P2 address = A0H

Listing 22: Sending 55H to Ports by Address


MOV A, #55H ;A=55H
MOV 90H,A ; P1=55H
MOV 0A0H,A ; P2=55H

12
Table 5: 8051 Special Function Register (SFR) Addresses

Symbol Name Address


ACC* Accumulator 0E0H
B* B register 0F0H
PSW* Program status word 0D0H
SP Stack pointer 81H
DPTR Data pointer 2 bytes
DPL Low byte 82H
DPH High byte 83H
P0* Port 0 80H
P1* Port 1 90H
P2* Port 2 0A0H
P3* Port 3 0B0H
IP* Interrupt priority control 0B8H
IE* Interrupt enable control 0A8H
TMOD Timer/counter mode control 89H
TCON* Timer/counter control 88H
T2CON* Timer/counter 2 control 0C8H
T2MOD Timer/counter mode control 0C9H
TH0 Timer/counter 0 high byte 8CH
TL0 Timer/counter 0 low byte 8AH
TH1 Timer/counter 1 high byte 8DH
TL1 Timer/counter 1 low byte 8BH
TH2 Timer/counter 2 high byte 0CDH
TL2 Timer/counter 2 low byte 0CCH
RCAP2H T/C 2 capture register high byte 0CBH
RCAP2L T/C 2 capture register low byte 0CAH
SCON* Serial control 98H
SBUF Serial data buffer 99H
PCON Power control 87H
* Bit-addressable

13
3.3 Stack and Direct Addressing Mode
Another major use of direct addressing mode is the stack. In the 8051 family, only direct addressing mode
is allowed for pushing onto the stack. Therefore, an instruction such as “PUSH A” is invalid. Pushing
the accumulator onto the stack must be coded as “PUSH 0E0H” where 0E0H is the address of register A.
Similarly, pushing R3 of bank 0 is coded as “PUSH 03”. Direct addressing mode must be used for the POP
instruction as well. For example, “POP 04” will pop the top of the stack into R4 of bank 0.
[Example 5-2] Show the code to push R5, R6, and A onto the stack and then pop them back them into
R2, R3, and B, where register B = register A, R2 = R6, and R3 = R5.
Solution:

Listing 23: Stack Push and Pop with Direct Addressing


PUSH 05 ; push R5 onto s t a c k
PUSH 06 ; push R6 onto s t a c k
PUSH 0E0H ; push r e g i s t e r A onto s t a c k
POP 0F0H ; pop t o p o f s t a c k i n t o r e g i s t e r B
; now r e g i s t e r B = register A
POP 02 ; pop t o p o f s t a c k i n t o R2
; now R2 = R6
POP 03 ; pop t o p o f s t a c k i n t o R3
; now R3 = R5

3.4 Register Indirect Addressing Mode


In the register indirect addressing mode, a register is used as a pointer to the data. If the data is inside the
CPU, only registers R0 and R1 are used for this purpose. In other words, R2–R7 cannot be used to hold
the address of an operand located in RAM when using this addressing mode. When R0 and R1 are used as
pointers, that is, when they hold the addresses of RAM locations, they must be preceded by the “@” sign,
as shown below.

Listing 24: Register Indirect Addressing Mode Examples


MOV A, @R0 ; move c o n t e n t s o f RAM l o c whose addr i s h e l d by R0 i n t o A
MOV @R1, B ; move c o n t e n t s o f B i n t o RAM l o c whose addr i s h e l d by R1
Notice that R0 (as well as R1) is preceded by the “@” sign. In the absence of the “@” sign, MOV will be
interpreted as an instruction moving the contents of register R0 to A, instead of the contents of the memory
location pointed to by R0.
[Example 5-3] Write a program to copy the value 55H into RAM memory locations 40H to 45H using
(a) direct addressing mode,
(b) register indirect addressing mode without a loop, and
(c) with a loop.
Solution:
(a)

Listing 25: Direct Addressing Mode


MOV A,#55H ; load A w i t h v a l u e 55H
MOV 40H,A ; copy A t o RAM l o c a t i o n 40H
MOV 41H,A ; copy A t o RAM l o c a t i o n 41H
MOV 42H,A ; copy A t o RAM l o c a t i o n 42H
MOV 43H,A ; copy A t o RAM l o c a t i o n 43H
MOV 44H,A ; copy A t o RAM l o c a t i o n 44H
(b)

14
Listing 26: Register Indirect without Loop
MOV A,#55H ; l o a d A w i t h v a l u e 55H
MOV R0,#40H ; l o a d t h e p o i n t e r . R0=40H
MOV @R0,A ; copy A t o RAM l o c a t i o n R0 p o i n t s to
INC R0 ; i n c r e m e n t p o i n t e r . Now R0=41H
MOV @R0,A ; copy A t o RAM l o c a t i o n R0 p o i n t s to
INC R0 ; i n c r e m e n t p o i n t e r . Now R0=42H
MOV @R0,A ; copy A t o RAM l o c a t i o n R0 p o i n t s to
INC R0 ; i n c r e m e n t p o i n t e r . Now R0=43H
MOV @R0,A ; copy A t o RAM l o c a t i o n R0 p o i n t s to
INC R0 ; i n c r e m e n t p o i n t e r . Now R0=44H
MOV @R0,A
(c)

Listing 27: Register Indirect with Loop


MOV A,#55 ;A=55H
MOV R0,#40H ; l o a d p o i n t e r . R0=40H, RAM a d d r e s s
MOV R2,#05 ; l o a d c o u n t e r , R2=5
AGAIN: MOV @R0,A ; copy 55H t o RAM l o c a t i o n R0 p o i n t s t o
INC R0 ; i n c r e m e n t R0 p o i n t e r
DJNZ R2 ,AGAIN ; l o o p u n t i l c o u n t e r = z e r o

3.5 Advantage of Register Indirect Addressing Mode


One of the advantages of register indirect addressing mode is that it makes accessing data dynamic rather
than static as in the case of direct addressing mode. Example 5-3 shows two cases of copying 55H into RAM
locations 40H to 45H. Notice in solution (b) that there are two instructions that are repeated numerous
times. We can create a loop with those two instructions as shown in solution (c). Solution (c) is the most
efficient and is possible only because of register indirect addressing mode. Looping is not possible in direct
addressing mode. This is the main difference between the direct and register indirect addressing modes.
[Example 5-4] Write a program to clear 16 RAM locations starting at RAM address 60H.
Solution:

Listing 28: Clearing 16 RAM Locations


CLR A ;A=0
MOV R1,#60H ; l o a d p o i n t e r . R1=60H
MOV R7,#16 ; l o a d c o u n t e r , R7=16(10 i n hex )
AGAIN: MOV @R1,A
INC R1 ; i n c r e m e n t R1 p o i n t e r
DJNZ R7 ,AGAIN ; l o o p u n t i l c o u n t e r=z e r o
An example of how to use both R0 and R1 in the register indirect addressing mode in a block transfer is
given in Example 3.5.
[Example 5-5] Write a program to copy a block of 10 bytes of data from RAM locations starting at 35H
to RAM locations starting at 60H.
Solution:

Listing 29: Block Transfer Using R0 and R1


MOV R0,#35H ; source pointer
MOV R1,#60H ; destination pointer
MOV R3,#10 ; counter
BACK: MOV A, @R0 ; g e t a b y t e from s o u r c e
MOV @R1,A ; copy i t t o d e s t i n a t i o n
INC R0 ; increment source p o i n t e r

15
INC R1 ; increment d e s t i n a t i o n p o i n t e r
DJNZ R3 ,BACK ; keep doing i t f o r a l l ten b y t e s

3.6 Limitation of Register Indirect Addressing Mode in the 8051


As stated earlier, R0 and R1 are the only registers that can be used for pointers in register indirect addressing
mode. Since R0 and R1 are 8 bits wide, their use is limited to accessing any information in the internal
RAM (scratch pad memory of 30H–7FH, or SFR). However, there are times when we need to access data
stored in external RAM or in the code space of on-chip ROM. Whether accessing externally connected RAM
or on-chip ROM, we need a 16-bit pointer. In such cases, the DPTR register is used, as shown next.

3.7 Indexed Addressing Mode and On-Chip ROM Access


Indexed addressing mode is widely used in accessing data elements of look-up table entries located in the
program ROM space of the 8051. The instruction used for this purpose is “MOVC A, @A+DPTR”. The
16-bit register DPTR and register A are used to form the address of the data element stored in on-chip
ROM. Because the data elements are stored in the program (code) space ROM of the 8051, the instruction
MOVC is used instead of MOV. The “C” means code. In this instruction the contents of A are added to the
16-bit register DPTR to form the 16-bit address of the needed data. See Example 3.7.
[Example 5-6] In this program, assume that the word “USA” is burned into ROM locations starting at
200H, and that the program is burned into ROM locations starting at 0. Analyze how the program works
and state where “USA” is stored after this program is run.
Solution:

Listing 30: Reading “USA” from ROM


ORG 0000H ; burn i n t o ROM s t a r t i n g a t 0
MOV DPTR,#200H ;DPTR=200H l o o k −up t a b l e a d d r e s s
CLR A ; c l e a r A(A=0)
MOVC A,@A+DPTR ; g e t t h e char from code s p a c e
MOV R0 ,A ; s a v e i t i n R0
INC DPTR ;DPTR=201 p o i n t i n g t o n e x t cha r
CLR A ; c l e a r A(A=0)
MOVC A,@A+DPTR ; g e t t h e n e x t c har
MOV R1 ,A ; s a v e i t i n R1
INC DPTR ;DPTR=202 p o i n t i n g t o n e x t cha r
CLR A ; c l e a r A(A=0)
MOVC A,@A+DPTR ; g e t t h e n e x t c har
MOV R2 ,A ; s a v e i t i n R2
HERE: SJMP HERE ; stay here

; Data i s burned i n t o code s p a c e s t a r t i n g a t 200H


ORG 200H
MYDATA: DB ”USA”
END ; end o f program
In the above program ROM locations 200H–202H have the following contents.

200 = (’U’) 201 = (’S’) 202 = (’A’)


We start with DPTR = 200H, and A = 0. The instruction “MOVC A, @A+DPTR” moves the contents
of ROM location 200H (200H + 0 = 200H) to register A. Register A contains 55H, the ASCII value for “U”.
This is moved to R0. Next, DPTR is incremented to make DPTR = 201H. A is set to 0 again to get the
contents of the next ROM location 201H, which holds character “S”. After this program is run, we have R0
= 55H, R1 = 53H, and R2 = 41H, the ASCII values for the characters “U”, “S” and “A”.

16
[Example 5-7] Assuming that ROM space starting at 250H contains “America”, write a program to
transfer the bytes into RAM locations starting at 40H.
Solution:
(a) This method uses a counter

Listing 31: ROM to RAM Transfer Using Counter


ORG 0000
MOV DPTR,#MYDATA ; l o a d ROM p o i n t e r
MOV R0,#40H ; l o a d RAM p o i n t e r
MOV R2,#7 ; load counter
BACK: CLR A ;A = 0
MOVC A,@A+DPTR ; move d a t a from code s p a c e
MOV @R0,A ; s a v e i t i n RAM
INC DPTR ; i n c r e m e n t ROM p o i n t e r
INC R0 ; i n c r e m e n t RAM p o i n t e r
DJNZ R2 ,BACK ; l o o p u n t i l c o u n t e r=0
HERE: SJMP HERE

;−−−−−−−−−On−c h i p code s p a c e used f o r s t o r i n g d a t a


ORG 250H
MYDATA: DB ”AMERICA”
END
(b) This method uses null char for end of string

Listing 32: ROM to RAM Transfer Using Null Terminator


ORG 0000
MOV DPTR,#MYDATA ; l o a d ROM p o i n t e r
MOV R0,#40H ; l o a d RAM p o i n t e r
BACK: CLR A ;A=0
MOVC A,@A+DPTR ; move d a t a from code s p a c e
JZ HERE ; exit i f null character
MOV @R0,A ; s a v e i t i n RAM
INC DPTR ; i n c r e m e n t ROM p o i n t e r
INC R0 ; i n c r e m e n t RAM p o i n t e r
SJMP BACK ; loop
HERE: SJMP HERE

;−−−−−−−−−On−c h i p code s p a c e used f o r s t o r i n g d a t a


ORG 250H
MYDATA: DB ”AMERICA” , 0 ; n o t i c e n u l l char f o r
; end o f s t r i n g
END
Notice the null character, 0, indicating the end of the string, and how we use the JZ instruction to detect
that.

3.8 Look-Up Table and the MOVC Instruction


The look-up table is a widely used concept in microprocessor programming. It allows access to elements of
a frequently used table with minimum operations. As an example, assume that for a certain application we
need x2 values in the range of 0 to 9. We can use a look-up table instead of calculating it. This is shown in
Example 3.8.
[Example 5-8] Write a program to get the x value from P1 and send x2 to P2, continuously.
Solution:

17
Listing 33: Square Look-Up Table
ORG 0
MOV DPTR,#300H ; l o a d l o o k −up t a b l e a d d r e s s
MOV A,#0FFH ;A=FF
MOV P1 ,A ; c o n f i g u r e P1 as i n p u t p o r t
BACK: MOV A, P1 ; get X
MOVC A,@A+DPTR ; g e t X s q u a r e d from t a b l e
MOV P2 ,A ; i s s u e i t t o P2
SJMP BACK ; keep doing i t

ORG 300H
XSQR TABLE :
DB 0 , 1 , 4 , 9 , 1 6 , 2 5 , 3 6 , 4 9 , 6 4 , 8 1
END
Notice that the first instruction could be replaced with “MOV DPTR,#XSQR TABLE”.
[Example 5-9] Answer the following questions for Example 3.8.
(a) Indicate the content of ROM locations 300–309H.
(b) At what ROM location is the square of 6, and what value should be there?
(c) Assume that P1 has a value of 9: What value is at P2 (in binary)?
Solution:
(a) All values are in hex.
300 = (00) 301 = (01) 302 = (04) 303 = (09)
304 = (10) 4 × 4 = 16 = 10 in hex
305 = (19) 5 × 5 = 25 = 19 in hex
306 = (24) 6 × 6 = 36 = 24H
307 = (31) 308 = (40) 309 = (51)
(b) 306H; it is 24H
(c) 01010001B, which is 51H and 81 in decimal (92 = 81)
In addition to being used to access program ROM, DPTR can be used to access memory externally
connected to the 8051. This is discussed in Chapter 14.
Another register used in indexed addressing mode is the program counter. This is discussed in Appendix
A.
In many of the examples above, the MOV instruction was used for the sake of clarity, even though one can
use any instruction as long as that instruction supports the addressing mode. For example, the instruction
“ADD A, @R0” would add the contents of the memory location pointed to by R0 to the contents of register
A. We will see more examples of using addressing modes with various instructions in the next few chapters.

3.9 Indexed Addressing Mode and MOVX Instruction


As we have stated earlier, the 8051 has 64K bytes of code space under the direct control of the Program
Counter register. We just showed how to use the MOVC instruction to access a portion of this 64K-byte
code space as data memory space. In many applications the size of program code does not leave any room
to share the 64K-byte code space with data. For this reason the 8051 has another 64K bytes of memory
space set aside exclusively for data storage. This data memory space is referred to as external memory and
it is accessed only by the MOVX instruction. In other words, the 8051 has a total of 128K bytes of memory
space since 64K bytes of code added to 64K bytes of data space gives us 128K bytes. One major difference
between the code space and data space is that, unlike code space, the data space cannot be shared between
code and data. This is such an important topic that we have dedicated an entire chapter to it: Chapter 14.

3.10 Accessing RAM Locations 30–7FH as Scratch Pad


As we have seen so far, in accessing registers R0–R7 of various banks, it is much easier to refer to them by
their R0–R7 names than by their RAM locations. The only problem is that we have only 4 banks and very

18
often the task of bank switching and keeping track of register bank usage is tedious and prone to errors. For
this reason in many applications we use RAM locations 30–7FH as scratch pad and leave addresses 8–1FH
for stack usage. That means that we use R0–R7 of bank 0, and if we need more registers we simply use
RAM locations 30–7FH. Look at Example 3.10.
[Example 5-10] Write a program to toggle P1 a total of 200 times. Use RAM location 32H to hold your
counter value instead of registers R0–R7.
Solution:

Listing 34: Toggle P1 200 Times Using Scratch Pad


MOV P1,#55H ; P1=55H
MOV 32H,#200 ; l o a d c o u n t e r v a l u e i n t o RAM l o c 32 h
LOP1 : CPL P1 ; t o g g l e P1
ACALL DELAY
DJNZ 32H, LOP1 ; r e p e a t 200 t i m e s

3.11 Review Questions


1. The instruction “MOV A, 40H” uses addressing mode. Why?
2. What address is assigned to register R2 of bank 0?
3. What address is assigned to register R2 of bank 2?
4. What address is assigned to register A?
5. Which registers are allowed to be used for register indirect addressing mode if the data is in on-chip
RAM?

4 Bit Addresses for I/O and RAM


Many microprocessors such as the 386 or Pentium allow programs to access registers and I/O ports in byte
size only. In other words, if you need to check a single bit of an I/O port, you must read the entire byte first
and then manipulate the whole byte with some logic instructions to get hold of the desired single bit. This
is not the case with the 8051. Indeed, one of the most important features of the 8051 is the ability to access
the registers, RAM, and I/O ports in bits instead of bytes. This is a very unique and powerful feature for a
microprocessor made in the early 1980s. In this section we show address assignment of bits of I/O, register,
and memory, in addition to ways of programming them.

4.1 Bit-Addressable RAM


Of the 128-byte internal RAM of the 8051, only 16 bytes are bit-addressable. The rest must be accessed in
byte format. The bit-addressable RAM locations are 20H to 2FH. These 16 bytes provide 128 bits of RAM
bit-addressability since 16 × 8 = 128. They are addressed as 0 to 127 (in decimal) or 00 to 7FH. Therefore,
the bit addresses 0 to 7 are for the first byte of internal RAM location 20H, and 8 to 0FH are the bit addresses
of the second byte of RAM location 21H, and so on. The last byte of 2FH has bit addresses of 78H to 7FH.
See Figure 2 and Example 4.1. Note that internal RAM locations 20–2FH are both byte-addressable and
bit-addressable.
[Example 5-11] Find out to which byte each of the following bits belongs. Give the address of the RAM
byte in hex.
(a) SETB 42H ;set bit 42H to 1 (d) SETB 28H ;set bit 28H to 1
(b) CLR 67H ;clear bit 67 (e) CLR 12 ;clear bit 12 (decimal)
(c) CLR 0FH ;clear bit 0FH (f) SETB 05
Solution:
(a) RAM bit address of 42H belongs to D2 of RAM location 28H.
(b) RAM bit address of 67H belongs to D7 of RAM location 2CH.

19
Figure 2: 16 Bytes of Internal RAM (Bit-Addressable Locations 20H–2FH)

20
(c) RAM bit address of 0FH belongs to D7 of RAM location 21H.
(d) RAM bit address of 28H belongs to D0 of RAM location 25H.
(e) RAM bit address of 12 belongs to D4 of RAM location 21H.
(f) RAM bit address of 05 belongs to D5 of RAM location 20H.
In order to avoid confusion regarding the addresses 00–7FH, the following two points must be noted.

1. The 128 bytes of RAM have the byte addresses of 00–7FH and can be accessed in byte size using various
addressing modes such as direct and register-indirect, as we have seen in this chapter and previous
chapters. These 128 bytes are accessed using byte-type instructions.

2. The 16 bytes of RAM locations 20–2FH also have bit addresses of 00–7FH since 16 × 8 = 128 (00–
7FH). In order to access these 128 bits of RAM locations and other bit-addressable space of 8051
individually, we can use only the single-bit instructions such as SETB. Table 6 provides a list of single-
bit instructions. Notice that the single-bit instructions use only one addressing mode and that is direct
addressing mode. In the first two sections of this chapter we showed various addressing modes of
byte-addressable space of the 8051, among them indirect addressing mode. It must be noted that there
is no indirect addressing mode for single-bit instructions.

Table 6: Single-Bit Instructions

Instruction Function
SETB bit Set the bit (bit=1)
CLR bit Clear the bit (bit=0)
CPL bit Complement the bit (bit=NOT bit)
JB bit, target Jump to target if bit=1 (jump if bit)
JNB bit, target Jump to target if bit=0 (jump if no bit)
JBC bit, target Jump to target if bit=1, clear bit (jump if bit, then clear)

4.2 I/O Port Bit Addresses


As we discussed in Chapter 4, the 8051 has four 8-bit I/O ports: P0, P1, P2, and P3. We can access either
the entire 8 bits or any single bit without altering the rest. When accessing a port in a single-bit manner, we
use the syntax “SETB X.Y” where X is the port number 0, 1, 2, or 3, and Y is the desired bit number from
0 to 7 for data bits D0 to D7. See Figure 3. For example, “SETB P1.5” sets high bit 5 of port 1. Remember
that D0 is the LSB and D7 is the MSB.
As we mentioned earlier in this chapter, every SFR register is assigned a byte address and ports P0–P3
are part of the SFR. For example, P0 is assigned byte address 80H, and P1 has address of 90H as shown in
Figure 3. While all of the SFR registers are byte-addressable some of them are also bit-addressable. The
P0–P3 are among this category of SFR registers. From Figure 3 we see that the bit addresses for P0 are
80H to 87H, and for P1 are 90H to 97H, and so on.
Notice that when code such as “SETB P1.0” is assembled, it becomes “SETB 90H” since P1.0 has the
RAM address of 90H. Also notice from Figures 2 and 3 that bit addresses 00–7FH belong to RAM byte
addresses 20–2FH, and bit addresses 80–F7H belong to SFR of P0, TCON, P1, SCON, P2, etc. The bit
addresses for P0–P3 are shown in Table 7, and discussed next.

4.3 Bit Memory Map


From Figures 2 and 3 and Table 7 once again notice the following facts.

1. The bit addresses 00–7FH are assigned to RAM locations of 20–2FH.

2. The bit addresses 80–87H are assigned to the P0 port.


3. The bit addresses 88–8FH are assigned to the TCON register.

21
Figure 3: SFR RAM Address (Byte and Bit)

22
4. The bit addresses 90–97H are assigned to the P1 port.
5. The bit addresses 98–9FH are assigned to the SCON register.
6. The bit addresses A0–A7H are assigned to the P2 port.
7. The bit addresses A8–AFH are assigned to the IE register.
8. The bit addresses B0–B7H are assigned to the P3 port.
9. The bit addresses B8–BFH are assigned to IP.
10. The bit addresses C0–CFH are not assigned.
11. The bit addresses D0–D7H are assigned to the PSW register.
12. The bit addresses D8–DFH are not assigned.
13. The bit addresses E0–E7H are assigned to the Accumulator register.
14. The bit addresses E8–EFH are not assigned.
15. The bit addresses F0–F7H are assigned to the B register.

Table 7: Bit Addresses for All Ports

P0 Addr P1 Addr P2 Addr P3 Addr Port’s Bit


P0.0 80 P1.0 90 P2.0 A0 P3.0 B0 D0
P0.1 81 P1.1 91 P2.1 A1 P3.1 B1 D1
P0.2 82 P1.2 92 P2.2 A2 P3.2 B2 D2
P0.3 83 P1.3 93 P2.3 A3 P3.3 B3 D3
P0.4 84 P1.4 94 P2.4 A4 P3.4 B4 D4
P0.5 85 P1.5 95 P2.5 A5 P3.5 B5 D5
P0.6 86 P1.6 96 P2.6 A6 P3.6 B6 D6
P0.7 87 P1.7 97 P2.7 A7 P3.7 B7 D7

[Example 5-12] For each of the following instructions, state to which port the bit belongs. Use Table 7.
(a) SETB 86H (b) CLR 87H (c) SETB 92H (d) SETB 0A7H
Solution:
(a) SETB 86H is for SETB P0.6.
(b) CLR 87H is for CLR P0.7.
(c) SETB 92H is for SETB P1.2.
(d) SETB 0A7H is for SETB P2.7.

4.4 Registers Bit-Addressability


While all I/O ports are bit-addressable, that is not the case with registers, as seen from Figure 2. Only
registers A, B, PSW, IP, IE, ACC, SCON, and TCON are bit-addressable. Of the bit-addressable registers,
we will concentrate on the familiar registers A, B, and PSW. The rest will be discussed in future chapters.
Now let’s see how we can use bit-addressability of registers such as A and PSW. As we discussed in
Chapter 2, in the PSW register two bits are set aside for the selection of the register banks. See Figure ??.
Upon RESET, bank 0 is selected. We can select any other banks using the bit-addressability of the PSW
as was shown in Chapter 2. The bit addressability of PSW also eliminates the need for instructions such as
JOV (Jump if OV=1). See Example 4.4.
Examine the next few examples of bit-addressability to gain a better understanding of this important
feature of the 8051.
[Example 5-13] Write a program to save the Accumulator in R7 of bank 2.
Solution:

23
Table 8: Bits of the PSW Register

CY AC F0 RS1 RS0 OV – P

RS1 RS0 Register Bank Address


0 0 0 00H–07H
0 1 1 08H–0FH
1 0 2 10H–17H
1 1 3 18H–1FH
Figure 5-3. Bits of the PSW Register

Listing 35: Saving Accumulator in Bank 2 R7


CLR PSW.3
SETB PSW.4
MOV R7 ,A
[Example 5-14] While there are instructions such as JNC and JC to check the carry flag bit (CY), there
are no such instructions for the overflow flag bit (OV). How would you write code to check OV?
Solution:
The OV flag is PSW.2 of the PSW register. PSW is a bit-addressable register; therefore, we can use the
following instruction to check the OV flag.

Listing 36: Checking Overflow Flag


JB PSW.2 ,TARGET ; jump i f OV=1
[Example 5-15] Write a program to see if the RAM location 37H contains an even value. If so, send it to
P2. If not, make it even and then send it to P2.
Solution:

Listing 37: Checking for Even Value


MOV A, 3 7H ; l o a d RAM l o c a t i o n 37H i n t o a c c u m u l a t o r
JNB ACC.0 , YES ; i s D0 o f r e g A 0? i f so jump
INC A ; i t i s odd , make i t even
YES : MOV P2 ,A ; send i t t o P2
[Example 5-16] Assume that bit P2.3 is an input and represents the condition of a door. If it goes high,
it means that the door is open. Monitor the bit continuously. Whenever it goes high, send a low-to-high
pulse to port P1.5 to turn on a buzzer.
Solution:

Listing 38: Door Monitor with Buzzer


HERE: JNB P2.3 ,HERE ; keep monitoring f o r high
CLR P1.5 ; C l e a r b i t ( P1.5 = 0)
ACALL DELAY
SETB P1.5 ; P1.5=1 ( low−to−h i g h p u l s e )
ACALL DELAY
SJMP HERE
[Example 5-17] The status of bits P1.2 and P1.3 of I/O port P1 must be saved before they are changed.
Write a program to save the status of P1.2 in bit location 06 and the status of P1.3 in bit location 07.
Solution:

Listing 39: Saving Port Bit Status


CLR 06 ; c l e a r b i t a d d r e s s 06

24
CLR 07 ; c l e a r b i t a d d r e s s 07
JNB P1.2 ,OVER ; c h e c k b i t P1.2 , i f 0 t h e n jump
SETB 06 ; i f P1.2 =1, s e t b i t l o c a t i o n 06 t o 1
OVER: JNB P1.3 ,NEXT ; c h e c k b i t P1.3 , i f 0 t h e n jump
SETB 07 ; i f P1.3 =1, s e t b i t l o c a t i o n 07 t o 1
NEXT: . . .
[Example 5-18] Write a program to save the status of bit P1.7 on RAM address bit 05.
Solution:

Listing 40: Saving P1.7 to RAM Bit 05


MOV C, P1.7 ; g e t b i t from p o r t
MOV 0 5 ,C ; save b i t
[Example 5-19] Write a program to get the status of bit pin P1.7 and send it to pin P2.0.
Solution:

Listing 41: Sending P1.7 Status to P2.0


HERE: MOV C, P1.7 ; g e t b i t from p o r t
MOV P2.0 , C ; send b i t t o p o r t
SJMP HERE ; repeat forever

4.5 Using BIT Directive


The BIT directive is a widely used directive to assign the bit-addressable I/O and RAM locations. The BIT
directive allows a program to assign the I/O or RAM bit at the beginning of the program, making it easier
to modify them. Examine the next few examples to see how we use the BIT directive.
[Example 5-20] Assume that bit P2.3 is an input and represents the condition of an oven. If it goes high,
it means that the oven is hot. Monitor the bit continuously. Whenever it goes high, send a low-to-high pulse
to port P1.5 to turn on a buzzer.
Solution:

Listing 42: Using BIT Directive for Oven Monitor


OVEN HOT BIT P2.3
BUZZER BIT P1.5

HERE: JNB OVEN HOT,HERE ; k e e p m o n i t o r i n g f o r HOT


ACALL DELAY
CPL BUZZER ; sound t h e b u z z e r
ACALL DELAY
SJMP HERE
This is similar to Example 5-16, except the use of BIT directive allows us to assign the OVEN HOT and
BUZZER bit to any port. This way you do not have to search the program for them.
[Example 5-21] An LED is connected to pin P1.7. Write a program to toggle the LED forever.
Solution:

Listing 43: Toggling LED Using BIT Directive


LED BIT P1.7 ; u s i n g BIT d i r e c t i v e
HERE: CPL LED ; t o g g l e LED
LCALL DELAY ; delay
SJMP HERE ; repeat forever
[Example 5-22] A switch is connected to pin P1.7 and an LED to pin P2.0. Write a program to get the
status of the switch and send it to the LED.
Solution:

25
Listing 44: Switch to LED Using BIT Directive
SW BIT P1.7 ; assign b i t
LED BIT P2.0 ; assign b i t
HERE: MOV C,SW ; g e t t h e b i t from t h e p o r t
MOV LED, C ; send t h e b i t t o t h e p o r t
SJMP HERE ; repeat forever
[Example 5-23] Assume that RAM bit location 12H holds the status of whether there has been a phone
call or not. If it is high, it means there has been a new call since it was checked the last time. Write a
program to display “New Messages” on an LCD if bit RAM 12H is high. If it is low, the LCD should say
“No New Messages”.
Solution:

Listing 45: Phone Message Indicator Using BIT Directive


PHONBIT BIT 12H
MOV C,PHONBIT ; copy b i t l o c a t i o n 12H t o c a r r y
JNC NO ; check to see i f i s high
MOV DPTR,#400H ; yes , l o a d a d d r e s s o f message
LCALL DISPLAY ; d i s p l a y message ( s e e Chap. 12)
SJMP EXIT ; g e t out
NO: MOV DPTR,#420H ; l o a d t h e a d d r e s s o f No message
LCALL DISPLAY ; d i s p l a y i t
EXIT : ; exit
;−−−−−−d a t a t o be d i s p l a y e d on LCD
ORG 400H
YES MG: DB ”New Messages ” , 0
ORG 420H
NO MG: DB ”No New Messages ” , 0

4.6 Using EQU Directive


We can also use the EQU directive to assign addresses, as shown in the next few examples. Notice that in
Example 4.6 the ports are defined by their names, while in Example 4.6, they are defined by their addresses.
[Example 5-24] A switch is connected to pin P1.7. Write a program to check the status of the switch and
make the following decision.
(a) If SW = 0, send “NO” to P2.
(b) If SW = 1, send “YES” to P2.
Solution:

Listing 46: Switch Decision Using EQU (by Name)


SW EQU P1.7
MYDATA EQU P2

HERE: MOV C,SW


JC OVER
MOV MYDATA,# ’N ’ ;SW=0, send ”NO”
MOV MYDATA,# ’O ’
SJMP HERE
OVER: MOV MYDATA,# ’Y ’ ;SW=1, send ”YES”
MOV MYDATA,# ’E ’
MOV MYDATA,# ’ S ’
SJMP HERE
END

26
[Example 5-25] A switch is connected to pin P1.7. Write a program to check the status of the switch and
make the following decision.
(a) If SW = 0, send ‘0’ to P2.
(b) If SW = 1, send ‘1’ to P2.
Use EQU to designate the I/O ports.
Solution:

Listing 47: Switch Decision Using EQU (by Address)


SW EQU 97H ; P1.7 b i t a d d r e s s
MYDATA EQU 0A0H ; P2 a d d r e s s

HERE: MOV C,SW


JC OVER
MOV MYDATA,# ’ 0 ’ ; 00110000 t o P2
SJMP HERE
OVER: MOV MYDATA,# ’ 1 ’ ; 00110001 t o P2
SJMP HERE
END

27

You might also like