Microcontroller Notes
Microcontroller Notes
Parameshwara.s
UNIT 1
MICRPROCESSOR AND MICROCONTROLLER
Introduction
Microprocessor: A Microprocessor is a general-purpose digital computer Central
Processing Unit. Although popularly known as a Computer On Chip. Below block
diagram shows the Microprocessor CPU.
Fig.2
MICROCONTROLLERS
Parameshwara.s
Two of the special function registers are shown at the top. These are the instruction
register and the program counter and are used together with the instruction decoder in the
execution cycle.
As was said earlier, the system program is stored in ROM. The program counter
is used for storing the position of the next instruction.
The instruction register is used for storing the current instruction.
The instruction decoder decodes the instruction (ie; it determines, from the
instruction, what operation to perform).
The Execution Cycle
What is meant by execution? It is the CPU's performance of an operation, as dictated
by the current instruction. When an embedded system is powered up (e.g.; you switch on
your mobile phone) the CPU fetches the first instruction from ROM. It then figures out
what operation it must perform, as dictated by the instruction. It performs the operation
and then gets the next instruction from ROM, performs the appropriate operation as
governed by this instruction, then gets the next instruction, and so on.
More specifically, on power up, the location of the first instruction in ROM is loaded
into the program counter (PC). The CPU then fetches the instruction from the location
pointed to by the PC and stores this instruction in the instruction register (IR). The
instruction decoder and control unit decode the instruction and initiate and control the
operation (the actual operation is carried out by the ALU). Then the program counter is
increased, so that it points to the next instruction in ROM and the process is repeated.
To make a complete microcomputer, one must add Memory, I/O devices etc, below fig
shows the Microcomputer block diagram.
MICROCONTROLLERS
Parameshwara.s
As we shall see, much of the work performed by the CPU involves reading from and
writing to memory. There are three busses involved in accessing memory: the address
bus, the data bus and the control bus.
Read Cycle
The steps involved in the read cycle are:
CPU places address on address bus.
Control signals memory - address on address bus is valid.
Memory chip fetches data from location specified by the address and places on
the data bus.
A control signal CPU - data on data bus is valid.
CPU takes data from data bus
Write Cycle
The steps involved in the write cycle are:
CPU places address on address bus.
Control signals memory - address on address bus is valid.
CPU places data on the data bus.
Control signals memory - data on data bus is valid.
Memory chip takes data from data bus and places it in the location specified by
the address.
An embedded system is made up of the basic functional blocks shown above. The
Central Processing Unit (CPU) is the microprocessor and can be thought of as the
system's brain. Memory, input ports and output ports are connected to the microprocessor
through an address bus, a data bus and a control bus. Ports are physical interfaces through
which data is sent to and from external peripherals such as keyboard, monitor etc.
MICROCONTROLLERS
o
Parameshwara.s
ROM, as the name suggests, is read only. You cannot write to a ROM
chip. How then, you may ask, do you get data onto a ROM chip? A ROM
chip must be programmed, but once programmed; it cannot be (easily)
changed.
ROM is non-volatile - when power is removed from the chip data is not
lost.
There are many types of ROM available; PROM, EPROM, EEPROM and Flash are
the most common and we will deal with each at a later date.
Which do we use, RAM or ROM?
The obvious advantage of RAM over ROM is the fact that data can be written to it as
well as read from it. The obvious advantage of ROM over RAM is the fact that data is not
lost on power down. So which is used in embedded systems?
The answer is both.
RAM is used for storing data that is used by the system.
For example, if you wish to heat some food and you set the timer on
your microwave oven for two minutes, this piece of data (2 minutes) is stored
in RAM and used by the system to count down to zero.
o
Another example is the time and date on a VCR. This is also stored in
RAM and is lost once you unplug the VCR. You then need to reset the
time when you plug it in again.
ROM is used for storing the system program. The program is the set of step-bystep instructions for the system to operate.
o If we take the microwave example again; the program tells the oven what
it should do when the user sets a time and presses the 'start' button. If this
data was lost once we unplugged the oven it would be useless. Therefore,
the program is stored in ROM. And since the program doesn't change it
does not matter that we cannot write to the chip. In fact, for safety reasons,
it is better that we cannot write to the chip; we might, accidentally (ie; a
bug in the program) write over some of the program and corrupt the
system.
Therefore, we should always keep in mind the two types of memory. RAM for data,
ROM for the program.
Microcontroller:
MICROCONTROLLERS
CPU
Parameshwara.s
Memory
ROM
Subsystems:
Timers, Counters, Analog
Interfaces, I/O interfaces
RAM
I/O
A single chip
Fig.4 Basic building blocks of Microcontroller.
Above fig shows the diagram of a typical microcontroller, which is a true computer
on chip. The design incorporates all of the features found in a Microprocessor CPU. it has
added the other features needed to make a complete computer i.e. ROM, RAM, I/O
interfaces, Counters, Timers.
A Microcontroller is a general purpose device, but one that is meant to read data,
performs limited calculations on that data, and controls its environment based on those
calculations. The prime use of the MC is to control the operation of a machine using a
fixed program that is stored in ROM and that does not change over the lifetime of the
system.
What's the difference between a microprocessor and a microcontroller?
A microprocessor system consists of a microprocessor with memory, input ports and
output ports connected to it externally. A microcontroller is a single chip containing a
microprocessor, memory, input ports and output ports. Since all four blocks reside on the
one chip, a microcontroller is much faster than a microprocessor system.
Microprocessor
CPU is stand-alone, RAM, ROM, I/O, timer are separate
Designer can decide on the amount of ROM, RAM and I/O ports.
expansive
versatility
general-purpose
MICROCONTROLLERS
Parameshwara.s
Microcontroller
CPU, RAM, ROM, I/O and timer are all on a single chip
fix amount of on-chip ROM, RAM, I/O ports
for applications in which cost, power and space are critical
single-purpose
RISC AND CISC Architecture
CISC: The two most common types of computers are Complex Instruction Set Computer
(CISC) and the Reduced Instruction Set Computer (RISC).
The features of CISC computer are listed as follows:
MICROCONTROLLERS
Parameshwara.s
Only load and store instructions arefer to the memory and may take more than one
clock cycle.
Harvard and Von-Neumann CPU Architecture:
Memory
Address Bus
CPU
Data Bus
Program
+ Data
Von Neumann
Architecture
Memory
Address Bus
CPU
Program
Fetch Bus
Harvard
Architecture
Address Bus
Data Bus
Data
Fig.5
The key feature of the computer architecture developed by Princeton University was
that the computer had common memory for storing the control program as well as
variables and other data structures. E chief scientist for this project was Von-Neumann.
As a name of developer this architecture is best known as Von-Neumann architecture.
Above Fig shows the block diagram of Von-Neumann architecture. It consists of
CPU, memory. In this architecture it is not possible to fetch instruction code and data
simultaneously. However, it is possible to fetch the next instruction when current
instruction is executing. This feature is commonly known as Pre-fetching.
Harvards architecture suggested to have separate memory banks for program storage
(code memory), the processor stack and variable RAM (data memory), as shown in fig.
The Harvard architecture has an advantage of executing instructions in fewer instructions
cycles than Princeton (Von-Neumann) architecture. This is because a much greater
amount of instruction parallelism can be achieved in the Harvard architecture due to
separate memory banks.
Besides the advantage of greater amount of parallelism in Harvard architecture, VonNeumann architecture was preferred by scientist because of the unreliability of
technology of that time. They found single memory architecture more suitable of
computers. Single memory architecture allows greater flexibility in developing software;
primarily contents are accessible to the programmer along with the data.
E&C Dept, NIE,MYSORE
MICROCONTROLLERS
Parameshwara.s
MICROCONTROLLERS
Parameshwara.s
MICROCONTROLLERS
Parameshwara.s
use of the accumulator. More than half of the 8051s 255 instructions manipulate or use
the accumulator in some way.
For example, if you want to add the number 10 and 20, the resulting 30 will be stored
in the Accumulator. Once you have a value in the Accumulator you may continue
processing the value or you may store it in another register or in memory.
The "R" registers:
R1, etc.
The "R" registers are a set of eight registers that are named R0,
These registers are used as auxiliary registers in many operations. To continue with
the above example, perhaps you are adding 10 and 20. The original number 10 may be
stored in the Accumulator whereas the value 20 may be stored in, say, register R4. To
process the addition you would execute the command:
ADD A, R4
After executing this instruction the Accumulator will contain the value 30.
You may think of the "R" registers as very important auxiliary, or "helper", registers. The
Accumulator alone would not be very useful if it were not for these "R" registers.
The "R" registers are also used to temporarily store values. For example, lets say you
want to add the values in R1 and R2 together and then subtract the values of R3 and R4.
One way to do this would be:
MOV A,R3 ;Move the value of R3 into the accumulator
ADD A,R4 ;Add the value of R4
MOV R5,A ;Store the resulting value temporarily in R5
MOV A,R1 ;Move the value of R1 into the accumulator
ADD A,R2 ;Add the value of R2
SUBB A,R5 ;Subtract the value of R5 (which now contains R3 + R4)
As you can see, we used R5 to temporarily hold the sum of R3 and R4. Of course, this
isnt the most efficient way to calculate (R1+R2) - (R3 +R4) but it does illustrate the use
of the "R" registers as a way to store values temporarily.
The B Register: The "B" register is very similar to the Accumulator in the sense that it
may hold an 8-bit (1-byte) value.
The "B" register is only used by two 8051 instructions: MUL AB and DIV AB. Thus, if
you want to quickly and easily multiply or divide A by another number, you may store the
other number in "B" and make use of these two instructions.
Aside from the MUL and DIV an instruction, the B register is often used as yet another
temporary storage register much like a ninth "R" register.
10
MICROCONTROLLERS
Parameshwara.s
The Data Pointer (DPTR): The Data Pointer (DPTR) is the 8051s only user-accessible
16-bit (2-byte) register. The Accumulator, "R" registers, and "B" register are all 1-byte
values.
DPTR, as the name suggests, is used to point to data. It is used by a number of commands
which allow the 8051 to access external memory. When the 8051 accesses external
memory it will access address indicated by DPTR.
While DPTR is most often used to point to data in external memory, many programmers
often take advantage of the fact that its the only true 16-bit register available. It is often
used to store 2-byte values which have nothing to do with memory locations.
The Program Counter (PC): The Program Counter (PC) is a 2-byte address which tells
the 8051 where the next instruction to execute is found in memory. When the 8051 is
initialized PC always starts at 0000h and is incremented each time an instruction is
executed. It is important to note that PC isnt always incremented by one. Since some
instructions require 2 or 3 bytes the PC will be incremented by 2 or 3 in these cases.
The Program Counter is special in that there is no way to directly modify its value. That
is to say, you cant do something like PC=2430h. On the other hand, if you execute LJMP
2430h youve effectively accomplished the same thing.
It is also interesting to note that while you may change the value of PC (by executing a
jump instruction, etc.) there is no way to read the value of PC. That is to say, there is no
way to ask the 8051 "What address are you about to execute?" As it turns out, this is not
completely true: There is one trick that may be used to determine the current value of PC.
This trick will be covered in a later chapter.
The Stack Pointer: The Stack Pointer, like all registers except DPTR and PC, may hold
an 8-bit (1-byte) value. The Stack Pointer is used to indicate where the next value to be
removed from the stack should be taken from.
When you push a value onto the stack, the 8051 first increments the value of SP and then
stores the value at the resulting memory location.
When you pop a value off the stack, the 8051 returns the value from the memory location
indicated by SP and then decrements the value of SP.
This order of operation is important. When the 8051 is initialized SP will be initialized to
07h. If you immediately push a value onto the stack, the value will be stored in Internal
RAM address 08h. This makes sense taking into account what was mentioned two
paragraphs above: First the 8051 will increment the value of SP (from 07h to 08h) and
then will store the pushed value at that memory address (08h).
SP is modified directly by the 8051 by six instructions: PUSH, POP, ACALL, LCALL,
RET, and RETI. It is also used intrinsically whenever an interrupt is triggered.
11
MICROCONTROLLERS
Parameshwara.s
P1.0
P1.1
P1.2
P1.3
P1.4
P1.5
P1.6
P1.7
RST
(RXD)P3.0
(TXD)P3.1
(INT0)P3.2
(INT1)P3.3
(T0)P3.4
(T1)P3.5
(WR)P3.6
(RD)P3.7
XTAL2
XTAL1
GND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
8051
(8031)
40
39
38
37
36
35
34
33
32
31
30
29
28
27
26
25
24
23
22
21
Vcc
P0.0(AD0
P
) 0.1(AD1)
P0.2(AD2
P
) 0.3(AD3)
P0.4(AD4)
P0.5(AD5)
P0.6(AD6)
P0.7(AD7)
EA/VPP
ALE/PROG
PSEN
P2.7(A15)
P2.6(A14
)P2.5(A13
)P2.4(A12
)P2.3(A11)
P2.2(A10)
P2.1(A9)
P2.0(A8)
12
MICROCONTROLLERS
Parameshwara.s
13
MICROCONTROLLERS
Parameshwara.s
to the EA pin, the microcontroller will use both memories, first internal and afterwards
external (if it exists), up to end of address space.
Pin 32-39: Port 0 Similar to port 2, if external memory is not used, these pins can be used
as universal inputs or outputs. Otherwise, P0 is configured as address output (A0-A7)
when the ALE pin is at high level (1) and as data output (Data Bus), when logic zero (0)
is applied to the ALE pin.
Pin 40: VCC Power supply +5V
Input/Output Ports (I/O Ports)
All 8051 microcontrollers have 4 I/O ports, each consisting of 8 bits which can be
configured as inputs or outputs. This means that the user has on disposal in total of 32
input/output lines connecting the microcontroller to peripheral devices.
A logic state on a pin determines whether it is configured as input or output: 0=output,
1=input. If a pin on the microcontroller needs to be configured as output, then a logic
zero (0) should be applied to the appropriate bit on I/O port. In this way, a voltage level
on the appropriate pin will be 0.
Similar to that, if a pin needs to be configured as input, then a logic one (1) should be
applied to the appropriate port. In this way, as a side effect a voltage level on the
appropriate pin will be 5V (as it is case with any TTL input). This may sound a bit
confusing but everything becomes clear after studying a simplified electronic circuit
connected to one I/O pin.
Fig.8
Input/Output Pin: This is a simplified overview of what is connected to a pin inside the
microcontroller. It concerns all pins except those included in P0 which do not have
embedded pull up resFig.9
Output pin:
Logic zero (0) is applied to a bit in the P register. By turning output FE transistor on, the
appropriate pin is directly connected to ground.
14
MICROCONTROLLERS
Parameshwara.s
Fig.10
Input pin:
A logic one (1) is applied to a bit in the P register. Output FE transistor is turned off. The
appropriate pin remains connected to voltage power supply through a pull-up resistor of
high resistance.
Port 0: It is specific to this port to have a double purpose. If external memory is used
then the lower address byte (addresses A0-A7) is applied on it. Otherwise, all bits on this
port are configured as inputs or outputs.
Another characteristic is expressed when it is configured as output. Namely, unlike other
ports consisting of pins with embedded pull-up resistor (connected by its end to 5 V
power supply), this resistor is left out here. This, apparently little change has its
consequences:
Fig.11
If any pin on this port is configured as input then it performs as if it floats. Such
input has unlimited input resistance and has no voltage coming from inside.
Fig.12
When the pin is configured as output, it performs as open drain, meaning that by
writing 0 to some ports bit, the appropriate pin will be connected to ground (0V). By
15
MICROCONTROLLERS
Parameshwara.s
writing 1, the external output will keep on floating. In order to apply 1 (5V) on this
output, an external pull-up resistor must be embedded.
Port 1: This is a true I/O port, because there are no role assigning as it is the case with
P0. Since it has embedded pull-up resistors it is completely compatible with TTL circuits.
Port 2: Similar to P0, when using external memory, lines on this port occupy addresses
intended for external memory chip. This time it is the higher address byte with addresses
A8-A15. When there is no additional memory, this port can be used as universal inputoutput port similar by its features to the port 1.
Port 3: Even though all pins on this port can be used as universal I/O port, they also have
an alternative function. Since each of these functions use inputs, then the appropriate pins
have to be configured like that. In other words, prior to using some of reserve port
functions, a logical one (1) must be written to the appropriate bit in the P3 register. From
hardwares perspective, this port is also similar to P0, with the difference that its outputs
have a pull-up resistor embedded.
Current limitations on pins
When configured as outputs (logic zero (0)), single port pins can "receive" current of
10mA. If all 8 bits on a port are active, total current must be limited to 15mA (port P0:
26mA). If all ports (32 bits) are active, total maximal current must be limited to 71mA.
When configured as inputs (logic 1), embedded pull-up resistor provides very weak
current, but strong enough to activate up to 4 TTL inputs from LS series.
External Memory: In order to satisfy the programmers permanent hunger for Data
Memory, producers have embedded an additional memory block of 128 locations into the
latest versions of the 8051 microcontrollers. Naturally, its not so simpleThe problem is
that electronics performing addressing has 1 byte (8 bits) on disposal and due to that it
can reach only the first 256 locations. In order to keep already existing 8-bit architecture
and compatibility with other existing models a little trick has been used.
Using trick in this case means that additional memory block shares the same
addresses with existing locations intended for the SFRs (80h- FFh). In order to
differentiate between these two physically separated memory spaces, different ways of
addressing are used. A direct addressing is used for all locations in the SFRs, while the
locations from additional RAM are accessible using indirect addressing.
16
MICROCONTROLLERS
Parameshwara.s
17
MICROCONTROLLERS
Parameshwara.s
When the program during execution encounters the instruction which resides in
external memory (ROM), the microcontroller will activate its control output ALE
and set the first 8 bits of address (A0-A7) on P0. In this way, IC circuit
74HCT573 which "lets in" the first 8 bits to memory address pins is activated.
A signal on the pin ALE closes the IC circuit 74HCT573 and immediately
afterwards 8 higher bits of address (A8-A15) appear on the port. In this way, a
desired location in additional program memory is completely addressed. The only
thing left over is to read its content.
Pins on P0 are configured as inputs, the pin PSEN is activated and the microcon
troller reads content from memory chip. The same connections are used both for
data and lower address byte.
Similar occurs when it is a needed to read some location from external Data Memory.
Now, addressing is performed in the same way, while reading or writing is performed via
signals which appear on the control outputs RD or WR.
Note: Counter and Timers, Serial Data Input/Output, Interrupts are will study in detail in
Unit 5, 6, 7 respectively.
18
MICROCONTROLLERS
Parameshwara.s
UNIT 2
MICROCONTROLLERS
Parameshwara.s
Immediate addressing is very fast since the value to be loaded is included in the
instruction. However, since the value to be loaded is fixed at compile-time it is not very
flexible.
Direct Addressing
Direct addressing is so-named because the value to be stored in memory is obtained by
directly retrieving it from another memory location. For example:
MOV A, 30h
MOV R0, 12H
MOV 8CH, R7
MOV 3AH, #3AH
MOV 0A8H, 77H
Direct addressing is generally fast since, although the value to be loaded isnt included
in the instruction, it is quickly accessible since it is stored in the 8051s Internal RAM. It
is also much more flexible than Immediate Addressing since the value to be loaded is
whatever is found at the given address--which may be variable.
Also, it is important to note that when using direct addressing any instruction which
refers to an address between 00h and 7Fh is referring to Internal Memory. Any instruction
which refers to an address between 80h and FFh is referring to the SFR control registers
that control the 8051 microcontroller itself.
The obvious question that may arise is, "If direct addressing an address from 80h
through FFh refers to SFRs, how can I access the upper 128 bytes of Internal RAM that
are available on the 8051?" The answer is: You cant access them using direct addressing.
As stated, if you directly refer to an address of 80h through FFh you will be referring to
an SFR. However, you may access the 8051s upper 128 bytes of RAM by using the next
addressing mode, "indirect addressing."
Indirect Addressing
Indirect addressing is a very powerful addressing mode which in many cases provides an
exceptional level of flexibility. Indirect addressing is also the only way to access the extra
128 bytes of Internal RAM found on an 8051.
Indirect addressing appears as follows:
MOV A, @R0
MOV @R1, #35H
MOV @R0, A
20
MICROCONTROLLERS
Parameshwara.s
This instruction causes the 8051 to analyze the value of the R0 register. The 8051 will
then load the accumulator with the value from Internal RAM which is found at the
address indicated by R0.
For example, lets say R0 holds the value 40h and Internal RAM address 40h holds the
value 67h. When the above instruction is executed the 8051 will check the value of R0.
Since R0 holds 40h the 8051 will get the value out of Internal RAM address 40h (which
holds 67h) and store it in the Accumulator. Thus, the Accumulator ends up holding 67h.
Indirect addressing always refers to Internal RAM; it never refers to an SFR. Thus, in a
prior example we mentioned that SFR 99h can be used to write a value to the serial port.
Thus one may think that the following would be a valid solution to write the value 1 to
the serial port:
MOV R0, #99h
; Load the address of the serial port
MOV @R0, #01h ; Send 01 to the serial port -- WRONG!!
This is not valid. Since indirect addressing always refers to Internal RAM these two
instructions would write the value 01h to Internal RAM address 99h on an 8052. On an
8051 these two instructions would produce an undefined result since the 8051 only has
128 bytes of Internal RAM.
External Direct
External Memory is accessed using a suite of instructions which use what I call "External
Direct" addressing. I call it this because it appears to be direct addressing, but it is used to
access external memory rather than internal memory.
There are only two commands that use External Direct addressing mode:
MOVX A, @DPTR
MOVX @DPTR , A
As you can see, both commands utilize DPTR. In these instructions, DPTR must first be
loaded with the address of external memory that you wish to read or write. Once DPTR
holds the correct external memory address, the first command will move the contents of
that external memory address into the Accumulator. The second command will do the
opposite: it will allow you to write the value of the Accumulator to the external memory
address pointed to by DPTR.
External Indirect
External memory can also be accessed using a form of indirect addressing which I call
External Indirect addressing. This form of addressing is usually only used in relatively
small projects that have a very small amount of external RAM. An example of this
addressing mode is:
MOVX @R0, A
21
MICROCONTROLLERS
Parameshwara.s
Once again, the value of R0 is first read and the value of the Accumulator is written to
that address in External RAM. Since the value of @R0 can only be 00h through FFh the
project would effectively be limited to 256 bytes of External RAM. There are relatively
simple hardware/software tricks that can be implemented to access more than 256 bytes
of memory using External Indirect addressing; however, it is usually easier to use
External Direct addressing if your project has more than 256 bytes of External RAM.
The letter C is added to the MOV Mnemonic to highlight the use of the opcodes for
moving data from the source address in the code ROM to the A register
Examples:
MOVC A, @A+DPTR
MOVC A, @A+PC
22
MICROCONTROLLERS
Parameshwara.s
23
MICROCONTROLLERS
Parameshwara.s
A POP opcode copies data from stack to the destination address. SP is decremented by 1
after data is copied from the stack RAM address to the direct destination to ensure that
data placed on the stack is retrieved in the same order as it was stored.
PUSH
add
POP
add
; copy the data from the internal RAM address contained in SP to add;
Decrement the SP.
Example: MOV 81H, #30H
; copy the immediate data 30h to the SP
MOV R0, #0ACH
; copy the immediate data ACh to the R0
PUSH 00H
; SP=31h; address 31h contais the ACh
PUSH 00H
; SP=32h; address 32h contais the ACh
POP
01H
; SP=31h; register R1 now contain the number ACh
POP 80H
; SP=30h; port 0 latch now contain the number Ach
DATA Exchange:
Exchange instructions actually move data in two directions, from source to destination
and from destination to source. All addressing modes except immediate may be used in
the XCH instruction.
XCH
XCH
XCH
XCH
A, Rr
A, add
A, @Rp
A, @Rp
A, #n
A, add
A, Rr
A, @Rp
ANL add, A
ANL add, #n
24
ORL
ORL
ORL
ORL
ORL
ORL
A, #n
A, add
A, Rr
A, @Rp
add, A
add, #n
XRL
XRL
XRL
XRL
XRL
XRL
A, #n
A, add
A, Rr
A, @Rp
add, A
add, #n
CLR A
CPL A
Bit level logical operations:
Certain internal RAM and SFRs can be addressed by their byte addresses or by the
address of each bit within a byte. Bit addressing is very convenient when you wish to
alter a single bit of a byte.
Internal RAM bit addresses: The available of Individual bit addresses in internal RAM
makes the use of the RAM very efficient when storing bit information.
The corresponding between byte and bit address is shown in fig 7 Programming model of
8051. (Refer back page).
SFR Bit Addresses: All SFRs may be addressed at byte level by using the direct address
assigned to it, but not all of the SFRs are addressable at the bit level. The corresponding
between byte and bit address is shown in fig 7 Programming model of 8051. (Refer back
page).
The following lists the Boolean bit level operations.
ANL C, b
; AND C and the addressed bit; put the result in C.
ANL C, /b
; AND C and compliment of the addressed bit; put the result in C; the
addressed bit is not altered.
ORL C, b
; OR C and the addressed bit; put the result in C.
ORL C,/b
; OR C and compliment of the addressed bit; put the result in C; the
addressed bit is not altered.
CPL C
; complement the C
CPL b
; complement the addressed bit
CLR C
; Clear the C flag to 0
CLR b
; Clear the addressed bit b to 0
MOV C, b ; copy the addressed bit to C
MOV b, C ; copy the C flag to addressed bit
SETB C
; set the flag to 1
SETB b
; set the addressed bit to 1.
Each bit is shifted one location to the right, with bit 0 going to bit 7.
RL A
Rotate left the accumulator.
Each bit is shifted one location to the left, with bit 7 going to bit 0.
Rotating through the Carry
There are two instructions that, in effect, create a 9-bit rotate register.
RRC
Rotate right through the carry.
Each bit is shifted one location to the right, with bit 0 going into the carry bit in the PSW,
while the carry was at goes into bit 7 (ie; if the carry was set prior to the execution of
RRC A, then bit 7 of the accumulator will contain 1 after execution of RRC A. Similarly, if
the carry was clear prior to execution of RRC A, then bit 7 of the accumulator will contain
0 after execution of RRC A).
RLC A
Rotate left through the carry.
Each bit is shifted one location to the left, with bit 7 going into the carry bit in the PSW,
while the carry goes into bit 0.
SWAP A
High Nibble
Low Nibble
Interchange the nibbles of register A; put the high nibble in the low nibble position and
the low nibble in the high nibble position.
Arithmetic Operations:
Incrementing and Decrementing: the simplest arithmetic operations involve adding or
subtracting a binary 1 and a number. These simple operations become very powerful
when coupled with the ability to repeat the operation that is to increment or decrement
until a desired result is reached. Register, direct, and indirect addressing may be
incremented or decremented. No math flags are affected.
The following are the Increment and decrement Mnemonics:
INC
INC
INC
INC
INC
DEC
DEC
DEC
DEC
A
Rr
add
@Rp
DPTR.
A
Rr
add
@Rp
Addition: All addition is done with the A register as the destination of the result. All
addressing modes may be used for the source.
The following lists the addition Mnemonics:
ADD
ADD
ADD
ADD
A, #n
A, Rr
A, add
A, @Rp
Subtraction: subtraction can be done by taking the twos complement of the number to
be subtracted, the subtrahend, and adding it to another number, the minuend. Register A
is the destination address for subtraction. All addressing modes may be used for source
addresses. The commands treat the carry flag as a borrow and always subtract the carry
flag as part of the operation.
The following lists the Subtraction Mnemonics:
SUBB A, #n
SUBB A, add
SUBB A, Rr
SUBB A, @Rp
Multiplication: Multiplication operation uses registers A and B as both source and
destination addresses for the operation.
Mnemonic is
MUL AB ; multiply A by B ; put the low-order byte of the product in A, put the high
Order byte in B
Division: Division operation uses registers A and B as both source and destination
addresses for the operation.
Mnemonic is
DIV AB
; divide A by B; put the integer part of quotient in register A and the integer
Part of the remainder in B.
Decimal Arithmetic: Most 8051 applications involve adding intelligence to machine
where the hexadecimal Numbering system works naturally. There are instances, however,
when application involves interacting with humans, who insist on using the decimal
number system.
Mnemonic is
DA A ; Adjust the sum of two packed BCD numbers found in A register; leave the
Adjusted number in A.
UNIT 3
Jump and Call Instructions
A jump or call instruction can replace the contents of the program counter with a new
program address number that causes program execution to begin at the code located at the
new address. The difference, in bytes, of this new address from the address in the
program where the jump or call is located is called the range of the jump or call.
Jump or call instructions may have one of three ranges: a relative range of + 127d, -128d
bytes from the instruction following the jump or call instruction, an absolute range on the
same 2K byte page as the instruction following the jump or call, or a long range of any
address from 0000h to FFFFh, any where in program memory. Fig 15 shows the relative
range of all the jump instructions.
Fig 15
Relative Range: Jumps that replaces the program counter contents with a new address
that is greater than the address of the instruction following the jump by 127d or less than
the address of the instruction following the jump by 128d are called relative ump.
Relative jumping has two advantages. 1. Only 1 byte of data need be specified, either
in positive format for jumps ahead in the program or in 2s compliment negative format
for jumps behind. The jump address displacement byte can then be added to the PC to get
the absolute address. Specifying only 1 byte saves program bytes and speeds up program
execution.
2. The program that is written using relative jumps can be located anywhere in the
program address space.
The disadvantage of using relative addressing is the requirement that all address
jumped be within a range of +127d, -128d bytes of the jump instruction. This range is not
a serous problem. Most jumps form program loops over short code range that are within
the relative range. If jumps beyond the relative range are needed, then a relative jump can
be done to another relative jump until the desired address is reached.
Short Absolute Range: Absolute range makes use of the concept of dividing memory
into logical divisions called pages. Program memory may be regarded as one continuous
stretch of address from 0000h to FFFFh. Or it may be divided into a series of pages of
any convenient binary size, such 256 bytes, 2K, and 4K and so on.
Absolute range addressing has the same advantage as relative addressing; fewer bytes are
needed and code is relocateble as long as the relocated code begins at the start of a page.
Long Absolute Range: Address that can access the entire program space from 0000h to
FFFFh use long-range addressing. Long range addresses require more bytes of code to
specify and are relocatable only at the beginning of 64K pages. Long range addressing
has the advantage of using entire program address space available to the 8051. it most
likely to be used in large programs.
Bit Jump: Bit jump all operate according to the status of the Carry flag in the PSW or
the status of any bit addressable location. All bit jumps are relative to the program
counter.
Bit Jump Instructions are:
JC radd
; jump relative if the carry flag is set to 1
JNC add
; jump relative if the carry flag is reset to 0
JB b, radd
; jump relative if address bit is set to 1
JNB b, radd
; jump relative if address bit is is reset to 0
JBC b, radd
; jump relative if address bit is set, and clear the addressable bit to 0.
Byte Jumps: Byte jumps jump instructions that test bytes of data behave as bit jumps.
If the condition that is tested is true, the jump is taken, if the condition is false, the
instruction after the jump is executed. All bytes jumps are relative to the program counter.
CJNE A, add, radd ; compare the contents of the A register with the contents of the
address; if they are not equal, then jump to the relative address; set carry flag to 1 if a is
less than the contents of the direct address; otherwise, set the carry flag to 0.
CJNE A, #n, radd: compare the contents of the A register with the immediate number
if they are not equal, then jump to the relative address; set carry flag to 1 if a is less than
the contents of the direct address; otherwise, set the carry flag to 0.
CJNE @Rp, #n, radd: compare the contents of the Rp register with the immediate
number; if they are not equal, then jump to the relative address; set carry flag to 1 if a is
less than the contents of the direct address; otherwise, set the carry flag to 0.
DJNZ Rn, radd: Decrement the register Rn by 1 and jump to the relative address if the
result is not 0; no flags are affected.
DJNZ add, radd: : Decrement the direct address by 1 and jump to the relative address
if the result is not 0; no flags are affected unless the direct address is the PSW.
JZ radd: jump to the relative address if A is 0; the flag and the A register are not
changed.
JNZ radd: jump to the relative address if A is not 0; the flag and the A register are not
changed.
This instruction is prefect for the time delay program, as detailed below.
MOV R0, 0FFH
DJNZ R0,$
The $ Operator
Most assemblers use the $ character as a pointer to the current program location.
Therefore, the instruction DJNZ R0, $ means - decrement the contents of R0 and if the
result is non-zero jump back to this line. In this way, the contents of R0 are continuously
decremented until they reach zero.
Longer Delays
As stated above, the longest single-loop delay is achieved by initialising the decrement
register (ie; the register that will be decremented) to FFH. To achieve longer delays we
can use multiple-loop time delays, as detailed in the flow chart below.
The inner loop (nested loop) takes 255 iterations before R1 reaches 0. When this happens,
the loop is exited and R0 is decremented. If R0 is not equal to zero the program jumps
back to the line that loads R1 with FFH again. Another 255 iterations of the nested loop
must occur before R0 is decremented again. Therefore, for every one iteration of the
outer loop there are 255 iterations of the inner loop.
We control the length of the time delay by changing the value loaded into R0. If R0 is
initialized to 03H, then the overall number of iterations is 3 * 255 = 765.
The maximum number of iteration for a two-loop time delay is 255 * 255 = 65025.
Calling a Subroutine from within a Subroutine
To write a three-loop delay we could create two nested loops inside a third outer loop as
detailed in the flowchart below.
Take note that the inner two loops are identical to the maximum two-loop delay shown
above. Therefore, if we write the three-loop delay in this manner we must rewrite the twoloop delay and test it. This is not an efficient programming practice. It would be better if
we reused our two-loop delay as detailed in the flowchart below.
The inner two-loop delay is replaced by a call to our original maximum two-loop delay.
In this manner we are reusing the code that was written and tested earlier.
The code for the above three-loop delay is:
DELAY3:
MOV R2,#0A0H
Loop: CALL DELAY2
DJNZ R2, Loop
RET
And the Code for the DELAY2 is:
DELAY2 :
MOV R0,#0FFH
LoadR1:
MOV R1, #0FFH
DJNZ R1, $
DJNZ R0, LoadR1
RET
Calling the three-loop delay will therefore result in 10 * 255 * 255 iterations.
We can now use our two delays for flashing the LED at something other than a 50% duty
cycle.
start:
SETB P1.0
CALL DELAY
CLR P1.0
CALL DELAY
JMP start
The above program sets the least significant bit of port 1 and then calls the two-loop
delay, after which it clears the least significant bit of port 1 and calls the three-loop delay.
The three-loop delay itself calls the two-loop delay ten times. Therefore, the LED (on
P1.0) will be off for approximately ten times longer than it is on.
Subroutines and the Stack
We have already looked at calling a subroutine in the previous section. Now we will look
at the actual call instructions and the effect they have on the stack.
Unconditional Jumps: unconditional jumps do not test any bit or byte to determine
whether the jump should be taken. The jump always taken.
JMP @A + DPTR : jump to the address formed by adding A to the DPTR; this is an
unconditional jump and will always be done; the address can be anywhere in program
memory; A the DPTR, and the flags are unchanged.
AJMP sadd : jump to a absolute short range address sadd ;this is an unconditional jump
and is always taken; and the flags are unchanged.
LJMP ladd : jump to a absolute long range address ladd ;this is an unconditional jump
and is always taken; and the flags are unchanged.
SJMP sadd : jump to a absolute relative address radd ;this is an unconditional jump and
is always taken; and the flags are unchanged.
NOP: Do nothing and go to the next instruction; NOP is used to waste time in a software
timing loop, or to leave room in a program for later additions; no flags are affected.
Calls and Subroutine: Changing execution of program by checking the external
conditions by moving data from the port pins to a location and jumping on the conditions
of the port pin data. This technique is called polling.
Another method of changing program execution is using interrupt signals on certain
external pins or internal registers to automatically cause a branch to a smaller program
that deals with the specific situation. When the event that caused the interruption has been
dealt with, the program resumes at the point in the program where the interruption took
place. Interrupt action can also be generated using software instructions named calls.
Subroutine: A subroutine is a program that may be used many times in the execution of
a larger program. The subroutine could be written into the body of the main program.
Everywhere it is needed, resulting in the fastest possible code execution.
Calls and the Stack: A call, whether hardware or software initiated, causes a jump to the
address where the called subroutine is located. At the end of the subroutine the program
resumes operation at the opcode address immediately following the call.
The stack area of internal RAM is used to automatically store the address, called the
return address, of the instruction found immediately after the call. The stack pointer
register holds the address of the last space used on the stack.
Fig 16 diagrams the following sequences of events:
LCALL ladd: call the subroutine located any where in program memory space; push
the address of the instruction immediately after the call on the stack.
RET: POP 2 bytes from the stack into the program counter.
1. Write an ALP to Move a block of data ( N=5) from location 8035h to another
memory location 8045h.
org 0000H
mov dph,#80h
mov r0,#35h
mov r1,#45h
mov r3,#05h
back:mov dpl,r0
movx a,@dptr
mov dpl,r1
movx @dptr,a
inc r0
inc r1
djnz r3,back
here:sjmp here
end
Result: BE 8035: 01 02 03 04 05AE 8045:01 02 03 04 05.
2. Write an ALP to interchange a block of data location 30h and the 40h.
org 00h
mov r0,#30h
mov r1,#40h
mov r2,#05h
back: mov a,@r0
xch a,@r1
mov @r0,a
inc r0
inc r1
djnz r2,back
here:sjmp here
end
Result: BE : 30h:01 02 03 04 05
40h:06 07 08 09 0A
AE: 30h; 06 07 08 09 0A
40: 01 02 03 04 05
org 0000h
mov dph,#80h
mov r0,#60h
mov r1,#70h
mov r2,#06h
back:mov dpl,r0
movx a,@dptr
mov r4,a
mov dpl,r1
movx a,@dptr
xch a,r4
movx @dptr,a
mov a,r4
mov dpl,r0
movx @dptr,a
inc r0
inc r1
djnz r2,back
here:sjmp here
end
Result:
BE 8060h: 01 02 03 04 05
8070h: 06 07 08 09 0A
AE: 8060h:06 07 08 09 0A
8070h:01 02 03 04 05
4. Write an ALP to find the Smallest of N-numbers, the numbers are stored in
starting address 8000h and store the result in next location of last element
org 0000h
mov dptr,#8000h
mov r0,#05
movx a,@dptr
mov r1,a
back:inc dptr
movx a,@dptr
clr c
movx a,@dptr
mov r2,a
subb a,r1
jnc next
mov a,r2
mov r1,a
next:djnz r0,back
mov a,r1
inc dptr
movx @dptr,a
here:sjmp here
end
Result: BE: 8000h: 06 07 04 02 03
AE: 8000h: 06 07 04 02 03 02
5. Write an ALP to find the Largest of N-numbers, the numbers are stored in starting
address 8000h and store the result in next location of last element
org 0000h
mov dptr,#8000h
mov r0,#05
movx a,@dptr
mov r1,a
back: inc dptr
clr c
movx a,@dptr
mov r2,a
subb a,r1
jc next
mov a,r2
mov r1,a
next:djnz r0,back
mov a,r1
inc dptr
movx @dptr,a
here:sjmp here
end
Result: BE: 8000h: 06 07 04 02 03
AE: 8000h: 06 07 04 02 03 07
6. Write an ALP to arrange the number in ascending /Descending order the given
numbers are stored from location 8000h.
org 0000h
mov r0,#05h
again:mov dptr,#8000h
mov r1,#05h
back:mov r2,dpl
movx a,@dptr
mov b,a
inc dptr
movx a,@dptr
cjne a,0f0h,next
ajmp skip
next:jnc skip
// for descending order Jc
mov dpl,r2
movx @dptr,a
inc dptr
mov a,0f0h
movx @dptr,a
skip:djnz r1,back
djnz r0,again
here:sjmp here
end
Result: BE: 8000h: 06 07 04 02 03
AE: 8000h: 02 03 04 06 07
org 00h
mov a,#99h
back:acall delay
add a,#99h
da a
jz back
here :sjmp here
delay: mov r1,#0ffh
dec2 :mov r2,#0ffh
dec1:mov r3,#0ffh
next:djnz r3,next
djnz r2,dec1
djnz r1,dec2
ret
end
11. Write an ALP to perform the following operation
If X=00; perform the operation A+B
Else if X=01perform the operation A-B.
Else if X=02 perform the operation A*B.
Else if X=03 perform the operation A/B.
org 0000h
mov r0,#40h
mov r1,#41h
mov a,@r1
inc r1
mov b,@r1
cjne @R0,#00,next
add a,b
sjmp last
next:cjne @r0,#01,nxt1
subb a,b
jnc dn
mov b,#0ffh
dn:sjmp last
nxt1:cjne @r0,#02,nxt2
mul ab
sjmp last
nxt2:cjne @r0,#03,nxt3
div ab
sjmp last
nxt3:mov a,#00h
mov b,#00h
last:inc r0
mov @r0,a
inc r0
mov @r0,b
here:sjmp here
end
Result: BE: 1. 40h: 00 07 04
2. 40h: 01 04 07
3. 40h: 02 03 03
4. 40h: 03 03 06
AE: 40h: 00 0B 00
40h: 01 03 00
40h: 02 09 00
40h: 03 02 00
12. Three 8-bit Nos X , N1 and N2 are stored in internal RAM locations 20h,21h,and
22h respectively. Write an ALP to completing the following.
If X=00: perform N1 AND N2.
If X=01: perform N1 OR N2.
If X=02: perform N1 XOR N2. Else result is 00. The result location is 23h.
Org 00h
Mov R0,#20h
Movx a, @R0
Inc R0
Mov a,R0
Mov b,a
Inc R0
Mov a,@R0
Cjne R1,#00,0r1
Anl a,b
Sjmp last
Or1: Cjne r1,#01,xor1
Orl a,b
Sjmp last
Xor1: Cjne r1,#02,other
Xrl a,b
Other: Clr a
Last : Inc r0
Mov @r0,a
Here:Sjmp here
End
Result: BE: 20h: 00 02 03
20h: 01 02 03
20h: 02 02 03
20h: 03 02 03
AE: 20h: 00 02 03 02
20h: 01 02 03 03
20h: 02 02 03 01
20h: 03 02 03 00
13. Two 8- bit Nos N1 and N2 are stored in external memory location X and Y
Respectively write an ALP to compare the two No;s, reflect your result as if
N1<N2 set LSB of the RAM as 2Fh. If N1>N2 set MSB of location 2Fh. If
N1==N2, clear bouth LSB and MSB of bit addressable memory location 2Fh.
Org 00h
Mov dptr, #8000h
Movx a,@dptr
Mov b,a
Inc dptr
Movx a, @dptr
Cjne a,0f0,next
Clr 7fh
Clr 78h
Sjmp last
Next:Jnc sett
Setb 7fh
Sjmp last
Sett:Setb 78h
Sjmp last
Last: sjmp last
End
Result: BE: 8000h: 06 07
8000h: 07 06
8000h: 06 06
AE: 2Fh: 01
AE: 2Fh: 80
AE: 2Fh: 81
1. An array of elements stored in location 4000h, Write an ALP to sort out the
EVEN and ODD numbers in location 5000h onwards and ODD numbers is
location 6000h onwards.
org 00h
mov r0,#0ah
mov r1,#00h
mov r2,#40h
mov r3,#00h
mov r4,#50h
mov r5,#00h
mov r6,#60h
back:mov dpl,r1
mov dph,r2
movx a,@dptr
jb acc.0,next
mov dpl,r3
mov dph,r4
movx @dptr,a
inc r3
sjmp next1
next:mov dpl,r5
mov dph,r6
movx @dptr,a
inc r5
next1:inc r1
djnz r0,back
here:sjmp here
end
Result: BE: 4000h: 06 07 04 02 03 08 05 01 09 0A
AE: 5000h: 07 03 05 09 6000h: 06 04 02 08 0A
2. Write an ALP to perform the Conversion of an 8-bit BCD number to
Hexadecimal.
org 00h
mov a,#45
anl a,#0f0h
swap a
mov b,#0ah
mul ab
mov r0,a
mov a,#45h
anl a,#0fh
add a,r0
here:sjmp here
end
AE: A= 3F
3. Write an ALP to Convert BCD to ASCII.
org 00h
mov r0,#30h
mov a,@r0
mov r1,a
anl a,#0fh
add a,#30H
inc r0
mov @r0,a
mov a,r1
anl a,#0f0h
swap a
add a,#30h
inc r0
mov @r0,a
here:sjmp here
end
Result: BE: 30h: 06
AE: 30h: 36
AE: 8000h: 05 05 02
mov r3,a
anl a,#0fh
acall ascii
inc r0
mov @r0,a
mov a,r3
anl a,#0f0h
swap a
acall ascii
inc r0
mov @r0,a
here:sjmp here
ascii:mov r4,a
subb a,#0ah
mov a,r4
jnc skip
sjmp last
skip:add a,#07h
last:add a,#30h
ret
end
Result: BE: 40h: 0B
AE: 40h: 42
org 0000h
mov r1,#00
back:mov a,r1
mov b,a
mul ab
cjne a,#64,next
sjmp last
next:inc r1
sjmp back
last:mov a,r1
mov r2,a
here:sjmp here
end
AE: R2= 08
19. Write an ALP to search the given number is present in the array on N numbers
org 0000h
mov dptr,#2000h
mov r1,#00h
mov r2,#00h
mov r3,#05h
back:movx a,@dptr
cjne a,#66h,next
mov r1,dpl
mov r2,dph
sjmp last
next:inc dptr
djnz r3,back
last:mov a,r1
mov dptr,#2200h
movx @dptr,a
mov a,r2
inc dptr
movx @dptr,a
here:sjmp here
end
Result: BE: 2000h: 06 66 04 02 03
AE: 2200h: 01 20
20. Write an ALP to Find the Nos of 0s and 1s are present in a byte of data.
org 0000h
mov r0,#50h
mov r3,#00h
mov r4,#00h
mov r5,#08h
mov a,@r0
back:rrc a
jc skip
inc r4
sjmp last
skip: inc r3
last: djnz r5,back
mov a,r3
inc r0
mov @r0,a
inc r0
mov a,r4
mov @r0,a
here:sjmp here
end
Result: BE: 50h: 06
AE: 50h: 02 06 02
UNIT 4
8051 Programming in C
Why Program the 8051 in C?
Compilers produce the hex files that we download into the ROM of the microcontroller.
The size of the hex file produced by the compiler is one of the main concerns of
microcontroller programmers, for two reasons.
1. Microcontrollers have limited on-chip ROM.
2. The code space for the 8051 is limited to 64K bytes.
The following are some of the major reasons for writing program in C instead of
Assembly.
Unsigned int: The unsigned data type is a 16-bit data type that a value in the range of 0
to 65535. in the 8051, unsigned int is used to define 16-bit variables such as memory
addresses. It is also set counter values of more than 256.
Signed int: signed int is a 16-bit data type that uses most significant bit to represent the
or + value. As a result, we have only 15 bits for the magnitude of the number, or values
from -32,768 to +32,767.
sbit(single bit): The sbit keyword is a widely used 8051 C data type designed
specifically to access single-bit addressable registers. It allows access to the single bit of
the SFR registers.
Bit and sfr: the bit data type allows access to single bits of bit-addressable memory
spaces 20h-2Fh. Notice that while the sbit data type is used for bit-addressable SFR.
To access the byte-size SFR register, we use sfr data type.
Examples:
1. Write an 8051 C program to send values 00-FF to port P1.
Solution:
#include<reg51.h>
void main (void)
{
unsigned char z;
for (z = 0 ; z <= 255 ; z++)
P1 = z;
}
2. Write an 8051 C program to send hex values for ASCII characters of 1, 2, 3, 4, 5, A, B,
C and D to port P1.
Solution:
#include<reg51.h>
void main (void)
{
unsigned char mynum[] = 012345ABCD ;
unsigned char z;
for (z = 0 ; z <= 255 ; z++)
P1 = mynum[z];
}
In either case, when we write a time delay we must use the oscilloscope to measure the
duration of our time delay.
In creating a time delay using a for loop, three factors that can affect the accuracy of the
delay.
1. The number of machine cycles and the number of clock periods per machine cycle
vary among different versions of the 8051/52 microcontroller. While the original
8051/52 design used 12 clock periods per machine cycle, many of the newer
generations of the 8051 use the fewer clock per machine cycle. For example the
DS5000 uses 4 clock periods per machine cycle, while the DS89C420 uses only one
clock per machine cycle.
2. The crystal frequency connected to the X1-X2 input pins. The duration of the clock
period for the machine cycles is a function of this crystal frequency.
3. Compiler choice. The third factor that affects the time delay is the compiler used to
compiler the C program. When we program in Assembly language, we can control the
exact instructions and sequences used in the delay subroutine. In the case of C
programs, it is the C compiler that converts the C statements and functions to
Assembly language instructions. As a result different compilers produce different
code.
Example .
1. Write an 8051 C program to toggle the all the bits of P2 continuously with a 250msec.
Solution:
#include<reg51.h>
Void msdelay (unsigned int );
void main (void)
{
for ( ; ;)
{
P0 = 0x55;
P2 = 0x55;
Msdelay(250);
P0 = 0xAA;
P2 = 0xAA;
Msdelay(250);
}}
void Msdelay(unsigned int itime)
{
unsigned int i, j;
for ( I = 0; i< itime ; i++)
for ( j = 0; j< 1275 ; j++) }
2. LEDs are connected to bits P1 and P2. Write an 8051 C program that shows the count
from 0 to FFh on the LEDs.
Solution:
#include<reg51.h>
#define LED P2
void main (void)
{
P1 = 00;
LED = 0;
for ( ; ;)
{ P1++;
LED++;}}
3. Write an 8051 C program to get a byte of data from P1, wait second, and then send it
to P2.
Solution:
#include<reg51.h>
void msdelay (unsigned int);
void main (void)
{
unsigned char mybyte;
P1 = 0xFF;
while (1)
{
mybyte = P1;
msdelay (500);
P2 = mybyte;
}
}
void msdelay (unsigned int itime);
{ unsigned int i , j;
for (i = 0 ; i <= itime ; i++)
for (j= 0 ; j <= 1275 ; j++)
}
4. Write an 8051 C program to get a byte of data from P1, wait second, and then send it
to P2.
Solution:
#include<reg51.h>
void main (void)
{
unsigned char mybyte;
P0 = 0xFF;
while (1)
{
mybyte = P0;
ef ( mybyte< 100 )
P1 = mybyte;
else
P2 = mybyte;
}
}
5. Write an 8051 C program to toggle only bit P2.4 continuously without the rest of the
bits of P2.
Solution:
#include<reg51.h>
sbit mybit = P2^4;
void main (void)
{
for ( ; ;)
{
mybit = 1;
mybit = 0;
}}
6. Write an 8051 C program to monitor bit P1.5.if it is high, send 55H to P0; otherwise,
send AAH to P2.
Solution:
#include<reg51.h>
sbit mybit = P1^5;
void main (void)
{
mybit = 1;
for ( ; ;)
{
if(mybit = = 1);
P0 = 0x55;
else
P2 = 0xAA;
}}
7. A door sensor is connected to the P1.1 pin, and a buzzer is connected to P1.7. write an
8051 C program to monitor the door sensor, and when it opens, sound the buzzer. You
can sound the buzzer by sending a square wave of a few hundred Hz.
Solution:
#include<reg51.h>
void msdelay (unsigned int);
sbit dsensor = P1^1;
sbit Buzzer = P1^7;
void main (void)
{dsensor = 1;
while = 0;
msdelay(200);
buzzer = 1;
msdelay(200);
}
}
void msdelay (unsigned int itime)
{
unsigned int i, j;
for ( i = 0; i< itime ; i++)
for ( j = 0; j< 1275 ; j++)
}
8. The data pins of an connected to P1. the information is latched into the LCD whenever
its Enable pin goes from high to low. Write an 8051 C program to send the Earth is but
one country to this LCD.
Solution:
#include<reg51.h>
#define LCDdata P1
sbit En = P2^0;
void main (void)
{
unsigned char message[] = the Earth is but one country ;
unsigned char z;
for ( z = 0; z<28;z++)
{ LCDdata = message[z] ;
En = 1;
En = 0;
}}
9. Write an 8051 C program to toggle all the bits 0f P0, P1, and P2 continuously with a
250msec delay. Use the sfr keyword to decline the port addresses.
Solution:
sfr P0 = 0x80;
sfr P1 = 0x90;
sfr P2 = 0xA0;
void msdelay (unsigned int);
void main (void)
{
P0 = 0x55;
P1 = 0x55;
P2 = 0x55;
msdelay (250);
P0 = 0xAA;
P1 = 0xAA;
P2 = 0xAA;
msdelay (250);
}}
void msdelay (unsigned int itime)
{
unsigned int i, j;
for ( i = 0; i< itime ; i++)
for ( j = 0; j< 1275 ; j++)
}
Bit-wise operators in C:
While every C programmer is familiar with the logical operators AND (&&), OR (||),and
NOT (!), many C programmers are less familiar with the bitwise operators AND ( & ),
OR ( | ),EX-OR ( ^ ),Inverter ( ~ ), shift Right ( >> ), and shift left ( << ). These bit-wise
operators are widely used in software engineering for embedded systems and control.
A
0
0
1
1
B
0
1
0
1
AND
A&B
0
0
0
1
OR
A|B
0
1
1
1
EX-OR
A^B
0
1
1
0
Inverter
Y = ~B
1
0
10. Write an 8051 C program to toggle all the bits 0f P0 and P2 continuously with a
250msec delay. Use the Inverter operator.
Solution:
#include<reg51.h>
void msdelay (unsigned int);
void main (void)
{
P0 = 0x55;
P2 = 0x55;
while (1)
{
P0 = P0;
P2 = ~P2;
msdelay(200);
}
}
void msdelay (unsigned int itime)
{
unsigned int i, j;
for ( i = 0; i< itime ; i++)
for ( j = 0; j< 1275 ; j++)
}
Bit-wise shift operation in C:
There are two bit-wise shift operators in C: 1. shift right ( >> ), and 2. shift left ( << ).
Their format in C is as follows:
Data >> number of bits to be shifted right
Data << number of bits to be shifted left.
The following shows some examples of shift operators in C
1. 0x9A >> 3 = 0x13 // shifting right 3 times//
2. 0x77 >> 4 = 0x07 // shifting right 4 times//
3. 0x6 << 4 = 0x60 // shifting right 4 times//
11. Write an 8051 C program to toggle all the bits 0f P0, P1, and P2 continuously with a
250msec delay. Use the EX-OR operator.
Solution:
#include<reg51.h>
void msdelay (unsigned int);
void main (void)
{
P0 = 0x55;
P1 = 0x55;
P2 = 0x55;
while (1)
{
P0 = P0^0xFF;
P1 = P1^0xFF;
P2 = P2^0xFF;
msdelay (250);
}}
void msdelay (unsigned int itime)
{
unsigned int i, j;
for ( i = 0; i< itime ; i++)
for ( j = 0; j< 1275 ; j++) ;
}
12. Write an 8051 C program to get bit P1.0 and send it to P2.7 after inverting it.
Solution:
#include<reg51.h>
sbit inbit = P1^0;
sbit outbit = P2^7;
bit membit;
void main (void)
{
for ( ; ;)
{
membit = 1;
outbit = ~membit;
}}
13. Write an 8051 C program to read the P1.0 and P1.1 bits and issue an ASCII character
to P0 according to the following table.
P1.1
P1.0
Send 0 to P0
Send 1 to P0
Send 2 to P0
Send 3 to P0
Solution:
#include<reg51.h>
void msdelay (unsigned int);
void main (void)
{
unsigned char z;
z = P1;
z = z & 0x3;
switch (z)
{
Case (0):
{
P0 = 0 ;
break;
}
Case (1):
{
P0 = 1 ;
break;
}
Case (2):
{
P0 = 2 ;
break;
}
Case (3):
{
P0 = 3 ;
break;
}}}
Data Conversion Program in 8051 C:
14. Write an 8051 C program to convert packed BCD 0x29 to ASCII and display the
bytes on P1 and P2.
Solution:
#include<reg51.h>
void main (void)
{
unsigned char x, y, z;
unsigned char mybyte = 0x29;
x = mybyte & 0x0F
P1 = x | 0x30;
Y = mybyte & 0xF0;
Y = y >> 4;
P2 = y | 0x30;
}
15. Write an 8051 C program to convert ASCII digits of 4 and 7 to packed BCD and
display them on P1.
Solution:
#include<reg51.h>
void main (void)
{
unsigned char bcdbyte;
unsigned char w = 4;
unsigned char z = 7;
w = w & 0x0F;
w = w<<4;
z = z & 0x0F;
bcdbyte = w | z ;
P1 = bcdbyte;
}
16. Write an 8051 C program to convert 11111101 (FD Hex) to decimal and the digits on
P0. P1 and P2.
Solution:
#include<reg51.h>
void main (void)
{
unsigned char x, binbyte, d1,d2,d3;
binbyte = 0xFD;
x = binbyte / 10 ;
d1 = binbyte % 10 ;
d2 = x % 10 ;
d3 = x / 10;
P0 = d1;
P1 = d2;
P2 = d3;
}
17. Write a C program to send out the value 44H serially one bit at a via P1.0. the LSB
should go out first.
Solution:
#include<reg51.h>
sbit p1b0 = P1^0;
sbit regALSB = ACC^0;
void main (void)
{
unsigned char conbyte = 0x44;
unsigned char x;
ACC = conbyte;
For ( x = 0 ; x<8 ; x++)
{
P1b0 = regALSB;
ACC ACC << 1;
}
}
18. Write a C program to bring in a byte of data serially one bit at a time via P1.0. The
LSB should come in first.
Solution:
#include<reg51.h>
sbit p1b0 = P1^0;
sbit regALSB = ACC^0;
void main (void)
{
unsigned char conbyte = 0x44;
unsigned char x;
ACC = conbyte;
For ( x = 0 ; x<8 ; x++)
{
P1b0 = regALSB;
ACC ACC << 1;
}
}
UNIT 5
This means that if the content of the timer 0 is equal to 0 (T0=0) then both registers it
includes will include 0. If the same timer contains for example number 1000 (decimal)
then the register TH0 (higher byte) will contain number 3, while TL0 (lower byte) will
contain decimal number 232.
Since the timers are virtually 16-bit registers, the greatest value that could be written to
them is 65 535. In case of exceeding this value, the timer will be automatically reset and
afterwards that counting starts from 0. It is called overflow. Two registers TMOD and
TCON are closely connected to this timer and control how it operates.
Timer 1
Referring to its characteristics, this timer is a twin brother to the Timer 0. This means
that they have the same purpose, their operating is controlled by the same registers
TMOD and TCON and both of them can operate in one of 4 different modes.
GATE1 starts and stops Timer 1 by means of a signal provided to the pin INT1
(P3.3):
o 1 - Timer 1 operates only if the bit INT1 is set
o 0 - Timer 1 operates regardless of the state of the bit INT 1
C/T1 selects which pulses are to be counted up by the timer/counter 1:
o 1 - Timer counts pulses provided to the pin T1 (P3.5)
o 0 - Timer counts pulses from internal oscillator
T1M1,T1M0 These two bits selects the Timer 1 operating mode.
T1M1
T1M0
Mode
Description
13-bit timer
16-bit timer
8-bit auto-reload
Split mode
GATE0 starts and stops Timer 1, using a signal provided to the pin INT0 (P3.2):
o 1 - Timer 0 operates only if the bit INT0 is set
o 0 - Timer 0 operates regardless of the state of the bit INT0
C/T0 selects which pulses are to be counted up by the timer/counter 0:
o 1 - Timer counts pulses provided to the pin T0(P3.4)
o 0 - Timer counts pulses from internal oscillator
T0M1,T0M0 These two bits select the Timer 0 operating mode.
T0M1
T0M0
Mode
Description
13-bit timer
16-bit timer
8-bit auto-reload
Split mode
1. Load the TMOD value register indicating which time is to be used and which
timer mode is selected.
2. Load registers TL and TH with initial count value.
3. Start the Timer.
4. Keep monitoring the timer flag (TF) with the JNB TFx, target instruction to
see if it is raised. Get out of the loop when TF becomes high.
5. Stop the Timer.
6. Clear the TF flag for the next round.
7. Go back to step 2 to load TH and TL again.
In Decimal;
Mode 0 Programming:
Mode 0 is exactly like mode 1 except that it is a 13-bit timer instead of 16-bit. The
13-bit counter can hold values between 0000 to 1FFFH in TH TL. Therefore the
timer its reaches maximum of 1FFFH, it rolls over to 0000, and TF is raised.
Mode 2 Programming:
The following are the characteristics and operations of mode 2.
1. It is an 8-bit timer; therefore, it allows only values of 00 to FFH to be loaded
into the timers register TH.
2. After TH is loaded with 8-bit value, the 8051 gives a copy of it to TL. Then
the timer must be started. This is done by the instruction SETB TR0 for
timer 0 and SETB TR1 for timer 1. this is like mode 1.
In Decimal;
Suppose it is needed to measure the duration of an event, for example how long some
device has been turned on? Look at the picture of the timer and pay attention to the
purpose of the bit GATE0 (which resides in the TMOD register). If this bit is cleared then
the state on the pin P3.2 does not affect the timer operating. If GATE0 = 1 the timer will
operate as far as the pin P3.2 has logic one (1) value. If this pin is supplied with 5V
through some external switch at the moment the device is being turned on, the timer will
measure duration of its operating, which actually was the aim.
How to count up pulses?
This time, the answer lies in the register TCON, and bit C/T0 respectively. Similar to the
previous example, this bit brings into an external signal. If the bit is cleared everything
occurs in the same way as in the previous examples and the timer counts pulses from
oscillator of defined frequency, i.e. measures the time that went by. If the bit is set, the
timer input is provided with pulses from the pin P3.4 (T0). Since these pulses do not have
some definite time or order, it is not possible to measure time by counting them. For that
reason, this timer is turned into the counter. The highest frequency that could be
measured by such a counter is 1/24 frequency of used quartz-crystal.
Accessing timer registers in C
1. Write a 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.
Solution:
#include<reg51.h>
Void T0Delay(void);
Void main (void)
{
P1=0x55;
T0Delay();
P1=0xAA;
T0Delay ();
} }
Void T0Delay ()
{
TMOD = 0x01;
TL0 = 0x00;
TH0 = 0x35;
TR0 = 1;
While (TF0 = = 0);
TR0 =0;
TF0= 0;
}
Calculation: FFFFH 3500H = CAFFH = 51967 + 1 = 51968
51968 * 1.085 s = 56.384 is the approximate Delay.
2. Write an 8051 C program to toggle only bit P1.5 continuously every 50ms. Use
Timer0, mode 1 (16-bit) to create the delay.
Solution:
#include<reg51.h>
Void T0M1delay (void);
Sbit mybit = P1^5;
Void main (void)
{
While (1)
{
mybit = ~mybit;
T0M1delay();
}}
Void T0M1delay (void)
{
TMOD = 0x01;
TL0 = 0x0FD;
TH0 = 0x4B;
TR0 = 1;
While (TF0==0);
TR0 = 0;
TF0 = 0;
}
Calculation: FFFFH 4BFDH = B402H = 46082 + 1 = 46083
Time delay = 46083 * 1.085 s = 50ms.
3. Write an 8051 C program to toggle all bits of P2 continuously every 500ms. Use Timer
1, mode 1 to create the delay.
Solution:
#include<reg51>
Void T1delay (void);
Void main (void)
{
Unsigned char x;
P2 = 0x55;
While (1)
{
P2 = ~P2;
For (x=0; x<20; x++)
T1delay();
}}
Void T1delay (void)
{
TMOD = 0x10;
TL1 = 0xFE;
TH1 = 0xA5;
TR1 = 1;
While (TF1 == 0);
TR1 = 0;
TF1 = 0;
}
Calculation:
FFFFH A5FEH = 23042 (decimal)
23042 * 1.085 s = 25ms and then 20 * 25ms = 500ms.
4. Write an 8051 C program to toggle only pin P1.5 continuously every 250ms. Use
Timer 0, mode 2 to create the delay.
Solution:
#include<reg51.h>
Void T0M2delay (void);
Sbit mybit = P1^5;
Void main (void)
{
Unsigned char x, y;
While (1)
{
mybit = ~mybit;
for (x = 0 ; x = 250 ; x++)
for ( y = 0; y = 36 ; y++ )
T0M2delay ();
}
}
Void T0M2delay (void)
{
TMOD = 0x02;
TH0 = -23;
TR0 = 1;
While (TF0 == 0);
TR0 = 0;
TF0 = 0;
}
Calculation:
256 23 = 233
23 * 1.085s = 25s and 25s * 250 * 40(36) = 250ms.
5. Write an 8051 C program to create a frequency of 2500Hz on pin P2.7. Use Timer 1,
mode 2 to create the delay.
Solution:
#include<reg51.h>
Void T1M2delay (void);
Sbit mybit = P2^7;
Void main (void)
{
Unsigned char x;
While (1)
{
mybit = ~mybit;
T1M2delay ();
}}
}
While (TF0==0);
TR0=0;
TF0=0;
}}
Void BintoASCII (unsigned char value)
{ unsigned char x,d1,d2,d3;
x = value/10;
d1 = value % 10;
d2 = x % 10;
d3 = x / 10 ;
P0 = 30 /d1; P1=30/d2; P2=30/d3 }
9. Assume that a 60Hz external clock is being fed into pin T0 (P3.4). write a C program
for counter 0 in mode 2 to display the seconds and minutes on P1 and P2, respectively.
Solution:
#include<reg51.h>
Void ToTime (unsigned char)
Void main (void)
{ unsigned char value;
T0 = 1;
TMOD = 0x06;
TH0 =-60;
While (1)
{
do
{ TR0 = 1;
sec = TL0;
ToTime (value);
}
While (TF0==0);
TR0=0;
TF0=0;
}}
Void ToTime (unsigned char value)
{ unsigned char sec, min;
min = value/60;
sec = value % 10;
P1=sec; P2=min; }
UNIT 6
8051 SERIAL COMMUNICATION
Basics of Serial Communication:
The fact that serial communication uses a single data line instead of the 8-bit data line of
parallel communication not only makes much cheaper but also enables two computers
located in two different cities to communicate over the telephone.
For serial communication to work, the byte of the data must be converted to serial bits
using a parallel to serial out shift register, and then it can be transmitted over a single data
line. This also means that receiving end must be a serial in parallel out shift register to
receive serial data and back them into a byte. Of course, if data is to be transferred on the
telephone line, it must be converted from 0s and 1s to audio signals. This conversion is
performed by a peripheral device called modem. This stands for modulator/demodulator.
Serial communication uses two methods, asynchronous and synchronous. The
Synchronous method transfers a block of data at a time, while the Asynchronous method
transfers a single byte at a time.
Simplex: if data is transmitted in one direction is referred to simplex.
Transmitter
Receiver
Half duplex: if data is transmitted one way at a time, it is referred to as half duplex.
Transmitter
Transmitter
Receiver
Receiver
Full Duplex: if the data can go both ways at the same time, it is full duplex.
Transmitter
Receiver
Receiver
Transmitter
Serial port should be configured prior to being used. That determines how many bits one
serial word contains, what the baud rate is and what the pulse source for
synchronization is. All bits controlling this are stored in the SFR Register SCON (Serial
Control).
SCON Register (Serial Port Control Register)
As seen, serial port mode is selected by combining the bits SM0 and SM2:
SM0
SM1
Mode
Description
Baud Rate
8-bit UART
9-bit UART
9-bit UART
5. The character byte to be transferred serially is written into the SBUF register.
6. The TI flag bit is monitored with the use of the instruction JNB TI, xx to see if
the character has been transferred completely.
7. To transfer the next character, go to step 5.
Programming the 8051 to receive data serially:
In programming the 8051 to receive character bytes serially, the following steps to be
taken.
1. The TMOD register is loaded with the value 20h, indicating the use of Timer 1 in
mode 2.
2. The TH1 is loaded the value which set the baud rate for serial data transfer.
3. The SCON register is loaded with the value 50H, indicating serial mode 1, where
8-bit data is framed with start and stop bits and receive enable is turned on.
4. TR1 is set to 1 to start timer 1.
5. RI is cleared with the CLR RI instruction.
6. The RI flag bit is monitored with the use of the instruction JNB RI, xx to see if
the character has been received yet.
7. When RI is raised, SBUF has the byte. Its contents are moved into a safe place.
8. To receive the next character, go to step 5.
Examples:
3. Write a program to transfer a letter Y serially at 9600 baud
continuously and also to send a letter N through port 0 which is
connected to a display device.
Solution: MOV
MOV
MOV
SETB
AGAIN : MOV
HERE : JNB
CLR
MOV
SJMP
2. Write a program to receive the data which has been sent in serial
form and send it out to port 0 in parallel form. Also save the data at
RAM location 60H.
Solution: MOV
MOV
MOV
SETB
CLR
HERE : JNB
MOV
MOV
MOV
{
TMOD = 0x20;
TH1 = 0xFD;
SCON = 0x50;
TR1 = 1;
while (1)
{
Sertx(Y);
Sertx(E);
Sertx(S);
}}
void sertx(unsigned char x);
{
SBUF = x;
while (TI= = 0);
TI = 0;
}
3. Program the 8051 in C to receive bytes of data serially and put them in P1. set the baud
at 4800, 8-bit data and 1 stop bit.
Solution:
#include< reg51>
void main (void)
{
TMOD = 0x20;
TH1 = 0xFA;
SCON = 0x50;
TR1 = 1;
while (1)
{
while (RI= = 0);
mybyte = SBUF;
P1 = mybyte;
RI = 0;
}}
3. Write an 8051 C program to send two different strings to the serial port. Assuming that
SW connected to pin P2.0, monitor its status and make a decision as follows:
SW = 0; send your first name, SW = 1; send your last name. Assume XTAL =
11.0592MHz, baud rate of 9600, 8-bit data, 1stop bit.
Solution:
#include< reg51>
sbit mysw = P2^0;
void main (void)
{ unsigned char z;
unsigned char fname[] = sathish;
Unsigned char lname[] = .T
TMOD = 0x20;
TH1 = 0xFD;
SCON = 0x50;
TR1 = 1;
if (mysw = 0)
{
for (z = 0 ; z<7; z++)
{
SBUF = fname[z];
while (TI= = 0);
TI = 0;
}}
else
{
for (z = 0 ; z<2; z++)
{ SBUF = lname[z];
while (TI= = 0);
TI = 0;
}}}
4. Write an 8051 C Program to send the two messages Normal Speed and High speed
to the serial port. Assuming that SW is connected to pin P2.0, its status and the baud rate
as follows;
SW = 0 28800 baud rate, SW = 156K baud rate, Assume that XTAL = 11.0592 MHz for
both cases.
Solution:
#include< reg51>
sbit mysw = P2^0;
void main (void)
{ unsigned char z;
unsigned char mess1[] = Normal speed;
Unsigned char mess2[] = High speed ;
TMOD = 0x20;
TH1 = 0xFF;
SCON = 0x50;
TR1 = 1;
if (mysw = 0)
{
for (z = 0 ; z<12; z++)
{
SBUF = mess1[z];
while (TI= = 0);
TI = 0;
}}
else
{
PCON = PCON | 0x080;
for (z = 0 ; z<10; z++)
{ SBUF =mess2[z];
while (TI= = 0);
TI = 0;
}}}
Programming the second serial Port:
Many of the new generations of the 8051 microcontrollers come two serial ports. The
DS89C4x0 and DS80C320 are among them.
DS89C4x0 second serial port: the second serial port of the DS89C4x0 uses pins P1.2
and P1.3 for the Rx and Tx lines, respectively. Notice that the first and second serial ports
are designated as Serial #0 and Serial #1, respectively.
SFR Byte addresses for DS89C4x0 Serial ports
SFR
SCON
SCON0 = 98H
SCON1= C0H
SBUF
SBUF0 = 99H
SBUF1 = C1H
TL
TL1 = 8BH
TL1 = 8BH
TH
TH1 = 8DH
TH1 = 8DH
TCON
TCON0 = 88H
TCON0 = 88H
PCON
PCON = 87H
PCON = 87H
5. Write a C program for the DS89C4x0 to transfer letter A serially at 4800 baud
continuously. Use the second serial port with 8-bit data and 1 stop bit. We can only use
timer 1 to set the baud rate.
Solution:
#include< reg51>
sfr SBUF1 = 0xC1;
sfr SCON1 = 0xC0;