Architecture and Programming of 8051 Microcontrollers
Architecture and Programming of 8051 Microcontrollers
Microcontrollers”
Table of Contents
Chapter 1: Introduction to Microcontrollers
Chapter 2: 8051 Microcontroller Architecture
Chapter 3: The 8051 Instruction Set
Chapter 4: The AT89S8253 Microcontroller
Chapter 5: Program Language Assembler
Chapter 6: Examples
Chapter 7: Development Tools
Chapter1: Introduction to Microcontrollers
Introduction
1.1 What are microcontrollers and what are they used for?
1.2 What is what in microcontroller?
Introduction
It was electricity in the beginning....The people were happy because they did not know that it
was existing all around them and that it could be utilized. It was fine. And then Faraday came
and the stone has started rolling slowly...
During the time, the first machines using a new sort of energy appeared accompanied with
people who knew something about electricity. A long time has passed since then and just when
civilization got used to this innovation and stopped paying attention to what a new generation of
specialists were doing, someone came up with an idea that electrons could be a very convenient
toy being closed in a glass pipe. At first sight, it was only a good idea, but there was no return,
electonics was born and the stone continued rolling down the hill faster and faster...
A new science - new specialists. The blue coats were replaced with white ones and people who
knew something about electronics appeared on stage. While the rest of the humanity were
passively watching in disbelief what was going on, within plotters two fractions appeared-
“software-oriented” and “hardware-oriented”. A bit younger than their teachers, very enthusiastic
and full of ideas, both of them kept on working but separate ways. While the first group had a
stable development, hardware-oriented people, driven by success, soon threw caution to the wind
and invented transistor.
Up till that moment, the things could be more or less kept under control, but broad publicity was
not aware of seriousness of the situation and it soon led to a fatal mistake! Being naive in belief
that using cheap tricks could slow down technology development as well as developing of the
world, mass market opened its door to the products of Electronics Industry, closing a magic
circle therefore. Components’ prices fell rapidly becoming available for use to younger
population. The stone was falling freely...
The first integrated circuits and processors have soon appeared, which enabled for computers to
drop down in price. The computers have started to develop their own production. The prices
droped down again and Electonics got new adherents. It appeared everywhere. Another circle
has been closed! Ordinary people got hold of computers and computer era has begun...
While this drama was going on, hobbyists and professionals, protected by anonymity, were
working hard on their projects , although split in two big groups. Then, someone has again
remembered: Why should not we make an universal component? It would be a cheap and
universal integrated circuit that could be programmed and used in any field of electronics, device
and wherever needed. Technology has been developed enough, market exists, why not? So it
happened, body and spirit are united, the circuit is created and called MICROCONTROLLER.
1.1 What are microcontrollers and what are they used for?
As all other good things, this powerful component is basically very simple and is obtained by
uniting tested and high- quality "ingredients" (components) as per following receipt:
Three things have had a crucial impact on such a success of the microcontrollers:
Powerful and intelligently chosen electronics embedded in the microcontrollers can via
input/output devices ( switches, push buttons, sensors, LCD displays, relays…) control various
processes and devices such as: industrial automatics, electric current, temperature, engine
performance etc.
A very low price enables them to be embedded in such devices in which, until recent time it was
not worth embedding anything. Thanks to that, the world is overwhelmed today with cheap
automatic devices and various “intelligent” appliences.
Prior knowledge is hardly needed for programming. It is sufficient to have any kind of PC
(software in use is not demanding at all and it is easy to learn to work on it) and one simple
device (programmer) used for “transffering” completed programs into the microcontroller.
Therefore, if you are infected with a virus called electronics, there is nothing left for you to do
but to learn how to control its power and how to direct it at the right course.
Even though there is a great number of various microcontrollers and even greater number of
programs designed for the microcontrollers’ use only, all of them have many things in common.
That means that if you learn to handle one of them you will be able to handle them all. A typical
scenario on whose basis it all functions is as follows:
1. Power supply is turned off and everything is so still…chip is programmed, every thing is in place,
nothing indicates what is to come…
2. Power supply connectors are connected to the power supply source and every thing starts to
happen at high speed! The control logic registers what is going on first. It enables only quartz
oscillator to operate. While the first preparations are in progress and parasite capacities are
being charged, the first milliseconds go by.
3. Power supply connectors are connected to the power supply source and every thing starts to
happen at high speed! The control logic registers what is going on first. It enables only quartz
oscillator to work. While the first preparations are in progress and parasite capacities are being
charged, the first milliseconds go by.
4. Voltage level has reached its full value and frequency of oscillator has became stable. The bits
are being written to the SFRs, showing the state of all periph erals and all pins are configured as
outputs. Everything occurs in harmony to the pulses’ rhythm and the overall electronis starts
operating. Since this moment the time is measured in micro and nanoseconds.
5. Program Counter is reset to zero address of the program memory. Instruction from that address
is sent to instruction decoder where its meaning is recognised and it is executed with immediate
effect.
6. The value of the Program Counter is being incremented by 1 and the whole process is being
repeated...several million times per second
Obviously, everything that occurs in the microcontroller occurs at high speed and quite simple,
but it would not be so useful if there are no special interfaces which make it complete. Text
below refers to that (in short).
The Program Memory is a type of memory which permanently stores a program being executed.
Obviously, the maximal length of the program that can be written to depends on the size of the
memory. Program memory can be built in the microcontroller or added from outside as a
separate chip, which depends on type of the microcontroller. Both variants have advantages and
disadvantages: if added from outside, the microcontroller is cheaper and program can be
considerably longer. At the same time, a number of available pins is decremented as the
microcontroller uses its own input/output ports to be connected to the memory. The capacity of
Internal Program Memory is usually smaller and more expensive but such a chip has more
possibilities of connecting to peripheral environment. Program memory size ranges from 512B to
64KB.
Data Memory is a type of memory used for temporary storing and keeping different data and
constants created and used during operating process . The content of this memory is erased once
the power is off. For example: when the program performes addition, it is necessary to have a
register presenting what in everyday life is called “a sum” . For that purpose one of the registers
in RAM is named as such and serves for storing results of addition. Data memory size goes up to
a few KBs.
EEPROM Memory
The EEPROM Memory is a special type of memory which not all the types of the
microcontrollers have.Its content can be changed during program execution (similar to RAM ),
but it is permanently saved even after the power goes off (similar to ROM). It is used for storing
different values created and used during operating process and which must be saved upon turning
off the device ( calibration values, codes, values to count up to etc.). A disadvantage of this
memory is that programming is relatively slow- measured in miliseconds.
SFRs ( Special Function Registers )
SFRs are a particular part of memory whose purpose is defined in advance by the producer. Each
of these registers have its name and control some of interfaces within the microcontroller. For
example: by writing zero or one to the SFR controlling some input/output port, each of the port
pins can be configured as input or output (each bit in this register controls the purpose of one
single pin).
Program Counter
Program Counter is an engine which starts the program and indicates the address in memory
where next instruction to execute is found. Immediately after its execution, the value of the
counter is incremented by 1. For this automatic increment, the program executes one instruction
at a time as it is written. However…the program counter value could be changed at any moment,
which will cause “jump” to a new location in the program memory. This is how subroutines or
branch instructions are executed. When finding its new place in the program, the counter
resumes even automatic counting +1, +1, +1…
As its name tells, this is "Big Brother" who monitors and controls all operations being performed
within the microcontroller and the user cannot affect its work. It consists of several smaller units.
The most important are:
Instruction decoder - a part of electronics which recognizes program instructions and on the
basis of which runs other circuits.
Arithmetical Logical Unit (ALU) - performs all mathematical and logical operations with data.
The features of this circuit are described in the "instruction set" which differs for each type of
the microcontroller..
Accumulator - is a special type of the SFR closely related to operating mode of the ALU. It is a
kind of desk on which all data needed to perform some operation on are set (addition, shift
etc.). It also contains a result, ready to be used further in operation. One of the SFRs, called the
Status Register, is closely related to the accumulator, showing at any time the "status" of a
number being in the accumulator (the number is greater than or less than zero etc.).
Bit - a word invented to confuse people who start handling electronics. In practice ( only in
practice) this word indicates whether the voltage is applied to an electrical conductor or not. In
the first case, a logical one is present on the pin, i.e. the bit’s value is 1. Otherwise, if the voltage
level is 0 V, i.e. a logical zero is present on the pin, the bit’s value is 0. It is more complicated in
theory where the bit is actually a digit in a binary system, whereas, a bit is just a bit whose value
amounts 0 or 1 (in decade system we are used to the digits’ value amounting 0, 1 , 2 , 3 , …..8 or
9).
The microcontroller cannot be of any use without being connected to peripheral devices. For that
reason each microcontroller has one or more registers connected to its pins (called ports in this
case).
Why input/output? Because the user can change pin’s role according to his/her own needs. These
are, in fact, the only registers in the microcontroller whose state can be checked by voltmeter !
Oscillator
The oscillator can be compared with rhythm section of a mini orchestra. Equalized pulses
coming from this circuit enable harmonious and synchronic operating of all other parts of the
microcontroller. It is commonly configured so as to use quartz-crystal or ceramics resonator for
frequency stabilization. Besides, it can often operate without elements for frequency stabilization
( like RC oscillator). It is important to know that instructions are not executed at the rate ordered
by oscillator but several times slower. The reason for this is that each instruction is executed in
several steps (In some microcontrollers execution time of all instructions is equal, while in others
microcontrollers execution time differs for different instructions). Consequently, if your system
uses quartz-crystal of 20MHz, execution time of a program instruction is not 50nS but 200, 400
or even 800 nS!
Timers/Counters
Most programs use in some way these miniature electronic "stopwatches". They are mostly 8- or
16-bit SFRs whose value is automatically incremented with each coming pulse. Once the register
is completely "filled up"- an interrupt is generated !
If the registers use internal oscillator for its operating then it is possible to measure the time
between two events ( if the register value is T1 at the moment measuring has started, and T2 at
the moment measuring has finished, then the time that has passed is equal to the value gained by
their subtruction T2-T1 ). If the registers for its operating use pulses coming from external source
then such a timer is converted to counter.
This is a very simple explanation used to describe the essence of the operating. It’s a bit more
complicated in practice.
Register is another name for a memory cell. Beside 8 bits available to the user, each register has
also addressing part usually not visible to the user. It is important to know:
All registers in ROM as well as those in RAM memory identified as general-purpose registers are
mutually equal and nameless. During programming, each register can be assigned a name,
which makes operating much easier.
All SFRs have their own names which are different for different types of the microcontrollers
and each of them has a particular role.
Watchdog timer
Its name tells a lot about its purpose. Watchdog Timer is a timer connected to a particular and
totally independent RC oscillator within the microcontroller.
If enabled to operate, every time it "counts up to end", the microcontroller is reset and program
execution starts from the first instruction. The to keep this from happening by using particular
command. The whole idea is based on the fact that every program circulates, in other words, the
program is executed in several longer or shorter loops.
If the instructions which resets the value of the watchdog timer are set at some important
program locations, besides commands being regularly executed, then the operation of the
watchdog timer will not be noticed.
If for any reason (usually electrical disturbances in industry), the program counter "gets stuck" at
memory location from where there is no return, the register’s value being steadily incremented
by the watchdog timer will reach the maximum et voila ! Reset occurs!
Two things within the circuit that take care of the microcontroller power supply are worth
attention :
Brown out is potentially dangerous state coming up at the moment the microcontroller is being
turned off or in situations when due to powerful disturbances, voltage supply comes to the lowest
limit. As the microcontroller consists of several circuits which have different operating voltage
levels, this can cause its "out of control" performance. In order to prevent that, a circuit for
brown out reset is usually embedded. When the voltage level drops below the lower limit then
this circuit immediately resets the whole electronics.
Reset pin is usually identified as MCLR (Master Clear Reset) and serves for "external" reset of
the microcontroller by applying logical zero or one depending on type of the microcontroller. In
case the brown out is not embedded a simple external circuit for brown out reset can be
connected to this pin.
Serial communication
Connection between the microcontroller and peripheral devices established through I/O ports is
an ideal solution for shorter distances- up to several meters. But, when it is needed to enable
communication between two devices on longer distances or when for any other reason it is not
possible to use "parallel" connection ( for example remote control of the aircraft ) it is obvious
that something so simple cannot be taken into account. In such and similar situations,
communication through pulses, called serial communication is the most appropriate to use.
Serial communication problem has been resolved a long time ago and nowadays several different
systems enabling this kind of connection are embedded as a standard equipment into most
microcontroller. Which of them will be used in very situation depends on several factors. The
most important are the following:
One of the most important things concerning the use of serial communication is to strictly
observe the Protocol. It is a set of rules which must be applied in order to enable devices to
recognize the data being exchanged. Fortunately, the microcontrollers automatically take care of
it, which leads to a reduction of the programmer’s work to simple writing and reading data.
Byte - 8 bits next to each other make entity called a program word or a byte. If the bit is a digit
then it is logical that bytes are numbers. All mathematical operations can be performed upon
them, just like with usual decimal numbers and they are performed in the ALU. It is important to
note that byte ( as each number) has “two sides”, i.e. digits a byte consists of are not of equal
significance. The highest value has a digit on the far left called the most significant bit ( MSB). A
digit on the far right has the least value and is called the least significant bit (LSB). As 8 digits
can be combined in 256 different ways, the greatest decimal number that can present one byte is
255 ( zero is also presented with one combination ).
Program
Unlike other integrated circuits which only need to be connected to other components and then
powered on, the microcontrollers need to be programmed too prior to turning the power on. This
is so called "a bitter pill" and the main reason why hardware-oriented electronics engineers
mainly avoid the microcontrollers. It is a trap causing huge losses because the microcontrollers
programming is in fact very simple.
In order to write a program for running microcontrollers, several "low-level" program languages
for programming computers can be used – Assembler , C and Basic ( and their versions ).
Besides, writing program procedure consists of simple giving instructions in order in which they
should be executed. There are also many programs operating in Windows environment used to
facilitate work and provide additional- visual tools.
The use of Assembler is described in this book because it is the simplest language with the
fastest execution allowing entire control on what is going on in the circuit.
Interrupt - electronics is usually more faster than physical process in environment it should
keep under control. That’s why the microcontroller spend the most of its time waiting for
something to happen or execute.In order to avoid continuous checking for logical state on input
pins and in internal registers, the interrupt is generated. It is a signal interrupting regular
program execution. Since several events can cause interrupt, when it occurs, the microcontroller
immediately stops operating and checks for the cause. If it is needed to perform some action, a
current state of the program counter is pushed on the Stack and the appropriate program is
executed (so called interrupt routine ).
Stack is a part of RAM used for storing the current state of the program counter (address).This
address lets the controller know where to return after the subroutine has been executed. Stack
can consist of several levels. This enables subroutines’ nesting, i.e. calling one subroutine from
another.
Chapter 2 : 8051 Microcontroller Architecture
2.1 What is 8051 Standard?
2.2 8051 Microcontroller's pins
2.3 Input/Output Ports (I/O Ports)
2.4 8051 Microcontroller Memory Organisation
2.5 SFRs (Special Function Registers)
2.6 Counters and Timers
2.7 UART (Universal Asynchronous Receiver and Transmitter)
2.8 8051 Microcontroller Interrupts
2.9 8051 Microcontroller Power Consumption Control
Microcontrollers’ producers have been struggling for a long time for attracting more and more
choosy customers. Every couple of days a new chip with a higher operating frequency, more
memory and more high-quality A/D converters comes on the market.
Nevertheless, by analyzing their structure it is concluded that most of them have the same (or at
least very similar) architecture known in the product catalogs as “8051 compatible”. What is all
this about?
The whole story began in the far 80s when Intel launched its series of the microcontrollers
labelled with MCS 051. Although, several circuits belonging to this series had quite modest
features in comparison to the new ones, they took over the world very fast and became a standard
for what nowadays is ment by a word microcontroller.
The reason for success and such a big popularity is a skillfully chosen configuration which
satisfies needs of a great number of the users allowing at the same time stable expanding ( refers
to the new types of the microcontrollers ). Besides, since a great deal of software has been
developed in the meantime, it simply was not profitable to change anything in the
microcontroller’s basic core. That is the reason for having a great number of various
microcontrollers which actually are solely upgraded versions of the 8051 family. What is it what
makes this microcontroller so special and universal so that almost all the world producers
manufacture it today under different name ?
As shown on the previous picture, the 8051 microcontroller has nothing impressive at first sight:
As it is shown on the previous picture, the 8051 microcontroller have nothing impressive at first
sight:
The whole configuration is obviously envisaged as such to satisfy the needs of most
programmers who work on development of automation devices. One of advantages of this
microcontroller is that nothing is missing and nothing is too much. In other words, it is created
exactly in accordance to the average user‘s taste and needs. The other advantage is the way RAM
is organized, the way Central Processor Unit (CPU) operates and ports which maximally use all
recourses and enable further upgrading.
Pin 9: RS Logical one on this pin stops microcontroller’s operating and erases the contents of
most registers. By applying logical zero to this pin, the program starts execution from the
beginning. In other words, a positive voltage pulse on this pin resets the microcontroller.
Pins10-17: Port 3 Similar to port 1, each of these pins can serve as universal input or output .
Besides, all of them have alternative functions:
Pin 10: RXD Serial asynchronous communication input or Serial synchronous communication
output.
Pin 11: TXD Serial asynchronous communication output or Serial synchronous communication
clock output.
Pin 18, 19: X2, X1 Internal oscillator input and output. A quartz crystal which determines
operating frequency is usually connected to these pins. Instead of quartz crystal, the miniature
ceramics resonators can be also used for frequency stabilization. Later versions of the
microcontrollers operate at a frequency of 0 Hz up to over 50 Hz.
Pin 21-28: Port 2 If there is no intention to use external memory then these port pins are
configured as universal inputs/outputs. In case external memory is used then the higher address
byte, i.e. addresses A8-A15 will appear on this port. It is important to know that even memory
with capacity of 64Kb is not used ( i.e. note all bits on port are used for memory addressing) the
rest of bits are not available as inputs or outputs.
Pin 29: PSEN If external ROM is used for storing program then it has a logic-0 value every time
the microcontroller reads a byte from memory.
Pin 30: ALE Prior to each reading from external memory, the microcontroller will set the lower
address byte (A0-A7) on P0 and immediately after that activates the output ALE. Upon receiving
signal from the ALE pin, the external register (74HCT373 or 74HCT375 circuit is usually
embedded ) memorizes the state of P0 and uses it as an address for memory chip. In the second
part of the microcontroller’s machine cycle, a signal on this pin stops being emitted and P0 is
used now for data transmission (Data Bus). In this way, by means of only one additional (and
cheap) integrated circuit, data multiplexing from the port is performed. This port at the same
time used for data and address transmission.
Pin 31: EA By applying logic zero to this pin, P2 and P3 are used for data and address
transmission with no regard to whether there is internal memory or not. That means that even
there is a program written to the microcontroller, it will not be executed, the program written to
external ROM will be used instead. Otherwise, by applying logic one 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.
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.
Input/Output (I/O) 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 pullup resistor.
Output pin
A 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.
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.
A logic state (voltage) on any pin can be changed or read at any moment. A logic zero (0) and
logic one (1) are not equal. A logic one (0) represents almost short circuit to ground. Such a pin
is configured as output.
A logic one (1) is “loosely” connected to voltage power supply through resistors of high
resistance. Since this voltage can be easily “pulled down” by an external signal, such a pin is
configured as input.
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:
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”.
When the pin is configured as output, it performs as “open drain”, meaning that by writing 0 to
some port’s bit, the appropriate pin will be connected to ground (0V). By 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.
Only in case P0 is used for addressing external memory ( only in that case), the microcontroller will
provide internal power supply source in order to establish logical ones on pins. There is no need to add
external pullup resistors.
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 input-output 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 hardware’s perspective , this
port is also similar to P0, with the difference that its outputs have a pull-up resistor embedded.
It may be seen from description of some ports, that even though all pins have more or less
similar internal structure, it is necessary to pay attention to which of them will be used for what
and how.
For example: If they are used as outputs with high voltage level (5V), then port 0 should be
avoided because its pins do not have added resistor for connection to +5V. Only low logic level
can be obtained therefore, if another port is used for the same purpose, one should have in mind
that pull-up resistors have a relatively high resistance. Consequentaly it can be counted on only
several hundreds microamperes of current coming out of a pin.
The microcontroller memory is divided into Program Memory and Data Memory. Program
Memory (ROM) is used for permanent saving program being executed, while Data Memory
(RAM) is used for temporarily storing and keeping intermediate results and variables. Depending
on the model in use ( still referring to the whole 8051 microcontroller family) at most a few Kb
of ROM and 128 or 256 bytes of RAM can be used. However…
All 8051 microcontrollers have 16-bit addressing bus and can address 64 kb memory. It is
neither a mistake nor a big ambition of engineers who were working on basic core development.
It is a matter of very clever memory organization which makes these controllers a real “
programmers’ tidbit“ .
Program Memory
The oldest models of the 8051 microcontroller family did not have internal program memory . It
was added from outside as a separate chip. These models are recognizable by their label
beginning with 803 ( for ex. 8031 or 8032). All later models have a few Kbytes ROM embedded,
Even though it is enough for writing most of the programs, there are situations when additional
memory is necessary. A typical example of it is the use of so called lookup tables. They are used
in cases when something is too complicated or when there is no time for solving equations
describing some process. The example of it can be totally exotic (an estimate of self-guided
rockets’ meeting point) or totally common( measuring of temperature using non-linear thermo
element or asynchronous motor speed control). In those cases all needed estimates and
approximates are executed in advance and the final results are put in the tables ( similar to
logarithmic tables ).
How does the microcontroller handle external memory depends on the pin EA logic state:
EA=0 In this case, internal program memory is completely ignored, only a program stored in
external memory is to be executed.
EA=1 In this case, a program from builtin ROM is to be executed first ( to the last location).
Afterwards, the execution is continued by reading additional memory.
in both cases, P0 and P2 are not available to the user because they are used for data nd address
transmission. Besides, the pins ALE and PSEN are used too.
Data Memory
As already mentioned, Data Memory is used for temporarily storing and keeping data and
intermediate results created and used during microcontroller’s operating. Besides, this
microcontroller family includes many other registers such as: hardware counters and timers,
input/output ports, serial data buffers etc. The previous versions have the total memory size of
256 locations, while for later models this number is incremented by additional 128 available
registers. In both cases, these first 256 memory locations (addresses 0-FFh) are the base of the
memory. Common to all types of the 8051 microcontrollers. Locations available to the user
occupy memory space with addresses from 0 to 7Fh. First 128 registers and this part of RAM is
divided in several blocks.
The first block consists of 4 banks each including 8 registers designated as R0 to R7. Prior to
access them, a bank containing that register must be selected. Next memory block ( in the range
of 20h to 2Fh) is bit- addressable, which means that each bit being there has its own address
from 0 to 7Fh. Since there are 16 such registers, this block contains in total of 128 bits with
separate addresses (The 0th bit of the 20h byte has the bit address 0 and the 7th bit of th 2Fh byte
has the bit address 7Fh). The third group of registers occupy addresses 2Fh-7Fh ( in total of 80
locations) and does not have any special purpose or feature.
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, it’s not so simple…The 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.
How to extend memory?
In case on-chip memory is not enough, it is possible to add two external memory chips with
capacity of 64Kb each. I/O ports P2 and P3 are used for their addressing and data transmission.
From the users’ perspective, everything functions quite simple if properly connected because the
most operations are performed by the microcontroller itself. The 8051 microcontroller has two
separate reading signals RD#(P3.7) and PSEN#. The first one is activated byte from external data
memory (RAM) should be read, while another one is activated to read byte from external
program memory (ROM). These both signals are active at logical zero (0) level. A typical
example of such memory extension using special chips for RAM and ROM, is shown on the
previous picture. It is called Hardward architecture.
Even though the additional memory is rarely used with the latest versions of the
microcontrollers, it will be described here in short what happens when memory chips are
connected according to the previous schematic. It is important to know that the whole process is
performed automatically, i.e. with no intervention in the program.
When the program during execution encounters the instruction which resides in exter nal
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 addtional 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 .
Addressing
While operating, processor processes data according to the program instructions. Each
instruction consists of two parts. One part describes what should be done and another part
indicates what to use to do it. This later part can be data (binary number) or address where the
data is stored. All 8051 microcontrollers use two ways of addressing depending on which part of
memory should be accessed:
Direct Addressing
On direct addressing, a value is obtained from a memory location while the address of that
location is specified in instruction. Only after that, the instruction can process data (howdepends
on the type of instruction: addition, subtraction, copy…). Obviously, a number being changed
during operating a variable can reside at that specified address. For example:
Since the address is only one byte in size ( the greatest number is 255), this is how only the first
255 locations in RAM can be accessed in this case the first half of the basic RAM is intended to
be used freely, while another half is reserved for the SFRs.
Only RAM locations available for use are accessed by indirect addressing (never in the SFRs).
For all latest versions of the microcontrollers with additional memory block ( those 128 locations
in Data Memory), this is the only way of accessing them. Simply, when during operating, the
instruction including “@” sign is encountered and if the specified address is higher than 128 ( 7F
hex.), the processor knows that indirect addressing is used and jumps over memory space
reserved for the SFRs.
MOV A,@R0; Means: Store the value from the register whose address is in the
R0 register
into accumulator
On indirect addressing, the registers R0, R1 or Stack Pointer are used for specifying 8-bit
addresses. Since only 8 bits are avilable, it is possible to access only registers of internal RAM in
this way (128 locations in former or 256 locations in latest versions of the microcontrollers). If
memory extension in form of additional memory chip is used then the 16-bit DPTR Register
(consisting of the registers DPTRL and DPTRH) is used for specifying addresses. In this way it
is possible to access any location in the range of 64K.
SFRs are a kind of control table used for running and monitoring microcontroller’s operating.
Each of these registers, even each bit they include, has its name, address in the scope of RAM
and clearly defined purpose ( for example: timer control, interrupt, serial connection etc.). Even
though there are 128 free memory locations intended for their storage, the basic core, shared by
all types of 8051 controllers, has only 21 such registers. Rest of locations are intensionally left
free in order to enable the producers to further improved models keeping at the same time
compatibility with the previous versions. It also enables the use of programs written a long time
ago for the microcontrollers which are out of production now.
A Register (Accumulator)
This is a general-purpose register which serves for storing intermediate results during operating.
A number (an operand) should be added to the accumulator prior to execute an instruction upon
it. Once an arithmetical operation is preformed by the ALU, the result is placed into the
accumulator. If a data should be transferred from one register to another, it must go through
accumulator. For such universal purpose, this is the most commonly used register that none
microcontroller can be imagined without (more than a half 8051 microcontroller's instructions
used use the accumulator in some way).
B Register
B register is used during multiply and divide operations which can be performed only upon
numbers stored in the A and B registers. All other instructions in the program can use this
register as a spare accumulator (A).
During programming, each of registers is called by name so that their exact address is not so important
for the user. During compiling into machine code (series of hexadecimal numbers recognized as
instructions by the microcontroller), PC will automatically, instead of registers’ name, write necessary
addresses into the microcontroller.
R Registers (R0-R7)
This is a common name for the total 8 generalpurpose registers (R0, R1, R2 ...R7). Even they are
not true SFRs, they deserve to be discussed here because of their purpose. The bank is active
when the R registers it includes are in use. Similar to the accumulator, they are used for
temporary storing variables and intermediate results. Which of the banks will be active depends
on two bits included in the PSW Register. These registers are stored in four banks in the scope of
RAM.
The following example best illustrates the useful purpose of these registers. Suppose that
mathematical operations on numbers previously stored in the R registers should be performed:
(R1+R2) - (R3+R4). Obviously, a register for temporary storing results of addition is needed.
Everything is quite simple and the program is as follows :
This is one of the most important SFRs. The Program Status Word (PSW) contains several status
bits that reflect the current state of the CPU. This register contains: Carry bit, Auxiliary Carry,
two register bank select bits, Overflow flag, parity bit, and user-definable status flag. The ALU
automatically changes some of register’s bits, which is usually used in regulation of the program
performing.
P - Parity bit. If a number in accumulator is even then this bit will be automatically set (1),
otherwise it will be cleared (0). It is mainly used during data transmission and receiving via
serial communication.
- Bit 1. This bit is intended for the future versions of the microcontrollers, so it is not supposed to
be here.
OV Overflow occurs when the result of arithmetical operation is greater than 255 (deci mal), so
that it can not be stored in one register. In that case, this bit will be set (1). If there is no
overflow, this bit will be cleared (0).
RS0, RS1 - Register bank select bits. These two bits are used to select one of the four register
banks in RAM. By writing zeroes and ones to these bits, a group of registers R0-R7 is stored in
one of four banks in RAM.
0 0 Bank0 00h-07h
0 1 Bank1 08h-0Fh
1 0 Bank2 10h-17h
1 1 Bank3 18h-1Fh
CY - Carry Flag is the (ninth) auxiliary bit used for all arithmetical operations and shift
instructions.
These registers are not true ones because they do not physically exist. They consist of two
separate registers: DPH (Data Pointer High) and (Data Pointer Low). Their 16 bits are used for
external memory addressing. They may be handled as a 16-bit register or as two independet 8-bit
registers.Besides, the DPTR Register is usually used for storing data and intermediate results
which have nothing to do with memory locations.
A value of the Stack Pointer ensures that the Stack Pointer will point to valid RAM and permits
Stack availability. By starting each subprogram, the value in the Stack Pointer is incremented by
1. In the same manner, by ending subprogram, this value is decremented by 1. After any reset,
the value 7 is written to the Stack Pointer, which means that the space of RAM reserved for the
Stack starts from this location. If another value is written to this register then the entire Stack is
moved to a new location in the memory.
In case that external memory and serial communication system are not in use then, 4 ports with
in total of 32 input-output lines are available to the user for connection to peripheral
environment. Each bit inside these ports coresponds to the appropriate pin on the
microcontroller. This means that logic state written to these ports appears as a voltage on the pin
( 0 or 5 V). Naturally, while reading, the opposite occurs – voltage on some input pins is
reflected in the appropriate port bit.
The state of a port bit, besides being reflected in the pin, determines at the same time whether it
will be configured as input or output. If a bit is cleared (0), the pin will be configured as output.
In the same manner, if a bit is set to 1 the pin will be configured as input. After reset, as well as
when turning the microcontroller on , all bits on these ports are set to one (1). This means that
the appropriate pins will be configured as inputs.
Conditionally said, I/O ports are directly connected to the microcontroller’s pins. This means that
a logic state of these registers can be checked by voltmeter and vice versa-voltage on the pins
can be checked by testing their bits!
As explained in the previous chapter, the main oscillator of the microcontroller uses quartz
crystal for its operating. As the frequency of this oscillator is precisely defined and very stable,
these pulses are the most suitable for time measuring (such oscillators are used in quartz clocks
as well). In order to measure time between two events it is only needed to count up pulses from
this oscillator. That is exactly what the timer is doing. Namely, if the timer is properly
programmed, the value written to the timer register will be incremented or decremented after
each coming pulse, i.e. once per each machine cycle cycle. Taking into account that one
instruction lasts 12 quartz oscillator periods (one machine cycle), by embedding quartz with
oscillator frequency of 12MHz, a number in the timer register will be changed million times per
second, i.e. each microsecond.
The 8051 microcontrollers have 2 timer counters called T0 and T1. As their names tell, their
main purpose is to measure time and count external events. Besides, they can be used for
generating clock pulses used in serial communication, i.e. Baud Rate.
Timer T0
As it is shown in the picture below, this timer consists of two registers – TH0 and TL0. The
numbers these registers include represent a lower and a higher byte of one 16-digit binary
number.
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.
This register selects mode of the timers T0 and T1. As illustrated in the following picture, the
lower 4 bits (bit0 - bit3) refer to the timer 0, while the higher 4 bits (bit4 - bit7) refer to the timer
1. There are in total of 4 modes and each of them is described here in this book.
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.
0 0 0 13-bit timer
0 1 1 16-bit timer
1 0 2 8-bit auto-
reload
1 1 3 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.
0 0 0 13-bit timer
0 1 1 16-bit timer
8-bit auto-
1 0 2
reload
1 1 3 Split mode
This is one of the rarities being kept only for compatibility with the previuos versions of the
microcontrollers. When using this mode, the higher byte TH0 and only the first 5 bits of the
lower byte TL0 are in use. Being configured in this way, the Timer 0 uses only 13 of all 16 bits.
How does it operate? With each new pulse coming, the state of the lower register (that one with
5 bits) is changed. After 32 pulses received it becomes full and automatically is reset, while the
higher byte TH0 is incremented by 1. This action will be repeated until registers count up 8192
pulses. After that, both registers are reset and counting starts from 0.
Timer 0 in mode 1 (16-bit timer)
All bits from the registers TH0 and TL0 are used in this mode. That is why for this mode is being
more commonly used. Counting is performed in the same way as in mode 0, with difference that
the timer counts up to 65 536, i.e. as far as the use of 16 bits allows.
Timer 0 in mode 2 (Auto-Reload Timer)
What does auto-reload mean? Simply, it means that such timer uses only one 8-bit register for
counting, but it never counts from 0 but from an arbitrary chosen value (0- 255) saved in another
register.
The advantages of this way of counting are described in the following example: suppose that for
any reason it is continuously needed to count up 55 pulses at a time from the clock generator.
When using mode 1 or mode 0, It is needed to write number 200 to the timer registers and check
constantly afterwards whether overflow occured, i.e. whether the value 255 is reached by
counting . When it has occurred, it is needed to rewrite number 200 and repeat the whole
procedure. The microcontroller performs the same procedure in mode 2 automatically. Namely,
in this mode it is only register TL0 operating as a timer ( normally 8-bit), while the value from
which counting should start is saved in the TH0 register. Referring to the previous example, in
order to register each 55th pulse, it is needed to write the number 200 to the register and
configure the timer to operate in mode 2.
Timer 0 in Mode 3 (Split Timer)
By configuring Timer 0 to operate in Mode 3, the 16-bit counter consisting of two registers TH0
and TL0 is split into two independent 8-bit timers. In addition, all control bits which belonged to
the initial Timer 1 (consisting of the registers TH1 and TL1), now control newly created Timer 1.
This means that even though the initial Timer 1 still can be configured to operate in any mode (
mode 1, 2 or 3 ), it is no longer able to stop, simply because there is no bit to do that. Therefore,
in this mode, it will uninterruptedly “operate in the background “.
The only application of this mode is in case two independent 'quick' timers are used and the
initial Timer 1 whose operating is out of control is used as baud rate generator.
This is also one of the registers whose bits directly control timer operating.
Only 4 of all 8 bits this register has are used for timer control, while others are used for interrupt
control which will be discussed later.
Normally, first this timer and afterwards its mode should be selected. Bits which control that are
resided in the register TMOD:
This means that timer 0 operates in mode 1 and counts pulses from internal source whose
frequency is equal to 1/12 the quartz frequency.
In order to enable the timer, turn it on:
Immediately upon the bit TR0 is set, the timer starts operating. Assuming that a quartz crystal
with frequency of 12MHz is embedded, a number it contains will be incremented every
microsecond. By counting up to 65.536 microseconds, the both registers that timer consists of
will be set. The microcontroller automatically reset them and the timer keeps on repeating
counting from the beginning as far as the bit’s value is logic one (1).
Depending on the timer’s application, it is needed to read a number in the timer registers or to
register a moment they have been reset.
- Everything is extremely simple when it is needed to read a value of the timer which uses only
one register for counting (mode 2 or Mode 3) . It is sufficient to read its state at any moment and
it is it!
- It is a bit complicated to read a timer’s value when it operates in mode 2. Assuming that the
state of the lower byte is read first (TL0) and the state of the higher byte (TH0) afterwards, the
result is:
Everything seems to be in order at first sight, but the current state of register at the moment of
reading was:
In case of negligence, this error in counting ( 255 pulses ) may occur for not so obvious but quite
logical reason. Reading the lower byte is correct ( 255 ), but at the same time the program
counter “ was taking “ a new instruction for the TH0 state reading, an overflow occurred and
both registers have changed their contents ( TH0: 14→15, TL0: 255→0). The problem has
simple solution: the state of the higher byte should be read first, then the state of the lower byte
and once again the state of the higher byte. If the number stored in the higher byte is not the
same both times it has been read then this sequence should be repeated ( this is a mini- loop
consisting of only 3 instructions in a program).
There is another solution too. It is sufficient to simply turn timer off while reading ( the bit TR0
in the register TCON should be 0), and turn it on after that.
Usually, there is no need to continuously read timer registers’ contents. It is sufficient to register
the moment they are reset, i.e. when counting starts from 0. It is called overflow. When this has
occurred, the bit TF0 from the register TCON will be automatically set. The microcontroller is
waiting for that moment in a way that program will constantly check the state of this bit.
Furthermore, an interrupt to stop the main program execution can be enabled. Assuming that it is
needed to provide a program pause ( time the program appeared to be stopped) in duration of for
example 0.05 seconds ( 50 000 machine cycles ):
First, it is needed to calculate a number that should be written to the timer registers:
This number should be written to the timer registers TH0 and TL0:
Once the timer is started it will continue counting from the written number. Program instruction
checks if the bit TF0 is set, which happens at the moment of overflow, i.e. after exactly 50.000
machine cycles and 0.05 seconds respectively.
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.
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.
2.7 UART (Universal Asynchronous Receiver and Transmitter)
One of the features that makes this microcontroller so powerful is an integrated UART, better
known as a serial port. It is a duplex port, which means that it can transmit and receive data
simultaneously. Without it, serial data sending and receiving would be endlessly complicated
part of the program where the pin state continuously is being changed and checked according to
strictly determined rhythm. Naturally, it does not happen here because the UART resolves it in a
very elegant manner. All the programmer needs to do is to simply select serial port mode and
baud rate. When the programmer is such configured, serial data sending is done by writing to the
register SBUF while data receiving is done by reading the same register. The microcontroller
takes care of all issues necessary for not making any error during data exchange.
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 :
TRANSMIT - Data transmission in form of pulse train automatically starts on the pin RXD at
the moment the data has been written to the SBUF register.In fact, this process starts after any
instruction being performed on this register. Upon all 8 bits have been sent, the bit TI in the
SCON register is automatically set.
RECEIVE - Starts data receiving through the pin RXD once two necessary conditions are met:
bit REN=1 and RI=0 (both bits reside in the SCON register). Upon 8 bits have been received, the
bit RI (register SCON) is automatically set, which indicates that one byte is received.
Since, there are no START and STOP bits or any other bit except data from the SBUF register,
this mode is mainly used on shorter distance where the noise level is minimal and where
operating rate is important. A typical example for this is I/O port extension by adding cheap IC
circuit ( shift registers 74HC595, 74HC597 and similar).
Mode 1
In Mode1 10 bits are transmitted through TXD or received through RXD in the following
manner: a START bit (always 0), 8 data bits (LSB first) and a STOP bit (always 1) last. The
START bit is not registered in this pulse train. Its purpose is to start data receiving mechanism.
On receive the STOP bit is automatically written to the RB8 bit in the SCON register.
TRANSMIT - A sequence for data transmission via serial communication is automatically
started upon the data has been written to the SBUF register. End of 1 byte transmission is
indicated by setting the TI bit in the SCON register.
RECEIVE - Receiving starts as soon as the START bit (logic zero (0)) appears on the pin RXD.
The condition is that bit REN=1and bit RI=0. Both of them are stored in the SCON register. The
RI bit is automatically set upon receiving has been completed.
The Baud rate in this mode is determined by the timer 1 overflow time.
Mode 2
In mode 2, 11 bits are sent through TXD or received through RXD: a START bit (always 0), 8
data bits (LSB first), additional 9th data bit and a STOP bit (always 1) last. On transmit, the 9th
data bit is actually the TB8 bit from the SCON register. This bit commonly has the purpose of
parity bit. Upon transmission, the 9th data bit is copied to the RB8 bit in the same register (
SCON).The baud rate is either 1/32 or 1/64 the quartz oscillator frequency.
RECEIVE - Receiving starts as soon as the START bit (logic zero (0)) appears on the pin RXD.
The condition is that bit REN=1and bit RI=0. Both of them are stored in the SCON register. The
RI bit is automatically set upon receiving has been completed.
Mode 3
Mode 3 is the same as Mode 2 except the baud rate. In Mode 3 is variable and can be selected.
The parity bit is the bit P in the PSW register. The simplest way to check correctness of the
received byte is to add this parity bit to the transmit side as additional bit. Simply, immediately
before transmit, the message is stored in the accumulator and the bit P goes into the TB8 bit in
order to be “a part of the message”. On the receive side is the opposite : received byte is stored in
the accumulator and the bit P is compared with the bit RB8 ( additional bit in the message). If
they are the same- everything is OK!
Baud Rate
Baud Rate is defined as a number of send/received bits per second. In case the UART is used,
baud rate depends on: selected mode, oscillator frequency and in some cases on the state of the
bit SMOD stored in the SCON register. All necessary formulas are specified in the table :
Mode 0 Fosc. / 12
1 Fosc.
Mode 1 16 12 (256- BitSMOD
TH1)
Fosc. / 32 1
Mode 2
Fosc. / 64 0
1 Fosc.
Mode 3 16 12 (256-
TH1)
Timer 1 as a baud rate generator
Timer 1 is usually used as a baud rate generator because it is easy to adjust various baud rate by
the means of this timer. The whole procedure is simple:
Fosc. (MHz)
Baud Rate Bit SMOD
11.0592 12 14.7456 16 20
150 40 h 30 h 00 h 0
300 A0 h 98 h 80 h 75 h 52 h 0
600 D0 h CC h C0 h BB h A9 h 0
1200 E8 h E6 h E0 h DE h D5 h 0
2400 F4 h F3 h F0 h EF h EA h 0
4800 F3 h EF h EF h 1
4800 FA h F8 h F5 h 0
9600 FD h FC h 0
9600 F5 h 1
19200 FD h FC h 1
38400 FE h 1
76800 FF h 1
Multiprocessor Communication
As described in the previous text, modes 2 and 3 enable the additional 9th data bit to be part of
message. It can be used for checking data via parity bit. Another useful application of this bit is
in communication between two microcontrollers, i.e. multiprocessor communication. This
feature is enabled by setting the SM2 bit in the SCON register. The consequence is the
following: when the STOP bit is ready, indicating end of message, the serial port interrupt will
be requested only in case the bit RB8 = 1 (the 9th bit).
Suppose that there are several connected microcontrollers having to exchange data. That means
that each of them must have its address. The point is that each address sent via serial
communication has the 9th bit set (1), while data has it cleared (0). If the microcontroller A
should send data to the microcontroller C then it at will place first send address of C and the 9th
bit set to 1. That will generate interrupt and all microcontrollers will check whether they are
called.
Of course, only one of them will recognize this address and immediately clear the bit SM2 in the
SCON register. All following data will be normally received by that microcontroller and ignored
by other microcontrollers.
2.8 8051 Microcontroller Interrupts
There are five interrupt sources for the 8051, which means that they can recognize 5 different
event that can interrupt regular program execution. Each interrupt can be enabled or disabled by
setting bits in the IE register. Also, as seen from the picture below the whole interrupt system can
be disabled by clearing bit EA from the same register.
Now, one detail should be explained which is not completely obvious but refers to external
interrupts- INT0 and INT1. Namely, if the bits IT0 and IT1 stored in the TCON register are set,
program interrupt will occur on changing logic state from 1 to 0, (only at the moment). If these
bits are cleared, the same signal will generate interrupt request and it will be continuously
executed as far as the pins are held low.
Interrupt Priorities
It is not possible to predict when an interrupt will be required. For that reason, if several
interrupts are enabled. It can easily occur that while one of them is in progress, another one is
requested. In such situation, there is a priority list making the microcontroller know whether to
continue operating or meet a new interrupt request.
1. Reset! The apsolute master of the situation. If an request for Reset omits, everything is stopped
and the microcontroller starts operating from the beginning.
2. Interrupt priority 1 can be stopped by Reset only.
3. Interrupt priority 0 can be stopped by both Reset and interrupt priority 1.
Which one of these existing interrupt sources have higher and which one has lower priority is
defined in the IP Register ( Interrupt Priority Register). It is usually done at the beginning of the
program. According to that, there are several possibilities:
Once an interrupt service begins. It cannot be interrupted by another inter rupt at the same or
lower priority level, but only by a higher priority interrupt.
If two interrupt requests, at different priority levels, arrive at the same time then the higher
priority interrupt is serviced first.
If the both interrupt requests, at the same priority level, occur one after another , the one who
came later has to wait until routine being in progress ends.
If two interrupts of equal priority requests arrive at the same time then the interrupt to be
serviced is selected according to the following priority list :
The IP register bits specify the priority level of each interrupt (high or low priority).
Handling Interrupt
Once some of interrupt requests arrives, everything occurs according to the following order:
IE0 3h
TF0 Bh
TF1 1B h
RI, TI 23 h
From the moment an interrupt is enabled, the microcontroller is on alert all the time. When
interrupt request arrives, the program execution is interrupted, electronics recognizes the cause
and the program “jumps” to the appropriate address (see the table above ). Usually, there is a
jump instruction already prepared subroutine prepared in advance. The subroutine is executed
which exactly the aim- to do something when something else has happened. After that, the
program continues operating from where it left off…
Reset
Reset occurs when the RS pin is supplied with a positive pulse in duration of at least 2 machine
cycles ( 24 clock cycles of crystal oscillator). After that, the microcontroller generates internal
reset signal during which all SFRs, excluding SBUF registers, Stack Pointer and ports are reset (
the state of the first two ports is indefinite while FF value is being written to the ports
configuring all pins as inputs). Depending on device purpose and environment it is in, on power-
on reset it is usually push button or circuit or both connected to the RS pin. One of the most
simple circuit providing secure reset at the moment of turning power on is shown on the picture.
Everything functions rather simply: upon the power is on, electrical condenser is being charged
for several milliseconds through resistor connected to the ground and during this process the pin
voltage supply is on. When the condenser is charged, power supply voltage is stable and the pin
keeps being connected to the ground providing normal operating in that way. If later on, during
the operation, manual reset button is pushed, the condenser is being temporarily discharged and
the microcontroller is being reset. Upon the button release, the whole process is repeated…
The microcontrollers normally operate at very high speed. The use of 12 Mhz quartz crystal
enables 1.000.000 instructions per second to be executed! In principle, there is no need for higher
operating rate. In case it is needed, it is easy to built-in crystal for high frequency. The problem
comes up when it is necessary to slow down. For example, when during testing in real operating
environment, several instructions should be executed step by step in order to check for logic state
of I/O pins.
Interrupt system applied on the 8051 microcontrollers practically stops operating and enables
instructions to be executed one at a time by pushing button. Two interrupt features enable that:
Interrupt request is ignored if an interrupt of the same priority level is being in progress.
Upon interrupt routine has been executed, a new interrupt is not executed until at least one
instruction from the main program is executed.
What is going on? Once the pin P3.2 is set to “0” (for example, by pushing button), the
microcontroller will interrupt program execution jump to the address 03hex, will be executed a
mini-interrupt routine consisting of 3 instructions is located at that address.
The first instruction is being executed until the push button is pressed ( logic one (1) on the pin
P3.2). The second instruction is being executed until the push button is released. Immediately
after that, the instruction RETI is executed and processor continues executing the main program.
After each executed instruction, the interrupt INT0 is generated and the whole procedure is
repeated ( push button is still pressed). Button Press = One Instruction.
Conditionally said microcontroller is the most part of its “lifetime” is inactive for some external
signal in order to takes its role in a show. It can make a great problem in case batteries are used
for power supply. In extremely cases, the only solution is to put the whole electronics to sleep in
order to reduce consumption to the minimum. A typical example of this is remote TV controller:
it can be out of use for months but when used again it takes less than a second to send a
command to TV receiver. While normally operating, the AT89S53 uses current of approximately
25mA, which shows that it is not too sparing microcontroller. Anyway, it doesn’t have to be
always like this, it can easily switch the operation mode in order to reduce its total consumption
to approximately 40uA. Actually, there are two power-saving modes of operation: Idle and
Power Down.
Idle mode
Immediately upon instruction which sets the bit IDL in the PCON register, the microcontroller
turns off the greatest power consumer- CPU unit while peripheral units serial port, timers and
interrupt system continue operating normally consuming 6.5mA. In Idle mode, the state of all
registers and I/O ports is remains unchanged.
In order to terminate the Idle mode and make the microcontroller operate normally, it is
necessary to enable and execute any interrupt or reset.Then, the IDL bit is automatically cleared
and the program continues executing from instruction following that instruction which has set
the IDL bit. It is recommended that three first following one which set NOP instructions. They
do not perform any operation but keep the microcontroller from undesired changes on the I/O
ports.
When the bit PD in the register PCON is set from within the program, the microcontroller is set
to Powerdown mode. It and turns off its internal oscillator reducing drastically consumption in
that way. In power- down mode the microcontroller can operate using only 2V power supply
while the total power consumption is less than 40uA. The only way to get the microcontroller
back to normal mode is reset.
During Power Down mode, the state of all SFR registers and I/O ports remains unchanged, and
after the microcontroller is put get into the normal mode, the content of the SFR register is lost,
but the content of internal RAM is saved. Reset signal must be long enough approximately 10mS
in order to stabilize quartz oscillator operating.
PCON register
Introduction
Writing program for the microcontroller mainly consists of giving instructions (commands) in
that order in which they should be executed later in order to carry out specific task. As
electronics can not “understand” what for example instruction “if the push button is pressed- turn
the light on” means, then a certain number of more simpler and precisely defined orders that
decoder can recognise must be used. All commands are known as INSTRUCTION SET. All
microcontrollers compatibile with the 8051 have in total of 255 instructions, i.e. 255 different
words available for program writing.
At first sight, it is imposing number of odd signs that must be known by heart. However, It is not
so complicated as it looks like. Many instructions are considered to be “different”, even though
they perform the same operation, so there are only 111 truly different commands. For example:
ADD A,R0, ADD A,R1, ... ADD A,R7 are instructions that perform the same operation (additon
of the accumulator and register) but since there are 8 such registers, each instruction is counted
separately! Taking into account that all instructions perform only 53 operations ( addition,
subtraction, copy etc.) and most of them are rarely used in practice, there are actually 20-30
shortened forms needed to be known, which is acceptable.
Depending on operation they perform, all instructions are divided in several groups:
Arithmetic Instructions
Branch Instructions
Data Transfer Instructions
Logical Instructions
Logical Instructions with bits
The first part of each instruction, called MNEMONIC refers to the operation an instruction
performs (copying, addition, logical operation etc.). Mnemonics commonly are shortened form
of name of operation being executed. For example:
Another part of instruction, called OPERAND is separated from mnemonic at least by one empty
space and defines data being processed by instructions. Some instructions have no operand, some
have one, two or three. If there is more than one operand in instruction, they are separated by
comma. For example:
Arithmetic instructions
ADD A,R1 - The result of addition (A+R1) will be stored in the accumulator.
Arithmetical Instructions
Oscillator
Mnemonic Description Byte Number
Period
Branch Instructions
Unconditional jump instructions: after their execution a jump to a new location from where the
program continues execution is executed.
Conditional jump instructions: if some condition is met - a jump is executed. Otherwise, the
program normally proceeds with the next instruction.
Branch Instruction
Oscillator
Mnemonic Description Byte Number
Period
JBC bit,rel Jump if addressed bit is set and clear it. Short jump. 3 4
NOP No operation 1 1
These instructions move the content of one register to another one. The register which content is
moved remains unchanged. If they have the suffix “X” (MOVX), the data is exchanged with
external memory.
Logical Instruction
These instructions perform logical operations between corresponding bits of two registers. After
execution, the result is stored in the first operand.
Logical Instructions
Similar to logical instructions, these instructions perform logical operations. The difference is
that these operations are performed on single bits.
Logical operations on bits
ANL C,bit Logical AND between Carry bit and directly addressed bit 2 2
ORL C,bit Logical OR between Carry bit and directly addressed bit 2 2
The operands listed below are written in shortened forms having the following meaning :
A - accumulator
Rn - Rn is one of R registers (R0-R7) in the currently active bank in RAM.
Rx - Rx is any register in RAM with 8-bit address. It can be a general-purpose register or SFR Register (I/O
port, control register etc.)
@Ri - Ri is R0 or R1 register in the currently active bank. It contains register.
address - the instruction is referring to.
#X - X is any 8-bit number (0-255).
#X16 - X is any 16-bit number (0-65535).
adr16 - 16-bit address is specified
adr11 - 11-bit address is specified
rel - The address of a close memory location is specified (-128 do +127 rela tive to the current one).
Basing on that address,
Asembler computes the value which is added or subtructed to the number which currently stored in the
program counter.
bit - Bit address is specified.
C - Carry bit in the status register (register PSW)
EXAMPLE:
Before execution: PC=0123h
After execution: PC=0345h
A: accumulator
Rn: Any R register (R0-R7)
Description: Instruction adds the number in the accumulator and the number in register Rn (R0-
R7). After addition, the result is stored in the accumulator.
EXAMPLE:
Before execution: A=2Eh (46 dec.) R4=12h (18 dec.)
After execution: A=40h (64 dec.) R4=12h
A: accumulator
Ri: Register R0 or R1
Description: Instruction adds number in the accumulator and number in Rx. The register Rx
address is in the Ri register (R0 or R1). After addition, the result is stored in the accumulator.
EXAMPLE:
A: accumulator
Rx: Arbitrary register with address 0 - 255 (0 - FFh)
Description: Instruction adds the accumulator and Rx register. As it is direct addressing, Rx can
be some of SFRs or general-purpose register with address 0-7 Fh. The result is stored in the
accumulator.
EXAMPLE:
A: accumulator
Rn: any R register (R0-R7)
Description: Instruction adds the accumulator, Carry bit and value in Rn register (R0-R7). After
addition, the result is stored in the accumulator.
EXAMPLE:
Before execution: A= C3h (195 dec.) R0= AAh (170 dec.) C=1
After execution: A= 6Eh (110 dec.) AC=0, C=1, OV=1
A: accumulator
X: Constant within 0 - 255 (0-FFh)
Description: Instruction adds the accumulator and number X (0-255). After addition, the result
is stored in the accumulator.
EXAMPLE:
ADDC A,Rx - Add accumulator, directly addressed register Rx and Carry bit
A: accumulator
Rx: Arbitrary register with address 0 - 255 (0 - FFh)
Description: Instruction adds value in the accumulator and Rx register including the Carry bit as
well. As it is direct addressing, Rx can be some of SFRs or general purpose register with address
0-7Fh (0-127dec.). The result is stored in the accumulator.
EXAMPLE:
Before execution: A= C3h (195 dec.) TEMP = AAh (170 dec.) C=1
After execution: A= 6Eh (110 dec.) AC=0, C=1, OV=1
ADDC A,@Ri - Add Carry bit, accumulator and indirectly addressed register Rx
A: accumulator
Ri: Register R0 or R1
Description: Instruction adds value in the accumulator and number in the Rx register. The Carry
bit is also added. Register Rx address is in the Ri register (R0 or R1). After addition, the result is
stored in the accumulator.
EXAMPLE:
Register address: SUM = 4Fh R0=4Fh
Before execution: A= C3h (195 dec.) SUM = AAh (170 dec.) C=1
After execution: A= 6Eh (110 dec.) AC=0, C=1, OV=1
A: accumulator
X: Constant within 0 - 255 (0-FFh)
Description: Instruction adds number in the accumulator and number X (0- 255). The Carry bit
is also added. After addition, the result is stored in the accumulator.
EXAMPLE:
Description : Program continues execution upon a jump to the specified address has been
executed. Similar to the ACALL instruction , this jump must be executed within the same 2K
byte block of program memory (starting from the first byte of the instruction following AJMP).
EXAMPLE:
Before execution: PC=0345h SP=07h
After execution: PC=0123h SP=09h
A: accumulator
Rn: Any R register (R0-R7)
Description: Instruction performs the logical-AND operation between the accumulator and Rn
register. The result of this logical operation is stored in the accumulator.
EXAMPLE:
Before execution: A= C3h (11000011 Bin.)
R5= 55h (01010101 Bin.)
After execution: A= 41h (01000001 Bin.)
ANL A,Rx - Logical-AND operation between accumulator and directly addressed register
A: accumulator
Rx: Arbitrary register with address 0 - 255 (0 - FFh)
EXAMPLE:
A: accumulator
Ri: Register R0 or R1
EXAMPLE:
A: accumulator
X: Constant in the range of 0 - 255 (0-FFh)
Description: Instruction performs logical-AND operation between the accumulator and number
X. The result is stored in the accumulator.
EXAMPLE:
Before execution: A= C3h (11000011 Bin.)
After execution: A= 41h (01000001 Bin.)
ANL Rx,A - Logical-AND operation between directly addressed register Rx and accumulator
EXAMPLE:
Description: Instruction performs logical-AND operation between the register Rx and number
X. As it is direct addressing, Rx can be some of SFRs or general-purpose register with address 0-
7Fh (0-127 dec.). The result of this logical operation is stored in the Rx register.
EXAMPLE:
Before execution: X= C3h (11000011 Bin.) MASK= 55h (01010101 Bin.) After execution:
MASK= 41h (01000001 Bin.)
C: Carry
bit: Any bit in RAM
Description: Instruction performs logical-AND operation between the addressed bit and Carry
bit.
0 0 0
0 1 0
1 0 0
1 1 1
EXAMPLE:
ANL C,/bit - Logical-AND opertaion between complement of bit and Carry bit
C: Carry
bit: Any bit in RAM
Description: Instruction performs logical-AND operation between inverted addressed bit and
Carry bit. The result is stored in the Carry bit.
0 1 0 0
0 1 1 1
1 0 0 0
1 0 1 0
EXAMPLE:
CJNE A,Rx,rel - Compare directly addessed byte with accumulator and jump if they are not
equal
A: accumulator
Rx: Arbitrary register with address 0 - 255 (0 - FFh)
adr. Jump Address
Description: Instruction first compares the number in the accumulator with the number in Rx
register. If they are equal, the program continues execution. Otherwise, a jump to the indicated
address in the program will be executed. This is a short jump instruction, which means that the
address of a new location must be relatively near the current position in the program (-128 to
+127 locations relative to the first following instruction).
EXAMPLE:
Before execution: PC=0145h A=27h
After execution: if MAX≠27: PC=0123h
If MAX=27: PC=0146h
CJNE A,#X,rel - Compare number X with accumulator and jump if they are not equal
A: accumulator
X: Constant in the range of 0 - 255 (0-FFh)
Description: Instruction first compares the number in the accumulator with number X. If they are
equal, the program continues execution. Otherwise, a jump to the specified address in the
program will be executed. This is a short jump instruction, which means that the address of a
new location must be relatively near the current position in the program (-128 to +127 locations
relative to the first following instruction)
EXAMPLE:
Before execution: PC=0445h
After execution: If A≠33: PC=0423h
If A=33: PC=0446h
CJNE Rn,#X,rel - Compare number X with register Rn and jump if they are not equal
Description: Instruction first compares number in the Rx register with number X. If they are
equal, the program continues execution. Otherwise, a jump to the specified address in the
program will be executed. This is a short jump instruction, which means that the address of a
new location must be relatively near the current position in the program ( -128 to + 127 locations
relative to the first following instruction).
EXAMPLE:
Before execution: PC=0345h
After execution : If R5≠44h: PC=0323h
If R5=44h: PC=0346h
CJNE @Ri,#X,rel - Compare indirectly addressed register with number X and jump if they are
not equal
Ri: Register R0 or R1
X: Constant in the range of 0 - 255 (0-FFh)
Description: Register Rx address is stored in the Ri register (R0 or R1). This instruction first
compares the number in Rx register with number X. If they are equal, the program continues
execution. Otherwise, a jump to the indicated address in the program will be executed.This is a
short jump instruction, which means that the address of a new location must be relatively near
the current position in the program (-128 to +127 locations relative to the next instruction).
EXAMPLE:
Before execution: Register Address SUM=F3h
PC=0345h R0=F3h
After execution : If SUM≠44h: PC=0323h
If SUM=44h: PC=0346h
A: accumulator
Syntax: CLR A
Byte: 1 (Instruction Code)
STATUS register flags: No flags are affected.
EXAMPLE:
After execution : A=0
C: Carry Bit
Syntax: CLR C
Byte: 1 (Instruction Code)
STATUS register flags: C
EXAMPLE:
EXAMPLE:
A: accumulator
Syntax: CPL A
Bytes: 1 (Instruction Code)
STATUS register flags: No flags are affected.
EXAMPLE:
EXAMPLE:
C: Carry bit
Syntax: CPL C
Byte: 1 (Instruction Code)
STATUS register flags: C
EXAMPLE:
Before execution: C=1
After execution: C=0
A: accumulator
Description: This instruction corrects the value after binary addition in order to fit BCD format.
Prior to addition, both numbers have to be in BCD format, which means that it is not just a
simple coversion of hexadecimal numbers into BCD numbers.The result of this operation in form
of two 4-digit BCD numbers is stored in the Accumaulator.
Syntax: DA A
Byte: 1 (Instruction Code)
STATUS register flags: C
EXAMPLE:
A: accumulator
Syntax: DEC A
Byte: 1 (Instruction Code)
STATUS register flags: No flags are affected.
EXAMPLE:
Syntax: DEC Rn
Byte: 1 (Instruction Code)
STATUS register flags: No flags are affected.
EXAMPLE:
EXAMPLE:
A: accumulator
B: Register B
Description: Instruction divides value in the accumulator by the value in the B register. After
division the integer part of result is stored in the accumulator while the register contains the
remainder. In case of dividing by 1, the flag OV is set and the result of division is unpredictable.
The 8-bit quotient is stored in the accumulator and the 8-bit remainder is stored in the B register.
Syntax: DIV AB
Byte: 1 (Instruction Code)
STATUS register flags: C, OV
EXAMPLE:
Before execution: A=FBh (251dec.) B=12h (18 dec.)
After execution: A=0Dh (13dec.) B=11h (17dec.)
13·18 + 17 =251
Ri: Register R0 or R1
EXAMPLE:
EXAMPLE:
EXAMPLE:
Description: This instruction increments value in the Rn register by 1. If the register includes the
number 255, the result of the operation will be 0.
Syntax: INC Rn
Byte: 1 (Instruction Code)
STATUS register flags: No flags are affected.
EXAMPLE:
A: accumulator
Syntax: INC A
Byte: 1 (Instruction Code)
STATUS register flags: No flags are affected.
EXAMPLE:
EXAMPLE:
Description: This instruction increments value of the Rx register by 1.If the register includes the
number 255, the result of the operation will be 0. As it is direct addressing, Rx must be within
the first 255 RAM locations.
Syntax: INC Rx
Bytes: 2 (Instruction Code, Address Rx)
STATUS register flags: No flags are affected.
EXAMPLE:
Before execution: CNT=33h
After execution: CNT=34h
Description: If the bit is set, a jump to the specified address will be executed. Otherwise, if the
value of bit is 0, the program proceeds with the next instruction. This is a short jump instruction,
which means that the address of a new location must be relatively near the current position in the
program (-128 to + 127 locations relative to the first following instruction).
EXAMPLE:
Before execution: PC=0323h
After execution: If P0.5=0: PC=0324h
If P0.5=1: PC=0345h
Description: This instruction increments value of the 16-bit data pointer by 1. This is a single
16-bit register on which this operation can be performed.
EXAMPLE:
Before execution: DPTR = 13FF (DPH = 13h DPL = FFh )
After execution: DPTR = 1400 (DPH = 14h DPL = 0)
Description: This instruction first check if the Carry bit is set. If it is set, a jump to the indicated
address is executed. Otherwise, the program proceeds with the next instruction. This is a short
jump instruction, which means that the address of a new location must be relatively near the
current position in the program (-129 to + 127 locations relative to the first following
instruction).
EXAMPLE:
Description: This instruction first checks if the bit is set. If it is set, a jump to the specified
address is executed and afterwards the bit is cleared. Otherwise, the program proceeds with the
first next instruction. This is a short jump instruction, which means that the address of a new
location must be relatively near the current position in the program (-129 to + 127 locations
relative to the first following instruction).
EXAMPLE:
Description: If the bit is cleared, a jump to the specified address will be executed. Otherwise, if
the bit value is 1, the program proceeds with the first next instruction. This is a short jump
instruction, which means that the address of a new location must be relatively near the current
position in the program (-129 to + 127 locations relative to the first following instruction).
EXAMPLE:
A: accumulator
DPTR: Data Pointer
Description: This instruction causes a jump to address which is calculated by adding value in
the accumulator and 16-bit number in the DPTR Register. It is used with complex program
branching where the accumulator affects jump address, for example when reading table. Neither
accumulator nor DPTR register are affected.
Syntax: JMP @A+DPTR
Byte: 1 (Instruction Code)
STATUS register flags: No flags are affected.
EXAMPLE:
Note:
As instructions AJMP LABELS occupy two locations each, the values in the accumulator
indicating them must be mutually different from each other by 2.
Description: This instruction checks if value in the accumulator is 0. If it is not 0, a jump to the
specified address will be executed. Otherwise, the program proceeds with the first next
instruction. This is a short jump instruction, which means that the address of a new location must
be relatively near the current position in the program (-129 to + 127 locations relative to the first
following instruction).
Description: This instruction first checks if the bit is set. If it is not set, a jump to the specified
address will be executed. Otherwise, the program proceeds with the first next instruction.This is
a short jump instruction, which means that the address of a new location must be relatively near
the current position in the program (-129 to + 127 locations relative to the first following
instruction).
EXAMPLE:
Before execution: PC=0323h
After Sexecution: If C=0: PC=360h
If C=1: PC=324h
Description: This instruction unconditionally calls a subroutine located at the specified address.
The current address and the start of the called subroutine can be located anywhere within the
memory space of 64K.
EXAMPLE:
Before execution: PC=0123h
After execution: PC=1234h
Description: The instruction checks if the value in the accumulator is 0. If it is 0, a jump to the
specified address will be executed. Otherwise, the program proceeds with the next
instruction.This is a short jump instruction, which means that the address of a new location must
be relatively near the current position in the program (-129 to + 127 locations relative to the first
following instruction).
EXAMPLE:
Before execution: PC=0323h
After execution: If A0: PC=324h
If A=0: PC=283h
Description: The instruction moves the Rn register to the accumulator. The Rn register is not
affected.
EXAMPLE:
EXAMPLE:
Ri: Register R0 or R1
A: accumulator
Description: Instruction moves the Rx register to the accumulator. Rx register address is stored
in the Ri register (R0 or R1). After instruction execution, the result is stored in the accumulator.
The Rx Register is not affected.
EXAMPLE:
Register Address SUM=F2h R0=F2h
Before execution: SUM=58h
After execution : A=58h SUM=58h
EXAMPLE:
Desription: Instruction moves the accumulator to Rn register. The accumulator is not affected.
EXAMPLE:
A: accumulator
X: Constant in the range of 0 - 255 (0-FFh)
EXAMPLE:
After execution: A=28h
EXAMPLE:
EXAMPLE:
EXAMPLE:
EXAMPLE:
Description: Instruction moves the Ry register to Rx register. Ry register address is stored in the
Ri register (R0 or R1). The Ry register is not affected .
EXAMPLE:
Register Address SUM=F3
Before execution: SUM=58h R1=F3
After execution: SUM=58h TEMP=58h
EXAMPLE:
A: accumulator
Ri: Register R0 or R1
Description: Instruction moves the accumulator to the Rx register. The Rx register address is
stored in the Ri register (R0 or R1). After instruction execution, the accumulator is not affected.
EXAMPLE:
EXAMPLE:
After execution: TEMP=22h
Ri: Register R0 or R1
X: Constant in the range of 0 - 255 (0-FFh)
Description: Instruction moves number X to the idirectly addressed register Rx. The Register Rx
address is stored in the Ri register ( R0 or R1).
EXAMPLE:
Description: Instruction moves the Rx register to Ry register. The register Ry address is stored
in the Ri register ( R0 or R1). After instruction execution, the Rx register is not affected.
EXAMPLE:
Register address TEMP=E2h
Before execution: SUM=58h R1=E2h
After execution: SUM=58h TEMP=58h
C: Carry bit
bit: Any bit in RAM
Description: Instruction moves the value of the Carry bit to the specified bit. After this
operation, the Carry bit is not affected.
EXAMPLE:
C: Carry bit
bit: Any bit in RAM
Description: Instruction moves value of the specified bit to the Carry bit. After this operation,
the bit is not affected.
EXAMPLE:
MOVC A,@A+DPTR - Move relatively addressed byte from program memory to accumulator
A: accumulator
DPTR: Data Pointer
Description: Instruction first adds the 16-bit DPTR Register and the accumulator. The result of
addition is afterwards used as address in the program memory indicating from which the 8-bit
content is moved to the accumulator.
EXAMPLE:
Before execution :
DPTR=1000:
A=0
A=1
A=2
A=3
After execution:
A=66h
A=77h
A=88h
A=99h
Description: Instruction writes 16-bit number into the DPTR register. The 8 high bits of this
number are stored in the DPH register while the 8 low bits are stored in the DPL register.
EXAMPLE:
After execution: DPH=12h DPL=34h
Ri: Register R0 or R1
A: accumulator
Description: Instruction reads the content of the Rx register in external RAM and moves it to the
accumulator. The register Rx address is stored in the Ri register (R0 or R1).
EXAMPLE:
Note:
SUMA Register is stored in external RAM in size of 256 bytes.
MOVC A,@A+PC - Move relatively addressed byte from program memory to accumulator
A: accumulator
PC: Program Counter
Description: Instruction first adds the 16-bit PC register with the content of the accumulator (the
current address in the program is stored in the PC register). The result of addition is afterwards
used as address in the program memory from which the 8-bit content is moved to the
accumulator.
EXAMPLE:
After the subroutine "Tabela" has been executed, one of four values is stored in the accumulator:
Before execution:
A=0
A=1
A=2
A=3
After execution:
A=66h
A=77h
A=88h
A=99h
Note: DB (Define Byte) is directiv in assembler used to define constant.
MOVX @Ri,A - Write the content of accumulator into byte of external memory (8-bit address)
Ri: Register R0 or R1
A: accumulator
Description: Instruction reads the content of the accumulator and moves it to the Rx register
which is stored in external RAM. The Rx register address is located in the Ri register.
EXAMPLE:
NOTE:
Register SUM is located in external RAM in size of 256 byte.
MOVX A,@DPTR - Write the content of accumulator into byte of external memory (8-bit
address)
A: accumulator
DPRTR: Data Pointer
Description: Instruction reads the content of the Rx register in external memory and moves it to
the accumulator. The 16-bit address of the Rx register is stored in the DPTR register (DPH and
DPL).
Syntax: MOVX A,@DPTR
Byte: 1 (Instruction Code)
STATUS register flags: No flags affected.
EXAMPLE:
Note:
Register SUM is located in external RAM in size of up to 64K.
A: accumulator
B: Register B
Description: Instruction multiplies the value in the accumulator with the value in the B register .
The low-order byte of the 16-bit result is stored in the accumulator , and the high byte is left in
the B register. If the result is greater than 255, the overflow flag is set. The Carry bit (C flag) is
not affected.
Syntax: MUL AB
Byte: 1 (Instruction Code)
STATUS register flags: No flags affected.
EXAMPLE:
Before execution: A=80 (50h) B=160 (A0h)
After execution: A=0 B=32h
A·B=80·160=12800 (3200h)
MOVX @DPTR,A - Write value in accumulator to byte of external memory (16-bit address)
A: accumulator
DPTR: Data Pointer
Description: Instruction reads value in the accumulator and moves it to the Rx register which is
stored in external RAM. 16-bit address of the Rx register is stored in the DPTR register (DPH
and DPL).
EXAMPLE:
Note:
Register SUM is located in RAM in size of up to 64K.
EXAMPLE:
NOP - No operation
Description: Instruction doesn’t perform any operation and is used when additional time delays
are needed.
Syntax: NOP
Byte: 1 (Instruction Code)
STATUS register flags: No flags affected.
EXAMPLE:
Sequence like this one provides on the P2.3 a negative pulse which lasts exactly 5 machine
cycles. If a 12 MHz quartz crystal is used then 1 cycle lasts 1uS, which means that this output
will be a low-going output pulse for 5 uS.
ORL A,@Ri - Logical-OR operation between accumulator and indirectly addressed register
Ri: Register R0 or R1
A: accumulator
EXAMPLE:
Register Address TEMP=FAh
Before execution: R1=FAh
TEMP= C2h (11000010 Bin.)
A= 54h (01010100 Bin.)
After execution: A= D6h (11010110 Bin.)
EXAMPLE:
ORL Rx,A - Logical-OR operation between directly addressed register Rx and accumulator
EXAMPLE:
Description: Instruction performs logical-OR operation between the accumulator and number X.
The result of this logical operation is stored in the accumulator.
Syntax: ORL A, #X
Bytes: 2 (Instruction Code, Constant X)
STATUS register flags: No flags affected.
EXAMPLE:
C: Carry bit
bit: Any bit in RAM
Description: Instruction performs logical-OR operation (logical OR) between the addressed bit
and Carry bit. The result is stored in the Carry bit.
EXAMPLE:
ORL Rx,#X - Logical-OR operation between directly addressed register Rx and number X
Description: Instruction performs logical-OR operation between the Rx registers and number X.
As it is direct addressing, Rx can be some of SFRs or general-purpose register with address 0-
7Fh (0-127 dec.). The result of this logical operation is stored in the Rx register.
EXAMPLE:
Before execution: TEMP= C2h (11000010 Bin.)
After execution: A= D2h (11010010 Bin.)
Description: Instruction first reads data from the location the Stack Pointer is currently ponting
to. Afterwards, the data is copied to the register Rx and the value of the Stack Pointer is
decremented by 1. As it is direct addressing, Rx can be some of SFRs or general-purpose register
with address 0-7Fh. (0-127 dec.)
Syntax: POP Rx
Bytes: 2 (Instruction Code, Address Rx)
STATUS register flags: No flags affected.
EXAMPLE:
ORL C,/bit - Logical-OR operation between complement bit and Carry bit
C: Carry bit
bit: Any bit in RAM
0 1 0 0
0 1 1 1
1 0 0 0
1 0 1 0
EXAMPLE:
Syntax: RET
Byte: 1 (Instruction Code)
STATUS register flags: No flags affected.
EXAMPLE:
Syntax: PUSH Rx
Bytes: 2 (Instruction Code, Address Rx)
STATUS register flags: No flags affected.
EXAMPLE:
A: accumulator
Description: Eight bits in the accumulator are rotated one bit left, so that the bit 7 is rotated into
the bit 0 position.
Syntax: RL A
Byte: 1 (Instruction Code)
STATUS register flags: No flags affected.
EXAMPLE:
Before execution: A= C2h (11000010 Bin.)
After execution: A=85h (10000101 Bin.)
Description: This instruction ends every interrupt routine and informs processor that interrupt
routine is no longer in progress. After instruction execution, the execution of the interrupted
program continues from where it left off. The PSW is not autotomatically restored to its pre-
interrupt status.
Syntax: RETI
Byte: 1 (Instruction Code)
STATUS register flags: No flags affected.
A: accumulator
Description: All eight bits in the accumulator are rotaded one bit right so that the bit 0 is rotated
into the bit 7 position.
Syntax: RR A
Byte: 1 (Instruction Code)
STATUS register flags: No flags affected.
EXAMPLE:
A: accumulator
Description: All eight bits in the accumulator and Carry bit are rotated one bit left. After this
operation, the bit 7 is rotated into the Carry bit position and the Carry bit is rotated into the bit 0
position.
Syntax: RLC A
Byte: 1 (Instruction Code)
STATUS register flags: C
EXAMPLE:
Before execution: A= C2h (11000010 Bin.)
C=0
After execution: A= 85h (10000100 Bin.)
C=1
C: Carry bit
Syntax: SETB C
Byte: 1 (Instruction Code)
STATUS register flags: C
EXAMPLE:
After execution: C=1
A: accumulator
Description: All eight bits in the accumulator and Carry bit are rotated one bit right. After this
operation, the Carry bit is rotated into the bit 7 position and the bit 0 is rotated into the Carry
position.
Syntax: RRC A
Byte: 1 (Instruction Code)
STATUS register flags: C
EXAMPLE:
Description: Instruction enables jump to the new address that address should be in the range of -
128 to +127 locations relative to the first following instruction.
EXAMPLE:
Description: Instruction sets the specified bit. The register including that bit must belong to the
group of so called bit addressable registers.
EXAMPLE:
Description: Instruction performs subtract operation: A-Rx including the Carry bit as well which
acts as borrow. If the higher bit is subtracted from the lower bit then the Carry bit is set. As it is
direct addressing, Rx can be some of SFRs or general-purpose register with address 0-7Fh. (0-
127 dec.). The result is stored in the accumulator.
EXAMPLE:
Before execution: A=C9h, DIF=53h, C=0
After execution: A=76h, C=0
Description: Instruction performs subtract operation: A-Rn including the Carry as well which
acts as borrow. If the higher bit is subtracted from the lower bit then the Carry bit is set. The
result is stored in the accumulator.
EXAMPLE:
Note:
The result is different (C9 - 54=75!) because the Carry bit has been set (C=1)before instruction
execution.
Description: Instruction performs subtract operation: A-X including the Carry bit as well which
acts as borrow. If the higher bit is subtracted from the lower bit then the Carry bit is set. The
result is stored in the accumulator.
EXAMPLE:
Ri: Register R0 or R1
A: accumulator
Description: Instruction performs subtract operation: A-Rx including the Carry bit as well which
acts as borrow. If the higher bit is subtracted from the lower bit then the Carry bit is set. As it is
indirect addressing, register Rx address is located in the Ri register (R0 or R1) . The result of the
operation is stored in the accumulator.
EXAMPLE:
Register Address MIN=F4
Before execution: A=C9h, R1=F4h, MIN=04, C=0
After execution: A=C5h, C=0
Description: Instruction causes the accumulator and Rn registers to exchange data. The content
of the accumulator is set in the register Rn. At the same time, the content of the Rn register is set
in the accumulator.
EXAMPLE:
A: accumulator
Description: A word “nibble” designates a group of 4 adjacent bits within one register (bit0-bit3
and bit4-bit7).This instruction interchanges the high and low nibbles of the accumulator.
Syntax: SWAP A
Byte: 1 (Instruction Code)
STATUS register flags: No flags are affected.
EXAMPLE:
Ri: Register R0 or R1
A: accumulator
Description: Instruction sets the contents of accumulator into register Rx. At the same time, the
content of register Rx is set into the accumulator. As it is indirect addressing, register Rx address
is located in the register Ri (R0 or R1).
EXAMPLE:
Register Address SUM=E3
Before execution: R0=E3, SUM=29h, A=98h
After execution: A=29h, SUM=98h
XCH A,Rx - Exchange the content of registers Rx with the content of accumulator
Description: Instruction sets the contents of the accumulator into the register Rx. At the same
time, the content of the Rx register is set into the accumulator. As it is direct addressing, the
register Rx can be some of SFRs or general-purpose register with address 0-7Fh (0-127 dec.).
EXAMPLE:
EXAMPLE:
XCHD A,@Ri - Exchange the content of low nibbles accumulator with indirectly addressed
register Rx
Ri: Register R0 or R1
A: accumulator
Description: This instruction interchanges the low nibbles (bits 0-3) of the accumulator with the
low nibbles of indirectly addressed register Rx. High nibbles of the accumulator and Rx register
are not affected. This instruction is mainly used in operating with BCD values. As it is indirect
addressing, the regiter Rx address is stored in the register Ri (R0 or R1).
EXAMPLE:
Register Address SUM=E3
Before execution: R0=E3 SUM=29h A=A8h,
After execution: A=A9h, SUM=28h
XRL A,@Ri - Exclusive-OR operation between accumulator and indirectly addressed register
Ri: Register R0 or R1
A: accumulator
EXAMPLE:
Register Address TEMP=FAh, R1=FAh
Before execution: TEMP= C2h (11000010 Bin.)
A= 54h (01010100 Bin.)
After execution: A= 96h (10010110 Bin.)
EXAMPLE:
XRL Rx,A - Exclusive-OR operation between directly addressed register Rx and accumulator
Rx: Arbitrary register with address 0 - 255 (0 - FFh)
A: accumulator
EXAMPLE:
Description: Instruction performs exclusive-OR operation between the accumulator and number
X. The result of this logical operation is stored in the accumulator.
EXAMPLE:
Before execution: A= C2h (11000010 Bin.)
X= 11h (00010001 Bin.)
After execution: A= D3h (11010011 Bin.)
XRL Rx,# - Exclusive-OR operation between directly addressed register Rx and number X
Description: Instruction performs exclusive-OR operation between the Rx Register and number
X. As it is direct addressing, the Rx register can be some of SFRs or general-purpose register
with address 0-7Fh (0-127 dec.). The result of this logical operation is stored in the Rx register.
EXAMPLE:
Introduction
Today, after more than 20 years of continuous improvement, the 8051 microcontroller is being
manufactured across the world by many companies and under different trademarks. Of course,
the latest models are by far more advanced than the original one. Many of these models are
labeled as “8051 compatible”, “8051 compliant”or “8051 family” in order to emphasize their
“noble heritage”. The tags should imply that microcontrollers have similar architecture and are
programmed in a similar way, using the same instruction set. In practice, if you know how to
handle one of them, you will be able to handle any other belonging to 8051 family, which
encompasses several hundreds of different models!
This book covers one model named AT89S8253, manufactured by Atmel. Why this particular
one? Because it is widespred, cheap and uses Flash memory for program storage. This last
feature makes it ideal for experimentation due to the fact that program can be loaded and erased
a number of times. Besides, thanks to the built-in SPI System (Serial Programing Interface),
program can be loaded to the microcontroller even if the chip has already been embedded in the
final device.
Port 0 (P0.0-P0.7) If configured as output, each of these pins can be connected up to 8 TTL
inputs. If configured as input, the pins can be used as high-impedance inputs as their potential is
undefined relative to the ground, i.e. these inputs are floating. If additional (external) memory is
used, these pins are used for alternate transfer of data and addresses (A0-A7) for accessing this
additional memory chip. Signal on ALE pin determines what and when will be transferred on the
port.
Port 1 (P1.0-P1.7) If configured as output, each of these pins can be connected up to 4 TTL
inputs. When configured as input, these pins act as standard TTL inputs, that is, each of them is
internally connected to the positive supply voltage via relatively high impedance resistor. The
voltage on these inputs is 5V. Also, this Port 1 pins have alternate functions as shown in the table
below :
Port 2 (P2.0-P2.7) If configured as input or output, this port is identical to Port 1. If external
memory is used, Port 2 stores the higer address byte (A8-A15) for addressing additional memory
chip.
Port 3 (P3.0-P3.7) Similar to P1, Port 3 pins can be used as universal input or output, but also
have additional functions which will be explained later in the chapter.
ALE/PROG In normal operation, this pin emits a pulse sequence with a frequency equal to 1/6
of the main oscillator frequency. If additional memory is used, signal from this pin controls the
additional register for temporary storage of the lower address byte (A0-A7). During writing
program to the microcontroller, this pin also serves as a control input.
PSEN This pin signal is used for reading from external program memory (ROM).
EA/VPP When this pin is connected to the ground, the microcontroller takes program
instructions from external program memory. In case that internal program memory is used
(common case), this pin should be connected to the positive supply voltage (VCC). During
loading program to internal Flash mamory, this pin is supplied with +12V.
XTAL 1 This is internal oscillator input. It is used for synchronizing the microcontroller with
another circuit or when the external oscillator which generates clock pulses is for some reason
used.
XTAL 2 This pin is connected to internal oscillator output. In case that external oscillator is
used, this pin is out of use.
Program memory with a capacity of 12Kb is designed in FLASH technology, which enables a
great number of writing to/erasing up programs. It is programmed via embedded SPI module
(Serial Peripheral Interface). Although, it is possible to add external ROM memory chip, 12Kb is
more than enough.
This memory consists of 3 blocks with 128 registers each, and structure that falls into the 8051
Standard:
EEPROM is a special type of memory, having features of both RAM and ROM. The data are
being written to and erased during operation, but saved after the power is turned off. This
microcontroller has total of 2K of EEPROM (2048 locations).
Memory Extension
Taking into account that AT89S8253 microcontroller is based on the 8051 core, all mentioned
before for this model’s ROM and RAM memory extension remains in force. Meaning that both
memories can be added as external chips with the capacity up to 64Kb. Addressing is also the
same as in the 8051 Standard.
Types of addressing
Similar to all the microcontrollers compatible with the 8051, there are two ways of addressing:
Direct (for example: MOV A,30h)
Indirect (for example: MOV A,@R0)
The AT89S8253 microcontroller has total of 40 Special Function Registers. For the sake of the
compatibility with eather 8051 models, the basic group of registers (22 of them ) kept their
functions and addresses, while the rest were added to manage new functions of the
microcontroller.
As shown in the table above, each of these registers has its name and specific address in RAM.
Unoccupied locations are intended for future expansions and new models of the microcontroller
and shouldn’t be used. This chapter covers “general” SFRs’ function.
Specialized registers as the ones controlling timers or SPI will be described in the following
chapters.
ACC (Accumulator)
Accumulator is designated as ACC or A and belongs to the basic register group of the 8051 core.
There are no changes on bits of this register.
B register
B register also belongs to the basic register group of the 8051 core and there are no changes on
its bits. Instructions of multiplication and division (MUL and DIV instructions) can be applied
only to operands located in registers A and B.
PSW register belongs to the basic register group of the 8051 core. There are no changes on bits
of this register.
SP Register belongs to the basic register group of the 8051 core. There are no changes on bits of
this register.
Every bit of these registers corresponds to one of the ports pins having the same name. These
registers are therefore used for comminicating to peripheral environment by copying data from
registers to corresponding pins and vice versa. The registers belongs to the basic register group
of the 8051 core and there are no changes on their bits.
They belong to the basic register group of the 8051 core. There are no changes on their bits.
DISALE
o 0 - Pulse sequence with the frequency equal to 1/6 of the quartz oscillator frequency
appears on ALE.
o 1 - Pin ALE is active only during execution of MOVX or MOVC instructions.
Intel_Pwd_Exit
o 0 - When the microcontroller is in Power Down mode, the program proceeds with
execution after the falling edge signal appears (1-0).
o 1 - When the microcontroller is in Power Down mode, the program proceeds with
execution after the raising edge signal appears (0-1).
0 - The oscillator frequency (at XTAL1 pin) is divided by 2 before it is used as clock (machine
cycle lasts for 6 such periods).
1 - The oscillator signal is directly used as clock generator. In this way, for the same
microcontroller’s operating rate, a quartz crystal for two times lower frequency may be used
(for example 6MHz instead of 12MHz).
Data Pointers
Data Pointers are not true registers because they don’t physically exist. They consist of two
separate registers: DPH (Data Pointer High) and DPL (Data Pointer Low). Data Pointer’s 16 bits
are used for addressing external memory and internal EEPROM memory. DPS bit located in the
EECON register is in command which registers are to be used as data pointers:
DPS=0 -> Data pointer consists of DP0L and DP0H registers and is designated as DPTR0.
DPS=1 -> Data pointer consists of registers DP1L and DP1H and is designated as DPTR1.
2 Kb of on-chip EEPROM memory enable this microcontroller to be used in devices which have
to permanently store runtime data. All data stored in this memory will be saved even after the
power supply is off and the producer warrants at least 100 000 writing cycles. It is easy for use
since there are only a few control bits enabling it.
EEPROM write and read is controlled by EECON special function register. Since the process of
programming of EEPROM is relatively slow (writing to one register takes approximately 4mS),
a small hardware trick is done in order to enhance it. When bit EELD in EECON is set, the data
is not directly written to EEPROM registers but loaded in a small buffer (temporary memory)
with the capacity of 32 bytes. When this bit is cleared, the first data following it will be normally
written ( takes 4 mS). Also, all registers currently loaded in the buffer will be written
simultaneously. In this way, all 32 bytes require only 4mS to be written instead of 128mS
required in single byte writing.
EEPROM memory is treated as external memory and that’s why a special instruction for
handling additional memory chip (MOVX) is used. The EEMEN bit in the EECON register
controlls whether the data will be written/read from an true additional chip or on-chip EEPROM
memory.
EECON register
This bit can be read only. When the power supply level is too low for programming of
EEPROM, hardware automatically clears the bit, which means that programming can not be
executed or that ongoing programming will be aborted.
RDY/BSY
DPS
0 - Address for programming or reading from EEPROM is stored in the DP0H and DP0L registers.
1 - Address for programming or reading from EEPROM is stored in the DP1H and DP1L registers.
EEMEN
EEMWE
When set, EEMWE bit enables writing data to EEPROM. The MOVX instruction is used for
data writing. After EEPROM write is completed, the bit needs to be cleared from within the
program.
EELD
When set, EELD bit enables writing up to 32 bytes simultaneously. When bit is set, the MOVX
instruction will not initiate programming of EEPROM, it will just load data to the data buffer of
EEPROM memory. Before writing the last data, the bit is cleared and upon the last MOVX, the
entire buffer is automatically programmed to EEPROM for 4mS.
4.5 Watchdog Timer (WDT)
Watch-dog timer uses pulses from the quartz oscillator. After Reset and during Power Down
Mode, this timer is disabled and has no effect on the program execution. When enabled, a well
known battle against the time starts and timer is always “loose”. If program works properly. In
this case, the program will always manage reset watchdog timer on time. Otherwise, if watch-
dog timer manages to count a full cycle, it indicates that the program doesn’t work properly for
some reason. Then WDT comes into force and resets the microcontroller. Obviously, the point is
to set instruction in the main program loop which will unceasingly reset the watch-dog timer. In
practice, several bits of WDTCON register control this simple and efficient mechanism.
Three bits (PS2, PS1 and PS0) which are in control of prescaler, determine the most important
feature of Watch-dog timer- so called nominal time, i.e. time needed to count a full cycle.
The values in the table are valid in case that quartz crystal with frequency of 12MHz is used.
Prescaler Bits
Nominal Time
PS2 PS1 PS0
0 0 0 16ms
0 0 1 32ms
0 1 0 64ms
0 1 1 128ms
1 0 0 256ms
1 0 1 512ms
1 1 0 1024ms
1 1 1 2048ms
PS2,PS1,PS0
These bits are in control of prescaler and define so called nominal time of the Watchdog timer. If
the program doesn’t clear WSWRST bit during that time, this timer will reset the
microcontroller. (When all three bits are cleared to 0, the watch-dog timer has a nominal period
of 16K machine cycles. When all three bits are set to 1, the nominal period is 2048K machine
cycles).
WDIDLE
DISRTO
This bit enables/disables reset of external electronic circuits (out of the microcontroller)
connected to the RST pin:
0 - Watch-dog controls state of the reset pin. This means that, at the moment of reset, this pin is
driven high and acts for a short time as output. In that way, the micro controller as well as all
other circuits connected to the RST pin are reset.
1 - Reset which generates Watch-dog doesn’t affect state of the reset pin. Watch-dog resets
only the microcontroller while the reset pin continues acting as input.
HWDT
This bit selects hardware or software mode for the Watch-dog Timer:
WSWRST
When set, this bit resets watch-dog timer in software mode (bit HWDT=0). In order to enable the
microcontroller to work normally, this bit must be regularly cleared from within the program.
After being set by software, this bit is cleared by hardware during the next machine cycle.
If watch-dog is in hardware mode, this bit has no effect, and if set by software, it will not be
cleared by hardware.
WDTEN
This bit enables/disables watch-dog timer in software mode (bit HWDT=0):
0 - Watch-dog halts
1 - Watch-dog starts counting
When watch-dog is in hardware mode (bit HWDT=1), this bit is read-only and reflects the status
of the Watch-dog timer (whether it is turned on or off).
Bit WDTEN doesn’t reset watch-dog timer, it only enables/disables it. This means that the status of the
counter is “frozen” while WDTEN=0.
4.6 Interrupts
The AT89S8253 has a total of six interrupt sources, meaning that it can recognize up to 6
different events that can interrupt regular program execution. Each of these interrupts can be
individually enabled or disabled by setting bits of the IE register while the whole interrupt
system can be disabled by clearing the EA bit in the same register.
This microcontroller has embedded Timer T2 and SPI (they are not part of the “8051 Standard”).
Since both of them can interrupt program execution, it was necessary to make minimal changes
in registers that control interrupt system. A new interrupt vector (address 2B) is added, i.e.
address in program memory from where the program continues its execution in case the Timer
T2 causes interrupt. All these changes are only “added” to the positions of previously unused
bits. This means that all programs already written for some of the former models of the
microcontrollers can , with no changes, be executed in this one too. It is one of the main reason
for popularity of all microcontrollers based on “noble gene” of the 8051.
IE register (Interrupt Enable)
EX1 Bit enables or disables external interrupt through the pin INT0:
0 - Changing of logical state on the pin INT0 can not cause interrupt
1 - Enables external interrupt at the moment of changing state on the pin INT0
EX0 Bit enables or disables external interrupt through the pin INT1:
0 - Changing of logical state on the pin INT1 can not cause interrupt
1 - Enables external interrupt at the moment of changing state on the pin INT1
Interrupt Priorities
If multiple interrupts are enabled, it is possible to have interrupt requests during execution of
another interrupt routine. In such situations, the microcontroller needs to resolve whether to
proceed with the current interrupt routine or to meet a new interrupt request, which is based on
priority levels. The former models of the microcontrollers differentiate between two priority
levels defined in the IP register.
The AT89S8253 has additional SFR register IPH which assigns 1 of 4 priorities to each interrupt
(excluding reset). The new list of priorities is as follows:
1. Reset. If there is a request for reset, all processes are stopped and the microcontroller behaves
as if the power has just been turned on.
2. The highest priority interrupt (3). It can be stopped only by reset.
3. Lower priority interrupt (2, 1 or 0). It can be stopped by any interrupt with higher priority level.
It is usually defined at the beginning of the program which one of these existing inter rupt
sources have higher and which one has lower priority level. According to this, the following
occurs:
If two interrupt requests, at different priority levels, arrive at the same time then the higher
priority interrupt is always serviced first.
If the both interrupt requests, at the same priority level, occur one after another , that one who
came later has to wait until routine being in progress ends.
If two interrupts of equal priority requests arrive at the same time then the interrupt to be
serviced is selected according to the following priority list :
0 - Priority 0
1 - Priority 1
0 - Priority 0
1 - Priority 1
0 - Priority 0
1 - Priority 1
0 - Priority 0
1 - Priority 1
0 - Priority 0
1 - Priority 1
Bits of this register can be combined with the appropriate bits of the IP register. The new priority
list with 4 levels (5 including reset ) is based on it.
0 0 Priority 0 (lowest)
0 1 Priority 1 (low)
1 0 Priority 2 (high)
1 1 Priority 3 (highest)
Handling interrupt
Upon receiving an interrupt requests, the microcontroller recognizes the source and following
scenario takes place:
IE0 3h
TF0 Bh
IE1 13h
TF1 1Bh
These addresses should hold the appropriate subroutines for handling interrupt. Instead , there
are usually instructions pointing to the locations where the appropriate subroutines reside (jump
instructions).
4. When interrupt routine is executed, address of the next instruction to be executed is poped
from the stack to the program counter and the program proceeds from where it left off.
The AT89S8253 has three timers/counters marked as T0, T1 and T2. Both timers T0 and T1
completely fall under the 8051 Standard. There are no changes in their operating.
Timer T2
Timer2 is the third 16-bit timer/counter installed only in newer models of 8051 family. Unlike
timers T0 and T1, this timer comprises total of 4 registers. The first two, TH2 and TL2, are
connected serially in order to form a bigger one, 16-bit counting register. Other two registers,
RCAP2H and RCAP2L, are also connected serially and have the function to capture the contents
of the counting register, i.e. the register in which counting is being executed is temporarily
copied to them and vice versa .
The main adventage of this organization lies in the fact that all reading and swapping take place
concurrently, using one instruction and with no need for programming acrobatics. Besides, T2
like older T0 and T1, has several different operating modes, which will be described later in this
chapter.
T2CON (Timer/Counter 2 Control Register)
TF2 - This bit is automatically set on counter overflow. In order to register next overflow, this
bit needs to be cleared from within a program. If bits RCLK and TCLK are set, overflow has no
effect on TF2.
EXF2 - This bit is automatically set whenever pulse on pin T2EX causes transfer from counting
register to capture register or vice versa. If enabled, it gen erates interrupt, unless bit DCEN in
T2CON register is set. EXF2 has to be cleared from within a program.
RCLK - This bit defines which timer determines receive rate of serial connection:
1 - Start Timer T2
0 - Stop Timer T2
1 - 16-bit register (T2H and T2L) counts pulses on pin C/T2 (counter)
0 - 16-bit register (T2H and T2L) counts pulses from oscillator (timer)
1 - If enabled, (bit EXEN=1) pulse on pin T2EX will cause transfer from counter to capture
register.
0 - Under same condition, signal on pin T2EX will cause transfer in the opposite direction – from
capture to counter register.
If bit CP/RL2 of register T2CON is set, timer T2 will operate according to the schematic
presented below. This is the so called Capture mode in which value of the counter (comprises
registers RCAP2H and RCAP2L) can be “captured” and copied to the capture register. The
transfer has no effect on the counting process. How does the timer like this operate?
1. 16-bit register (TH2+TL2) holds the number from which the counting starts.
2. If set, bit TR2 of register TCON starts the timer. Each incoming pulse increments the value by 1.
When both registers are full (decimal value of 65536), the first next pulse causes overflow, then
reset occurs, and counting starts from zero.
Settings:
Timer T2 in Auto-reload mode
In order to set the timer T2 to Auto-reload mode, the bit CP/RL2 needs to be cleared. Then, the
Timer will be able to count up or down from the specified value, depending on the bit DCEN in
register T2MOD:
DCEN - When set, it enables counting in either direction- "up" and "down".
As it is presented in the schematic above, unlike Capture mode, the value of the capture register
(RCAP2H, RCAP2L) is in this case copied to the counter (TH2, TL2) upon overflow.
If counting down, overflow occurs when values in the counting and capture registers match. At
that moment, bit TF2 and all bits of registers T2H and T2L are set while the counting goes on
“from the top” : 65535, 65534,65533...
In eather case, bit EXF2 is assigned a new role. Namely, upon overflow, this bit only inverts the
signal and can not be used for generating interrupt anymore. Instead, this bit serves as
supplementary bit (17th bit) of the counting register, making the counter virtually 17-bit register.
If bits RCLK or TCLK of the register TCON are set, timer T2 turnes into clock generator (so
called Baud Rate generator) which determines the transfer rate of serial communication. This
mode is very similar to Auto-Reload mode with the rate of serial connection calculated according
to the following formula:
Naturally, there are several specific details that should be taken into account:
1. Previous equation works only if the internal oscillator is used for counting ( in this mode, clock is
divided by 2, instead of 12)
2. Overflow has no effect on bit TF2 and does not generate interrupt.
3. Whether the bit EXEN2 is set or not, logic state on T2EX has no effect on the counter. It means
that pin T2EX can be used as an external interrupt source in this mode.
4. When working in this mode, timer should be turned off (TR2 = 0) ahead of writing or reading the
contents of registers TH2 and TL2. Otherwise, an error in serial communication may occur.
In previous examples, pin P1.0 (marked as T2 in figures), serves as an alternative clock generator
for this timer -i.e. it acts as input. It can be also used as output for generating sequence of pulses.
Using the 16MHz quartz crystal, frequency of generated pulses ranges from 61Hz to 4MHz with
pulse-to-pause ratio of 50%.
To configure the pin as output, bit C/T2 (in register T2CON) needs to be cleared, and bit T2OE
(in register T2MOD) needs to be set. After that, bit TR2 starts the timer and the pin generates
rectangular waves with frequency calculated according to the formula:
Universal Asynchronous Receiver Transmitter UART preserved all the features of standard 8051
microcontrollers. It means that it can operate in 1 of 4 different modes, which is determined by
bits SM0 and SM1 in register SCON.
Multiprocessor Communication
If using multiprocessor communication (bit SM2 in the SCON register is set), it is possible to
automatically recognize microcontroller’s addresses. It enables easier program writing because
the mutually connected microcontrollers don’t need to examine every serial address. How does it
work?
Two new special Function Registers, SADDR and SADEN, enable it. Microcontroller’s address
(an arbitrary number) is written to SADDR register, while so called address mask is written to
register SADEN. The address mask is a binary number used to define which bits in the SADDR
are to be used and which bits are to be ignored.
Since the bit SM2 is set, the microcontroller will recognize serial received 9-bit data as an
address. Internal electronics immediately performs operation “logical AND” on these two
registers and compares the result with received address. In that way, the processor recognizes
whether upcoming data refer to it or not. Since some of the bits in address can be ignored (all
corresponding bits with 0 in SADEN register), the data received via serial communication can be
transferred to one, some or all microcontrollers which are mutually connected.
Microcontroller A is the master and communicate with devices “B” and “C”.
If transmit address is 1100 0010, the data will be exchanged with slave device B.
If transmit address is 1100 0001 the data will be exchanged with slave device C.
If transmit address is 1100 0000 the data will be exchanged with both slave devices.
In addition to UART system, the AT89S8253 has also another system for serial communication
which doesn’t fall into the 8051 Standard. It is SPI system which provides a high-speed
synchronous data transfer between the microcontroller and one or more peripheral devices or
between multiple microcontrollers. In such connection, one microcontroller is always considered
as the main one- master device. It defines rate, transfer direction (whether the data are
transferred or received) and data format. The other is slave device which is in subordinated
position, meaning that it cannot start data transfer and has to adjust to conditions imposed by the
master device.
The data are transferred via full duplex connection using 3 conductors connected to pins MISO
(P1.6), MOSI (P1.5) and SCK (P1.7). The forth pin-control pin SS- is not in use on the master
device and may be used as general-purpose input/output while on the slave device it must have
voltage level 0. When pin SS on the slave device is set, its SPI system is deactivated and the
MOSI pin can be used as a general-purpose input.
As it is shown in the schematic, pins MISO and MOSI perform differently on the master and
slave device (as inputs or outputs), which is determined by the MSTR bit in register SPCR.
Like many other circuits inside the microcontroller, SPI system can also operate in several
modes.
After writting data to the SPI data register SPDR, it is automatically transferred to 8- bit shift
register. SPI clock generator gets start and data in serial form appears on the pin MOSI. An
initial delay may occur for synchronization with the main oscillator.
After shifting one byte, the SPI clock generator stops, bit SPIF(flag) is set, received byte is
transferred to register SPDR and if enabled, an interrupt is generated.
Any attempt to write byte to register SPDR while a transmission is in progress, will set the
WCOL bit, which indicates that error has occured. However, the transmission will be completed
normally, meaning that error concerns new byte which will be ignored (byte will not be
transferred).
Enhanced mode is similar to normal mode except that during transmission data goes through one
more register. It doesn’t have any sense at first though, but connection is really enhanced in that
way! Look at the figure below...
After writting data to the SPI data register SPDR, it is transferred to capture register (buffer),
which automatically set bit WCOL signifying that the buffer is full and any further writes will
cause overflow. Control electronics (hardware) cleares this bit upon the data from buffer is
transferred to the shift register and its transmission in serial format begins. If this is the first byte
in series, the data is immediately transferred to the shift register (still empty) and bit WCOL is
immediately cleared (buffer is empty).
While this byte transmitting, the next byte may be written to register SPDR (it will be
immediately copied to buffer). In order to know that sending data is in progress, it is sufficient to
check if the bit LDEN (Load Enable) is set in register SPSR. When this bit is set and bit WCOL
is cleared means that data transfer is in progress and that buffer is free so the next byte can be
written to register SPDR.
How to select the right mode? If some individual byte is sent occasionally then there is no need
to complicate- it is sufficient to set up the normal mode. If it is needed to send a great amount of
data, it is better to use enhanced mode which offers obvious adventages: clock generator is not
turned off as far as buffer is regularly kept full and as far as processor “see” set bit WCOL. In
this mode, there is no wasting time for the sake of synchronization and data is easily transferred
in format of long composition of bytes- as quick as lighting and with no holdups.
This is the register for storing data to be transferred via SPI (in serial format). It is also used for
storing received data.
SPSR (SPI Status Register)
SPIF Interrupt flag. Upon data transfer, this bit is automatically set and an interrupt is generated
if bits SPIE=1 and ES=1. The SPIF bit is cleared by reading SPSR followed by reading/writing
SPDR register.
WCOL In normal mode (ENH=0), the bit is set if SPDR register is written during data transfer. It
means that writing is premature and has no effect (It is called Write Collision). This bit is
cleared in the same manner as the bit SPIF.
In enhanced mode (ENH=1), bit is set when buffer is full. It signifies that a new data “is waiting”
for transmission to the shift register.
In enhanced mode, a new data can be written to buffer when this bit is set (if at the same time the
bit WCOL=0).
DISSO When set, this bit causes the pin MISO to be floating, which make it possible that more
than one slave microcontrollers can share the same interface with a single master. Normally,
only the first byte in sequence could be the slave address, and all microcontrollers receive it.
Afterwards, only one selected microcontroller should clear its DISSO bit.
ENH
0 SPI system is in normal mode (with no buffer)
1 SPI system is in enhanced mode
SPIE When this bit is set, SPI system can generate interrupt
SPE This bit “turns on” SPI system. When this bit is set, pins SS, MOSI, MISO and SCK are
connected to microcontroller’s pins P1.4, P1.5, P1.6 and P1.7.
CPOL Bit controls state on the pin SCK when the SPI system is on wait :
CPHA This bit along with the CPOL bit controls relation between clock and data in serial format
(see table below).
SPR1,SPR0 When SPI system operates as master, these two bits determine boud rate, i.e. the
frequency of clock signal of master device. When operates as slave , bits have no effect and SPI
system is adjusted to the rate imposed by the master device.
0 0 Fosc/4
0 1 Fosc/16
1 0 Fosc/64
1 1 Fosc/128
Similar to all models belonging to the 8051 series, this microcontroller can operate in 1 of 3
modes: normal (consumption ca. 25 mA), Idle (consumption ca. 6.5 mA) and Power Down
(consumption ca. 40 uA). Mode is selected by bits in register PCON (Power Control) with
minimal supplements relative to the basic model:
PCON register
SMOD1 When set, this bit makes boud rate is two times faster.
SMOD0 Bit determines the purpose of the seventh bit in SCON register:
POF Bit is automatically set when, after turning on, the voltage level reaches maximum (must be
higher than 3V). It is used for finding out/detecting causes for reset (turning on or restart after
switching from Power Down mode).
PD When set, this bit sets up the microcontroller in Power Down mode
IDL When set, this bit sets up the microcontroller in Idle mode
If something unexpected happens, during the operation of the microcontrollers, what most
bothers is the fact that it’s never up to the microcontroller. Although it’s not always obvious, the
microcontroller will always obediently and consistently follow program instructions. For that
reason, in order to avoid misunderstanding, special attention should be payed to several “critical
points” when writing program. The first of them is RAM memory.
Even it is designed to meet needs of the majority of users, even it has all that is needed, a
memory space intended for RAM is still only one single totality. It means that there are no
phisically separated registers R0-R7, general purpose registers, stack etc. Instead, they all are
differently designated parts of the same “memory shelf” (look at the figure)
If this “detail”, with a bit of negligence, is overlooked, there is a danger that program (or device)
suddenly starts performs totally unpredictable. In order to prevent from such situations, attention
should be payed to the following:
If only registers R0-R7 are in use, it is not possible that something unpredictable happens and
memory locations at addresses from 08h are available for use. If registers from some other bank
are in use (other registers with the same designations), be careful when using locations whose
addresses are less than 20h because the contents of “R” registers can be erased.
If bit-variables are not used in the program, RAM locations at addresses 20h-2Fh are available
for use. If there are such variables in the program, this space should be carefully used in order to
avoid their accidental changes.
By default (if nothing has been changed), the data pushed on stack use RAM locations starting
from address 08h. If the banks of registers 1, 2 or 3 are in use, their contents will be almost for
sure unintentionally erased. For that reason, at the beginning ot the program, it is good to set
value of Stack Pointer to be greater than 20h (more better-greater than 2Fh).
SFRs are in command to control and run microcontroller’s operation. Each of them has its
specific purpose and so it should be. It means that they cannot be used as general purpose
registers even in case that some of addesses in SFRs is not acctually in use.
In instruction set recognized by the microcontroller, there are such instructions which can be
used for manipulating individual bits in the scope of register. Beside registers at addresses 20h -
7Fh, such direct access to individual bits is possible in some SFRs (not in all of them). Such
SFRs are recognizable by their addresses divisible by 8.
If memory expanding is used (external RAM or ROM), complete ports P0 and P2 become
unavailable regardless of how many pins are actually in use for communication with additional
memory.
Register DPTR is a 16-bit register comprised of registers DPH and DPL which are 8-bit each. In
practice, they should be treated like that. For example, if DPTR register should be pushed to the
Stack, DPL should be pushed first, then DPH.
When serial communication is used, it is register SCON which controls this process. Since the
Timer 1 is mostly used for boud rate generating than registers TCON and TMOD should be
configured too.
When some of interrupts is enabled, one should be careful because there is danger that program
starts executing in a strange way. What is all this about? When interrupt request arrives, the
microcontroller will execute ongoing instruction, push address of the first following location on
the stack (in order to know from where to continue) and jump to the address defined for interrupt
requested. When subroutine has been executed, processor will pop address from the stack and
will continue executing from where it left off. But...
The microcontroller “remembers” only return address. During subroutine execution, contents of
many registers can be changed. When program continues execution after returning from
subroutine, changed contents of registers will be treated as correct ones, if their previous values
haven’t been saved, which can cause total chaos. The worst thing is that problem like this can be
manifested anytime: at the moment or several days of work later (depending on the moment
interrupt occurs). Obviously, the only solution is to memorize the state of all important registers
in the beginning of interrupt routine and to turn these true values back to the program before
returning from subroutine. The following registers are concerned:
PSW
DPTR (DPH, DPL)
ACC
B
Registers R0 - R7
Procedure of memorizing the state of registers is commonly performed by placing them on the Stack (by
PUSH instruction). But instruction such as “PUSH R0” can not be applied because the processor “doesn’t
know” to which register it refers (there are 4 banks with registers R0-R7). So, for memorizing values of R
register, instead of their names, their addresses should be used ( by PUSH 00h instruction).
When some of instructions for indirect addressing are in use, one should pay attention to not use
them for accessing SFRs because processor ignores their addresses and accesses free RAM
locations which have the same addresses as SFRs.
When UART system for serial connection is in use, bits RI and TI of register SCON generate the
same interrupt routine so one should first find out the cause of interrupt (byte is transferred,
received or both). One should pay attention that processor only sets these bits! If one forget to
clear these bits at the end of routine, the program gets stuck and repeats the same interrupt all the
time.
After reset 0 0 0 0 0 0 0 0
ACC
Bit name - - - - - - - -
Bit address E7 E6 E5 E4 E3 E2 E1 E0
After reset 0 0 0 0 0 0 0 0
B
Bit name - - - - - - - -
Bit address F7 F6 F5 F4 F3 F2 F1 F0
After reset X X 0 0 0 0 0 0
IP
Bit name - - PT2 PS PT1 PX1 PT0 PX0
Bit address BF BE BD BC BB BA B9 B8
IE
After reset 0 X 0 0 0 0 0 0
Bit address AF AE AD AC AB AA A9 A8
After reset 1 1 1 1 1 1 1 1
P0
Bit name - - - - - - - -
Bit address 87 86 85 84 83 82 81 80
After reset 1 1 1 1 1 1 1 1
P1
Bit name - - - - - - - -
Bit address 97 96 95 94 93 92 91 90
After reset 1 1 1 1 1 1 1 1
P2
Bit name - - - - - - - -
Bit address A7 A6 A5 A4 A3 A2 A1 A0
Bit address B7 B6 B5 B4 B3 B2 B1 B0
After reset 0 0 0 0 0 0 0 0
PSW
Bit name CY AC F0 RS1 RS0 OV - P
Bit address D7 D6 D5 D4 D3 D2 D1 D0
After reset 0 0 0 0 0 0 0 0
SCON
Bit name SM0 SM1 SM2 REN TB8 RB8 TI RI
Bit address 9F 9E 9D 9C 9B 9A 99 98
After reset 0 0 0 0 0 0 0 0
TCON
Bit name TF1 TR1 TF0 TR0 IF1 IT1 IF0 IT0
Bit address 8F 8E 8D 8C 8B 8A 89 88
Bit address CF CE CD CC CB CA C9 C8
Bit name - - - - - - - X2
Bit name - - - - - - - -
DP0L
After reset 0 0 0 0 0 0 0 0
Bit name - - - - - - - -
Bit name - - - - - - - -
Bit name - - - - - - - -
PCON
After reset 0 X X X 0 0 0 0
Bit name - - - - - - - -
Bit name - - - - - - - -
Bit name - - - - - - - -
SP After reset 0 0 0 0 0 1 1 1
Bit name - - - - - - - -
Bit name SPIE SPE DORD MSTR CPOL CPHA SPR1 SPR0
Bit name - - - - - - - -
Bit name - - - - - - - -
Bit name - - - - - - - -
Timer 0 Low (Address: 8A)
Bit name - - - - - - - -
Bit name - - - - - - - -
Bit name - - - - - - - -
Bit name - - - - - - - -
TH1
After reset 0 0 0 0 0 0 0 0
Bit name - - - - - - - -
Bit name - - - - - - - -
Bit name GATE1 C/T1 T1M1 T1M0 GATE0 C/T0 T0M1 T0M0
Bit name PS2 PS1 PS0 WDIDLE DISRTO HWDT WSWRST WDTEN
WDTCON
After reset - - - - - - - -
Bit name - - - - - - - -
Input Low-voltage
VIL1 -0.5 V 0.2Vcc - 0.3V
on EA pin
Input High-voltage
VIH1 on pins XTAL1 and 0.7 Vcc Vcc + 0.5 V
RST
Output High-voltage
Ioh = -40mA, Ta =
when Pull-up
85°C
resistors are enabled 2.4 V
Ioh = -25mA, Ta =
VOH1 (Port P0 in External 0.75 Vcc
85°C
BUS mode, ports 0.9 Vcc
Ioh = -10mA, Ta =
P1,2,3, pins ALE and
85°C
PSEN)
Logical 0 input
Vin = 0.45V, Vcc =
IIL current (ports - 50 μA
5.5V, Ta = -40°C
P1,2,3)
Input leakage
IILI current (port P0, pin 0.45V < Vin < Vcc ± 10 μA
EA)
Reset pull-down
RRST 50 KΩ 150 KΩ
resistor
CIO I/O pin Capacitance f = 1Mhz, Ta = 25°C 10 pF
Normal mode: f =
12Mhz, Vcc = 5.5V
Power-supply Ta = -40°C 25 mA
current Idlle mode f = 6.5 mA
ICC 12Mhz, Vcc = 5.5V
Ta = -40°C
Vcc = 5.5V Ta = -
100 μA
Power-down mode 40°C
40 μA
Vcc = 4V Ta = -40°C
Introduction
The moment has come that hardware-oriented to the core make compromise if they want to stay
“in the game”. Namely, unlike other circuits which need to be connected to other components
and power supply in order to be of any use, the microcontrollers require program too. Luckily,
their evolution still did not progress so far, so all of them (for the time being) “understand” only
one machine language. It is a good news. The bad one is that even primitive, only
microcontrollers and some experts can understand this language of zeros and ones. In order to
bridge this gap between machine and humans, the first high-level programming language-
Assembler was created.
The main problem- to remember the codes which electronics recognizes as commandswas
solved, but a new one- equally complicated to both us and “them”(microcontrollers) arose. The
conflict was resolved at common pleasure by means of the program for PC called assembler (not
original at all) and a simple device called programmer.
Even simple, assembler is basically like any other language, which means that it has its words,
rules and syntax. Its basic elements are:
Labels
Orders
Directives
Comments
Syntax of Assembly language
When writing program in assembler it is necessary to observe specific rules in order to enable the
process of compiling into executable “HEX-code” run with no errors. These obligatory rules in
writing program are called syntax and there are only several of them:
Numbers
Decimal Numbers
If there are no particular indications, the assembler interpretes all numbers as decimal ones. All
ten digits are in use (0,1,2,3,4,5,6,7,8,9). Since at most 2 bytes are used for their memorizing to
the microcontroller, the greatest number that can be written in this system is 65535. If it has to be
emphasised that some number is in decimal format, that number is followed by the letter “D”.
For example 1234D.
Hexadecimal Numbers
This is a common way of writing numbers in programming. Instead of 10, there are 16 digits in
use (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F). In Assembler, the greatest number that can be
written in this system is FFFF ( corresponds to decimal number 65535). In order to distinguish
them from decimal numbers, there is the letter “h”(in upper-or lowercase) following hexadecimal
numbers. For example 54h.
Binary Numbers
Binary numbers are often used when the value of each individual bit in some register is
important, since each digit of binary number represents one bit. There are only two digits in use
(0 and 1). The greatest number in this numeric system recognizable by assembler as correct one
is 1111111111111111. In order to distinguish them from other numbers, there is the letter “b” (in
upper-or lowercase) following binary numbers. For example 01100101B.
Operators
Instead of writing symbols which have specific value, some assembler-used commands allow the
use of logical and mathematical expessions. For example:
IF (VERSION>1)
LCALL Table_2
USING VERSION+1
ENDIF
...
As it can be seen, the assembler is able to compute some values on its own and place them in a
programming code. In that case, it distinguishes between the following mathematical and logical
operations:
+ Addition 10+5 15
- Subtraction 25-17 8
* Multiplication 7*4 28
Division (with no
/ 7/4 1
remainder)
Negation (first
NOT NOT 1 1111111111111110B
complement of number)
Symbols
In assembly language, every register, constant, address or subroutine can be assigned a specific
symbol, which considerably facilitates writing program. Hence, for example, if input pin P0.3 is
connected to a pushbutton for manually interrupting of some process (pushbutton STOP), writing
program will be simpler if the bit P0.3 is assigned the same name: “pushbutton_STOP”. Of
course, like in any other language, there are specific rules as well:
While writing symbols, it is allowed to use all letters from alphabet (A-Z, a-z), dec imal numbers
(0-9) and two special characters ("?" and "_"). Assembler does not dif ferentiate between upper
case and lower case.
Serial_Port_Buffer
SERIAL_PORT_BUFFER
In order to be different from a constant (number), every symbol must start with a letter or one
of two special characters (? or _).
Symbol may consist of maximum 255 characters, but only first 32 of them are taken into
account. In the following example, the first two symbols will be interpreted as duplicate (error),
while the third and forth symbols will be accepted as different ones:
START_ADDRESS_OF_TABLE_AND_CONSTANTS_1
START_ADDRESS_OF_TABLE_AND_CONSTANTS_2
TABLE_OF_CONSTANTS_1_START_ADDRESS
TABLE_OF_CONSTANTC_2_START_ADDRESS
Some symbols cannot be used because they are already part of instructions or assembly
directives. Consequently, for example, a register or subroutine cannot be assigned name “A” or
“DPTR” because the registers having the same name exist already.
A AB ACALL ADD
CSEG DA DATA DB
DPTR DS DSEG DW
END EQ EQU GE
ISEG JB JBC JC
JZ LCALL LE LJMP
R0 R1 R2 R3
R4 R5 R6 R7
Labels are a special type of symbols used to denote address in subroutine and are recognizable
by being always written at the beginning of a program line. Without them it is not allowed to call
subroutine or execute some of jump or branch instructions. They are easy for use:
Symbol (label) with some easily recognizable name should be written at the beginning of a
program line from where subroutine starts or where jump should be executed.
In instruction which calls this subroutine or a jump, instead of address in form of 16-bit number,
it is sufficient to enter the name of label.
During program compiling into machine code, the assembler will automatically replace such
symbols with correct addresses.
Directives
Unlike instructions being translated into machine code and written to on-chip program memory,
directives are commands of assembler itself and have no effect on the operation of the
microcontroller. Some of them are obligatory part of every program while some of them are used
only to facilitate or enhance the operation.
Directives are written to the column reserved for instructions. There is the rule allowing only one
directive per program line.
EQU directive
MAXIMUM EQU 99
After this directive, every appearance of the label “MAXIMUM” in the program, the assembler
will interprete as number 99 (MAXIMUM = 99). It is only once possible to define symbols in
this way so the EQU directive is mostly used at the beginning of the program.
SET directive
Similar to the EQU directive, by means of the SET directive, a numeric value is replaced by a
symbol. Significant difference is that with this directive it can be done for unlimited number of
times:
SPEED SET 45
SPEED SET 46
SPEED SET 57
BIT directive
By means of this directive, bit address is replaced by a symbol (bit address must be in the range
of 0-255). For example:
TRANSMIT BIT PSW.7 ;Transmit bit (the seventh bit in PSW register)
;is assigned the name "TRANSMIT"
OUTPUT BIT 6 ;Bit at address 06 is assigned the name "OUTPUT"
RELAY BIT 81 ;Bit at address 81 (Port 0)is assigned the name ;"RELAY"
CODE directive
By means of this directive, an address in program memory is designated as a symbol. Since the
maximal capacity of program memory is 64K, the address must be in the range of 0-65535. For
example:
By means of this directive, an address within internal RAM is designated as a symbol (address
must be in the range of 0-255). In other words, any selected register may change its name or be
assigned a new one. For example:
By means of this directive, indirectly addressed register (its addrress is located in the specified
register) changes its name or is assigned a new one. For example:
This directive is used to name registers within external (additional) RAM memory. Address of
such defined ragister cannot be greater than 65535. For example:
This directive is used to define location in program memory where the program following
directive is to be placed. For example:
USING directive
This directive is used to define which register bank (registers R0-R7) will be used in the
following program.
This directive must be at the end of every program. Once it encounters this directive, the
assembler will stop interpreting program into machine code. For example:
...
END ;End of program
There are 5 such directives used for selecting one of five available memory segments in the
microcontroller :
DSEG ;Indicates that next segment refers to internal RAM (part accessed by
direct addressing).
ISEG ;Indicates that next segment refers to the “upper” part of internal RAM
(part accessed by
;indirect addressing using registers R0 and R1).
When assembler gets started, the segment CSEG is activated by default and remains active until
a new directive is specified. Each of these memory segments has its internal address counter
which is cleared every time the assembler is started. Its value can be changed by indicating value
after the mark AT (it may be a number, an arithmetical operation or a symbol). For example:
Dollar symbol "$" denotes current value of address counter in the segment which is currently
active. The following two examples illustrate how this can be used in practice:
Example 1:
Example 2:
Using previous two program lines, exact number of characters in the message “ALARM turn off
engine” which is defined at address labelled as “MESSAGE”, can be computed.
DS directive
This directive reserves space in memory expressed in bytes. It is used if the segment ISEG,
DSEG or XSEG is currently active. For example:
Example 1:
Example 2:
This directive reserves space within bit-addressable part of RAM (size is expressed in bits). It
can be used only if the BSEG segment is active. For example:
This directive is used for writing indicated value to program memory. If several values are
indicated one after another then they are separated by commas. If ASCII array should be
indicated it is enclosed with single quotation marks.This directive can be used only if the
segment CSEG is active. For example:
CSEG
DB 22,33,’Alarm’,44
When written before this directive, the label will point to the first value in the array ( in this
example number 22).
DW directive
This directive has the same purpose as DB directive, but it is followed by two-byte value (the
high byte is written first, the low byte afterwards).
These directives are used to create so called conditional blocks in a program. Each of these
blocks starts with directive IF and ends with directive ENDIF or ELSE. State or symbol (in
parentheses) following the directive IF represents a condition which determines the part of the
program to be compiled into machine code:
If the statement is correct or if symbol is equal to one, program will include all instructions up to
directive ELSE or ENDIF.
If the statement is not correct or if the symbol value is equal to zero, all upcoming instructions
are neglected (are not interpreted) and program continues with com mands following directives
ELSE or ENDIF.
Example 1:
IF (VERSION>3)
LCALL Table_2
LCALL Addition
ENDIF
...
If the program is of later date than version 3 (statement is correct), subroutines “Table 2” and
“Addition” will be executed. If the statement in parentheses is not correct (VERSION<3), two
instructions calling subroutines are neglected and are not compiled.
Example 2:
If the symbol value “Model” is equal to one, first two instructions after directive IF will be
compiled into machine code and program will afterwards continue with instructions following
directive ENDIF (all instructions between ELSE and ENDIF are neglected). Otherwise, if
Model=0, instructions between IF and ELSE are neglected and assembler compiles only
instructions following directive ELSE.
IF (Model)
MOV R0,#BUFFER
MOV A,@R0
ELSE
MOV R0,#EXT_BUFFER
MOVX A,@R0
ENDIF
...
Control directives
These directives are recognizable by having the dollar symbol $ as the first letter. These
commands are used to define which files are to be used by assembler during compiling. It is also
used to determine where executable file is to be stored as well as the final appearance of the
compiled program. Although, there are many directives belonging to this category, only few of
them is really important:
$INCLUDE directive
The name of this directive tells enough about its purpose. During compiling, it enables assembler
to use data stored in another file. For example:
$INCLUDE(TABLE.ASM)
$MOD8253 directive
$MOD8253 is the file where names and addresses of all SFRs of 8253 microcontrollers are
stored. By using this file and directive having the same name, assembler can execute program
compiling only on the base of the registers’ names. In case where those would not be used it is
necessary in introductory part of the program to define an accurate name and address for every
SFRs that will be used in the program
Chapter 6 : Examples
6.1 Basic connecting of the microcontroller
6.2 Additional components
6.3 Examples
Introduction
The purpose of this chapter is to inform you about basic issues on microcontrollers that one
should know in order to use them successfully in practice. That is why you will not find here
some ultra interesting program or device schematic with amazing solutions. Instead of that,
examples described in this chapter are more proof that program writing is neither privilege nor
talent issue but ability of simple putting puzzle pieces together using directives. Device
development mainly comes to the method “test-correct-repeat”. Of course, the more you are into
it, the issues become more complicated as the puzzle pieces are put together by both children and
first-class architects...
6.1 Basic connecting of the microcontroller
As seen on the above figure, in order to enable microcontroller to operate properly it is necessary
to provide :
Power supply
Reset signal
Clock signal
Obviously, all this is about very simple circuits, but it does not have to be always like that. If
device is used for handling expensive machines or for maintaining vital functions, everything
becomes more and more complicated! This kind of solution is quite enough for the time being...
Power supply
Although this circuit can operate with different power supply voltage, why to test “Marphy’s
low”?! Voltage of 5V is so common that it imposes itself. The circuit, shown on the figure, uses
cheap voltage stabilisator LM7805 and provides high-quality voltage level and guite enough
current to enable microcontroller and “peripheral electronics” to operate ( sufficient current in
this case amounts to 1A)!
Reset signal
In order to operate properly, the microcontroller must “see” logic 0 (0V) on reset pin RS (It
explains connection pin-resistor 10K-ground). Pushbutton which connects reset pin RS to power
supply VCC is not necessary but it is almost always built in because it enables microcontroller
safe return to normal operating conditions when the things go wrong. By activating this pin, 5V
is brought to it, the microcontroller is reset and program starts execution from the beginning.
Clock signal
Although the microcontroller has built in oscillator, it cannot operate without two external
condensators and quartz crystal which stabilize its frequency (microcontroller’s operating speed).
Regardless of the fact that microcontrollers are the product of modern technology, they are not so
useful without being connected to additional components. Simply, the appearance of voltage on
its pin means nothing if it does not perform certain operations (turn on/off, shift, display and
similar).
There is nothing simpler than this! This is the simplest way of controlling appearance of some
voltage on microcontroller’s input pin. There is also no need for additional explanation of how
these components operate.
Nevertheless, it is not so simple in practice... This is about something commonly unnoticeable
when using these components in everyday life. It is about contact bounce- a common problem
with m e c h a n i c a l switches. If contact switching does not happen so quickly, several
consecutive bounces can be noticed prior to maintain stable state. The reasons for this are:
vibrations, slight rough spots and dirt. Anyway, whole this process does not last long (a few
micro- or miliseconds), but long enough to be registered by the microcontroller. Concerning
pulse counter, error occurs in almost 100% of cases!
The simplest solution is to connect simple RC circuit which will “suppress” each quick voltage
change. Since the bouncing time is not defined, the values of elements are not strictly
determined. In the most cases, the values shown on figure are sufficient.
If complete safety is needed, radical measures should be taken! The circuit, shown on the figure
(RS flip-flop), changes logic state on its output with the first pulse triggered by contact bounce.
Even though this is more expensive solution (SPDT switch), the problem is definitely resolved!
Besides, since the condensator is not used, very short pulses can be also registered in this way.
In addition to these hardware solutions, a simple software solution is commonly applied too:
when a program tests the state of some input pin and finds changes, the check should be done
one more time after certain time delay. If the change is confirmed it means that switch (or
pushbutton) has changed its position. The advantages of such solution are obvious: it is free of
charge, effects of disturbances are eliminated too and it can be adjusted to the worst-quality
contacts. Disadvantage is the same as in case of using RC filter-pulses shorter than program
delay cannot be registered.
Optocouplers
Relays are elements connected to ouput pins of the microcontroller and used to turn on/off all
that being out of board which has sensitive components: motors, transformators, heaters, bulbs,
high-voltage components, antenna systems etc. There are various types of relays but all have the
same operating principle: when a current flows through the coil, it makes or brakes machanical
connection between one or more pairs of contacts. As it is case with optocouplers, there is no
galvanically connection (electrical contact) between input and output circuits. Relays usually
demand both higher voltage and current to start operating but there are also miniature versions
which can be activated with a low current directly obtained from the microcontroller’s pin.
Below figure presents one solution specific to the 8051 microcontrollers. In this very case,
darlington transistor is used to activate relays because of its high current gain. This is not in
accordance with “rules”, but it is necessary in case of logic one activation since the current is
then very low (pin acts as input)!
In order to be prevented from appearance of high voltage of self-induction caused by a sudden
stop of current flow through the coil, an inverted polarized diode is connected in parallel to the
coil. The purpose of this diode is to “cut off” the voltage peak.
Light-emitting diodes are elements for light signalization in electronics. They are manufactured
in different shapes, colors and sizes. For their low price, low consumption and simple use, they
have almost completely pushed aside other light sources- bulbs at first place. They perform
similar to common diodes with the difference that they emit light when current flows through
them.
It is important to know that each diode will be immediately destroyed unless its current is
limited. This means that a conductor must be connected in parallel to a diode. In order to
correctly determine value of this conductor, it is necessary to know diode’s voltage drop in
forward direction, which depends on what material a diode is made of and what colour it is.
Values typical for the most frequently used diodes are shown in table below: As seen, there are
three main types of LEDs. Standard ones get ful brightness at current of 20mA. Low Current
diodes get ful brightness at ten times lower current while Super Bright diodes produce more
intensive light than Standard ones.
Infrared - 30 50 1.4
Orange - 10 30 2.0
Yellow - 20 30 2.1
Blue - 20 30 4.5
White - 25 35 4.4
Since the 8051 microcontrollers can provide only low input current and since their pins are
configured as outputs when voltage level on them is equal to 0, direct connectining to LEDs is
carried out as it is shown on figure (Low current LED, cathode is connected to output pin).
LED displays
Basically, LED displays are nothing else but several LEDs moulded in the same plastic case.
Diodes are arranged so that different marks-commonly digits: 0, 1, 2,...9 are displayed by
activating them. There are many types of displays composed of several dozens of built in diodes
which can display different symbols.
The most commonly used are so called 7-segment displays. They are composed of 8 LEDs, 7
segments are arranged as a rectangle for symbol displaying and there is additional segment for
decimal point displaying. In order to simplify connecting, anodes and catodes of all diodes are
connected to the common pin so that there are common cathode displays and common anode
displays. Segments are marked with the latters Ato G as shown on the figure on the left. When
connecting, each diode is treated independently, which means that each must have its own
conductor for current limitation.
When connecting displays to the microcontroller, the greatest problem is a great deal of valuable
I/O pins which they “occupy”, especially if it is needed to display several-digit numbers.
Problem is more than obvious if for example it is needed to display two 6-digit numbers (a
simple calculation shows that 96 output pins are needed)!The solution on this problem is called
MULTIPLEXING. This is how optical illusion based on the same operating principle as
filmcamera occurs. The principle is that only one digit is active but by quick changing one gets
impression that all digits of a number are active at the same time.
Referring to the previous example it would mean that firstly one byte representing units is
applied on a microcontroller’s port and only transistor T1 is activated at the same time. After a
while, the transistor T1 is turned off, a byte representing tens is applied on a port and transistor
T2 is activated. This process is being cyclicly repeated at high speed for all digits and
corresponding transistors.
When displaying any digit, a defeating fact that microcontroller is nevertheless only a machine
made to understand only language of units and zeros is fully expressed. Namely, it “does not
know” what units, tens or hundreds are, nor it knows how ten digits we are used to look like.
Therefore, each number intended to be shown on display must be prepared in the following way:
In special subroutine, a several digit number must be first separated in units, tens etc.
Afterwards, each of these digits must be stored in specific byte. In order to make these digits
familiar to us, “masking” is carried out. Basically, it is a simple subroutine by which binary
format of each number is replaced by different combination of bits. For example, the digit 8
(0000 1000) is replaced by binary digit 0111 111 in order to activate all LEDs which represent
digit 8 on display. The only diode, inactive in this case is reserved for decimal point. If a
microcontroller’s port is connected to display in a way that bit 0 activates segment “a”, bit 1
activates segment “b”, bit 2 segment “c” etc., the table below shows “mask” for each digit.
dp a b c d e f g
0 1 0 0 0 0 0 0 1
1 1 0 0 1 1 1 1 1
2 1 0 0 1 0 0 1 0
3 1 0 0 0 0 1 1 0
4 1 1 0 0 1 1 0 0
5 1 0 1 0 0 1 0 0
6 1 0 1 0 0 0 0 0
7 1 0 0 0 1 1 1 1
8 1 0 0 0 0 0 0 0
9 1 0 0 0 0 1 0 0
These components are “specialized” for being used with the microcontrollers, which means that
they cannot be activated by standard IC circuits. They are used for writing different messages on
a miniature LCD.
Amodel described here is for its low price and great possibilities most frequently used in
practice. It is based on the HD44780 microcontroller (Hitachi) and can display messages in two
lines with 16 characters each . It displays all letters of alphabet, greek letters, punctuation marks,
mathematical symbols etc. In addition, it is possible to display symbols that user makes up on its
own. Automatic shifting message on display (shift left and right), appearance of the pointer,
backlight etc. are considered as useful characteristics.
Pins Functions
There are pins along one side of the small printed board used for connection to the
microcontroller. There are total of 14 pins marked with numbers (16 in case the background light
is built in). Their function is described in the table bellow:
Ground 1 Vss - 0V
8 D1 0/1 Bit 1
9 D2 0/1 Bit 2
10 D3 0/1 Bit 3
Data / commands
11 D4 0/1 Bit 4
12 D5 0/1 Bit 5
13 D6 0/1 Bit 6
LCD screen
LCD screen consists of two lines with 16 characters each. Each character consists of 5x8 or 5x11
dot matrix. This book covers 5x8 character display because it is commonly used.
Contrast on display depends on the power supply voltage and whether messages are displayed in
one or two lines. For that reason, variable voltage 0-Vdd is applied on pin marked as Vee.
Trimmer potentiometer is usually used for that purpose. Some versions of displays have built in
backlight (blue or green diodes). When used during operating, a resistor for current limitation
should be used (like with any LE diode).
If there are no characters on display or all of them are dimmed upon the display is on, the first thing that
should be done is to check the potentiometer for contrast regulation. Is it properly adjusted? Same
applies in case the operation mode is changed (writing in one or two lines).
LCD Memory
DDRAM Memory
DDRAM memory is used for storing characters that should be displayed. The size of this
memory is sufficient for storing 80 characters. One part of these locations is directly connected
to the characters on display.
All functions quite simply: it is sufficient to configure display so that addresses are automatically
incremented (shift right). Afterwards it sets starting value for the message that should be
displayed (for example 00 hex).
After that, all characters sent through lines D0-D7 will be displayed as a message we are used to-
from left to right. In this case, displaying starts from the first character in the first line on display
since the address is 00 hex. If more than 16 characters are sent, they all will be also memorized
but not visible. In order to display them, a shift command should be used. Virtually, everything
looks as if LCD display is a “window” which moves left-right over memory locations with
characters. In reality, that is how the affect of message “moving”on the screen is obtained (from
left to right or vice versa).
If cursor is on, it will appear at location which is currently addressed. In other words, characters
will appear at cursor’s position while the cursor is automatically moved to the next addressed
location.
Since this is a sort of RAM memory, data can be written to and read from it. Disadvantage is that
the contents will be lost forever upon the power is off.
CGROM Memory
A “map” with all characters that can be displayed are written by default. Each character has
corresponding location.
Addresses of CGROM memory locations match standard ASCII values of characters. It means
that if in a program being currently executed by the microcontroller is written “send letter P to
port”, the binary value 0101 0000 will appear on the port. This value is ASCII equivalent to the
letter P. When this binary number is sent to LCD, a symbol stored on 0101 0000 location in
CGROM will be displayed. In other words, the letter “P” will be displayed . This applies to all
alphabet letters (upper- and lowercase), but not to numbers!
If one carefully looks at the “map” with characters in this memory, it can be seen that addresses
of all digits are “shifted” by 48 in comparison to the values of these digits (address of the digit 0
is 48, of digit 1 is 49, of digit 2 is 50 etc.). For that reason and in order to display digits correctly,
each of them needs to be added a decimal number 48 prior to being sent to LCD.
Since the time the first computer was made, it recognizes numbers but not letters. It means that on
sending any character from keyboard to PC, from PC to printer or from microcontroller to other
computer, through connection line are actually sent binary numbers instead of characters . A table that
links all standard symbols and their number equivalents is called ASCII code.
CGRAM memory
Beside being able to display all standard characters, the LCD can display symbols that user
defines on its own. It enables displaying cyrilic fonts as well as many other symbols which fit to
the frame of 5x8 dots size. RAM memory (CGRAM) in size of 64 bytes enables the above.
The size of registers of this memory is a standard one (8 bits), but only 5 lower bits are in use.
Logic one (1) in every register represents a dimmed dot, while 8 locations considered jointly
represent one character. It is best illustrated on the figure below:
Symbols are usually defined at the beginnig of a program by simple writing zeros and units to
registers of CGRAM memory so that they form desirable shapes. In order to display them it is
sufficient to specify their address. Pay attention to the first coloumn in CGROM map of
characters- these are not addresses of RAM memory but symbols which are discussed here.In
this example, “display 0” means - display “č”, “display 1” means - display “ž” etc.
All data transferred to LCD through outputs D0-D7 will be interpreted as commands or as data,
which depends on logic state on pin RS:
RS = 0 - Bits D0 - D7 are commands which determine display mode. List of commands which
LCD “recognizes”are given in the table below:
Comparing to the microcontroller, LCD is an extremly slow component. Because of that It was
necessary to provide a signal which will indicate that display is ready to receive a new data or a
command following the previous one has been executed. That signal is called busy flag and can
be read from line D7. When the bit BF is cleared (BF=0), display is ready to receive.
LCD Connection
Depending on how many lines are used for connection to the microcontroller, there are 8-bit and
4-bit LCD modes. The appropriate mode is determined at the beginning of the process in a phase
called “initialization”. In the first case, the data are transferred through outputs D0-D7 as it has
been already explained. In case of 4-bit LED mode, for the sake of saving valuable I/O pins of
the microcontroller, there are only 4 higher bits (D4-D7) used for communication, while other
may be left unconnected. Consequently, each data is sent to LCD in two steps: four higher bits
are sent first (that normally would be sent through lines D4-D7), four lower bits are sent
afterwards. With the help of initialization, LCD will correctly connect and interprete each data
received. Besides, with regards to the fact that data are rarely read from LCD (data mainly are
transferred from microcontroller to LCD) one more I/O pin may be saved by simpleconnecting
R/W pin to the Ground. Such saving has its price. Even though message displaying will be
normally performed, it will not be possible to read from busy flag since it is not possible to read
from display.
Luckily, solution is simple. It is sufficient to give LCD enough time to perform its task upon
sending every character or command. Since execution of the slowest command is approximately
1.64mS, it will be quite enough to wait for approximately 2mS.
LCD Initialization
Once the power supply is turned on, LCD is automatically cleared. This process lasts for
approximately 15mS. After that, display is ready to operate. The mode of operating is set by
default. This means that:
1. Display is cleared
2. Mode
o DL = 1 Communication through 8-bit interface
o N = 0 Messages are displayed in one line
o F = 0 Character font 5 x 8 dots
3. Display/Cursor on/off
o D = 0 Display off
o U = 0 Cursor off
o B = 0 Cursor blink off
4. Character entry
o ID = 1 Addresses on display are automatically incremented by 1
o S = 0 Display shift off
Automatic reset is mainly performed without any problems. Mainly but not always! If for any
reason power supply voltage does not reach ful value in the course of 10mS, display will start
perform completely unpredictably. If voltage supply unit can not meet this condition or if it is
needed to provide completely safe operating, the process of initialization by which a new reset
enabling display to operate normally must be applied.
Nothing special... Beside elements necessary for operating (oscillator with condensators and the
simplest reset circuit), there are also several LEDs and one pushbutton which actually do not
have any practical application and are used only to indicate program operating.
All LEDs are polarized so that they are activated by logic zero (0) on the microcontroller’s pin.
LED Blinking
This program does not demonstrate LEDs’ operating but the speed of operation of the
microcontroller! Simply, in order to enable LED blinking be visible, sufficient amount of time
must pass between on/off states. In this example time delay is solved using a subroutine called
Delay. It is a triple loop where the program remains for approximately 0.5 seconds and
decrements values in registers R0, R1 or R2. Upon return from subroutine, the state on the pin is
inverted and procedure is repeated...
;************************************************************************
;* PROGRAM NAME : Delay.ASM
;* DESCRIPTION: Program turns on/off LED on the pin P1.0
;* Software delay is used (Delay).
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(DELAY.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ;Reset vector
ORG 100H
LOOP:
CPL P1.0 ; State on the pin P1.0 is inverted
LCALL Delay ; Time delay
SJMP LOOP
Delay:
MOV R2,#20 ;500 ms time delay
F02: MOV R1,#50 ;25 ms
F01: MOV R0,#230
DJNZ R0,$
DJNZ R1,F01
DJNZ R2,F02
This program describes how the watch-dog timer should not operate! As a matter of fact watch-
dog timer is properly adjusted (nominal time for counting is 1024mS), but instruction for its reset
is intentionally left out so that this timer always wins the “battle for time”. As a result, the
microcontroller is reset (state in registers remains unchanged), program starts execution from the
beginning, number in register R3 is incremented by 1 and copied to port P1 afterwards.
;************************************************************************
;* PROGRAM NAME : WatchDog.ASM
;* DESCRIPTION : After watch-dog reset, program increments number in
;* register R3 and shows it on port P1 in binary format.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(WATCHDOG.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;RESET VECTOR
CSEG AT 0
JMP XRESET ; Reset vector
CSEG
ORG 100H
This program spends the most of its time in endless loop waiting for timer T0 to count up a full
cycle. Once it happens, interrupt is generated, the routine TIM0_ISR is executed and logic zero
(0) on port P1 is shifted right by one place. This is another way to demonstrate the speed of
operation of the microcontroller since each shift means that counter T0 has counted off 216
pulses!
;************************************************************************
;* PROGRAM NAME : Tim0Mod1.ASM
;* DESCRIPTION: Program rotates "0" on port 1. Timer T0 in mode 1 is
;* used
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(TIM0MOD1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;DEFINING OF VARIABLES
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 00BH
JMP TIM0_ISR ; Timer T0 reset vector
ORG 100H
Similar to the previous example, the program spends the most of its time in a loop called
LOOP1. Since 16-bit Timer T0 is split into two 8-bit timers, there are also two interrupt sources,
therefore.
First interrupt is generated after timer T0 reset. It executes the routine TIM0_ISR in which logic
zero (0) bit on port P1 is rotated. Looking from outside, it seems that LED’s light shifts.
Another interrupt is generated upon Timer T1 reset. It executes the routine TIM1_ISR in which
the bit state DIRECTION is inverted. Since this bit determines direction of bit rotation then the
direction of LED shifting is also changed.
If at any moment a pushbutton T1 is pressed, logic zero (0) on output P3.2 will stop the Timer
T1.
;************************************************************************
;* PROGRAM NAME : Split.ASM
;* DESCRIPTION: Timer TL0 rotates bit on port P1, while TL1 determines
;* the direction of rotation. Both timers operate in mode
;* 3. Logic 0 on output P3.2 stops rotation on port P1.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(SPLIT.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;DEFINING OF VARIABLES
BSEG AT 0
;DEFINING OF BIT-VARIABLES
SEMAPHORE: DBIT 8
DIRECTION BIT SEMAPHORE
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 00BH
ORG 01BH
JMP TIM1_ISR ; Timer T1 reset vector
ORG 100H
XRESET: MOV SP,#STACK_START ; Defining of Stack pointer
MOV TMOD,#00001011B ; Defining of MOD3
MOV A,#0FFH
MOV P1,#0FFH
MOV R0,#30D
SETB TR0 ; TL0 is turned on
SETB TR1 ; TL1 is turned on
MOV IE,#08AH ; Interrupt enabled
CLR C
CLR DIRECTION ; First rotation is to right
LOOP1: SJMP LOOP1 ; Remain here
TIM0_ISR:
DJNZ R0,LAB3 ; Slow down rotation by 256 times
JB DIRECTION,LAB1
RRC A ; Rotate contents of Accumulator to
the right through
; Carry bit
SJMP LAB2
LAB1: RLC A ; Rotate contents of Accumulator to
the left through
; Carry bit
LAB2: MOV P1,A ; Contents of Accumulator is moved
to port P1
LAB3: RETI ; Return from interrupt
TIM1_ISR:
DJNZ R1,LAB4 ; Slow down direction of rotation
by 256 times
DJNZ R2,LAB4 ; If time is ran out, change
direction of
; rotation
CPL SMER
MOV R2,#30D
LAB4: RETI
One can take this program as extension of the previous one. The idea is the same but in this case
true timers T0 and T1 are used. In order to demonstrate operation of both timers simultaneously,
the Timer T0 reset is used to shift logic zero (0) on port while Timer1 reset is used to change
direction of rotation. This program spends the most of its time in the loop LOOP1 waiting for
interrupt caused by reset. By checking the bit DIRECTION, an information on direction of
rotation of both bits in Accumulator and shifting LED on port is obtained.
;************************************************************************
;* PROGRAM NAME : Tim0Tim1.ASM
;* DESCRIPTION: Timer TO rotates bit on port P1 while Timer1
;* changes direction of rotation. Both timers oper
;* ates in mode 1.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(TIM0TIM1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;DEFINING OF VARIABLES
BSEG AT 0
;DEFINING OF BIT-VARIABLES
SEMAPHORE: DBIT 8
DIRECTION BIT SEMAPHORE
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
TIM0_ISR:
JB DIRECTION,LAB1
RRC A ; Rotate contents of Accumulator to
the right through
; Carry bit
SJMP LAB2
LAB1: RLC A ; Rotate contents of Accumulator to
the left through
; Carry bit
LAB2: MOV P1,A ; Contents of Accumulator is moved
to port P1
RETI ; Return from interrupt
TIM1_ISR:
DJNZ R0,LAB3 ; If time is ran out, change
direction of rotation
CPL DIRECTION
MOV R0,#30D ; Initialize R0
LAB3:
RETI
END ; End of program
Using Timer T2
This example describes the use of Timer T2 configured to operate in Auto-Reload mode. In this
very case, LEDs are connected to port P3 while the pushbutton used for forced timer reset
(T2EX) is connected to pin P1.1.
Program execution is similar to the previous examples. When timer ends counting, interrupt is
enabled and subroutine TIM2_ISR is executed. Within it, logic zero (0) in accumulator is rotated
and afterwards content of accumulator is moved to pin P3. At the end, flags which caused
interrupt are erased and program returns to the loop LOOP1 where it remains until a new
interrupt request is encountered...
If pushbutton T2EX is pressed, timer is temporarily reset. Hence, this pushbutton resets timer
while pushbutton RESET resets microcontroller.
;************************************************************************
;* PROGRAM NAME : Timer2.ASM
;* DESCRIPTION: Program rotates log. "0" on port P3. Timer2 determines
;* the speed of rotation and operates in auto-reload mode
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(TIMER2.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;DEFINITION OF VARIABLES
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
Logic zero (0) on pin P3.2 starts interrupt routine Isr_Int0. The routine increments number in
register R0 and copies it to port P0. Low level on pin P3.3 starts subroutine Isr_Int1which
increments number in register R1 by 1 and copies it to port P1 afterwards.
In short, each press on pushbuttons INT0 and INT1 will be counted and immediately shown in
binary format on the appropriate port (LED which emitts light represents logic zero (0)).
;************************************************************************
;* PROGRAM NAME : Int.ASM
;* DESCRIPTION : Program counts interrupts INT0 which are generated by
;* appearance of high-to-low transition signal on pin
;* P3.2 Result appears on port P0. Interrupts INT1 are
;* counted off at the same time. They are generated by
;* appearing high-to-low transition signal on pin P3.
;* This result appears on port P1.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(INT.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
XRESET:
MOV TCON,#00000101B ; Interrupt INT0 is generated by
appearing
; high-to-low transition signal on pin
P3.2
; Interrupt INT0 is generated by
appearing
; high-to-low transition signal on pin
P3.3
MOV IE,#10000101B ; Interrupt enabled
MOV R0,#00H ; Counter starting value
MOV R1,#00H
MOV P0,#00H ; Reset port P0
MOV P1,#00H ; Reset port P1
Isr_Int0:
INC R0 ; Increment value of interrupt INT0
counter
MOV P0,R0
RETI
Isr_Int1:
INC R1 ; Increment value of interrupt INT1
counter
MOV P1,R1
RETI
END ; End of program
Using LED display
Following examples describe the use of LED display. Common chatode displays are used here,
which means that all built in LEDs are polarized so that their anodes are connected to the
microcontroller pins. It is not the way it should be but common way of thinking is that logic one
(1) “turns on” something while logic zero (0) “turns off” something. That is why Low Current
displays (low consumption) and their diodes (segments) are connected in series to resistors of
relatively high resistance.
In order to save I/O pins, four LED displays are connected to operate in multiplex mode. That
means that all segments having the same name are connected to one output port each and that
there is always one display active.
By quick and synchronized activation of tranzistors and segmenats on displays, one gets
impression that all digits emit lights simultaneously.
Write digits on LED display
This program is designed as “warming up” before real work starts. The single aim is to display
something on any of displays. This time it is not multiplex mode, instead, digit 3 is displayed on
only one of them (first one on the right).
Since the microcontroller “does not know” how man writes number 3, a small subroutine called
Disp is used (microcontroller writes it as 0000 0011). This subroutine performs as a mask for all
digits in decade system (0-9). The principle of the operation is simple. A number that should be
displayed is added to the current address and program jump is executed. Different numbers
match different jump length. Precisely determined combination of zeroes and units appears on
each of these new locations (digit 1 mask, digit 2 mask...digit 9 mask). When this combination is
transferred to the port, display diodes are activated as to show desired digit.
;************************************************************************
;* PROGRAM NAME : 7Seg1.ASM
;* DESCRIPTION: Program shows number "3" on 7-segment LED display
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
LOOP:
MOV A,#03 ; Send number “3” on display
LCALL Disp ; Find appropriate mask for that
number
MOV P1,A
SJMP LOOP
Program in this example is only an extended verson of the previous one. There is only one digit
active- the first one on the right side, and there is no use of multiplexing. Unlike the previous
case, all decade digits are displayed (0-9). In order to enable digits to shift at rational rate, a
soubroutine L2 which causes a small time delay is executed before each shift. Basically, the
whole process is very simple and takes place in the main loop LOOP as follows:
;************************************************************************
;* PROGRAM NAME: 7Seg2.ASM
;* DESCRIPTION: Program writes numbers 0-9 on 7-segment LED display
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG2.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
LOOP:
MOV A,R3
LCALL Disp ; Find appropriate mask for number
in
; Accumulator
MOV P1,A
INC R3 ; Increment number in register by
1
CJNE R3,#10,L2 ; Check whether the number 10 is
in R3
MOV R3,#0 ; If it is, reset counter
L2:
MOV R2,#20 ; 500 mS wait time
F02: MOV R1,#50 ; 25 mS
F01: MOV R0,#230
DJNZ R0,$
DJNZ R1,F01
DJNZ R2,F02
SJMP LOOP
It is time for time multiplex! This is the simplest example where the number 23 is displayed on
two displays which represent units and tens,. It means that digit 3 should be dispalyed on the far
right display and digit 2 on the display beside. The most important thing in the program is
regular time synchronization. Since this is the simplest case where only two digits are used and
since the microcontroller does nothing else but diaplays a number everything is very simple.
Transistor T4 “turns on” display D4 and at the same time a bits’ combination corresponding to
the digit 3 is set on the port. After that, transistor T4 is “turned off” and the whole process is
repeated using transistor 3 and display 3 in order to display digit 2. This procedure must be
continuosly repeated in order to make impression that both displays are activ at the same time.
;************************************************************************
;* PROGRAM NAME: 7Seg3.ASM
;* DESCRIPTION: Program displays number "23" on 7-segment LED display
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG3.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
XRESET: MOV SP,#STACK_START ; Defining of Stack pointer
In this example all four displays, instead of two, are active so it is possible to write numbers 0 -
9999. In this very case, the number 1 234 is displayed. After introductory initialization, program
remains in the loop LOOP where digital multiplexing is performed.The subroutine Disp has the
purpose to convert binary numbers into corresponding bit combinations for lighting segments
activation on display.
;************************************************************************
;* PROGRAM NAME : 7Seg5.ASM
;* DESCRIPTION : Program displays number"1234" on 7-segment LED display
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG5.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
Things are getting complicated... Beside two digit multiplexing, the microcontroller performs
other operations “in the background” too. In this case, contents of registers R2 and R3 are
incremented in order to make counting 97, 98, 99, 00, 01, 02... visible on display.
This time, transistors which activate displays remains on for 25mS. The soubroutine Delay is in
charge for that. Even though digits are shifted much slower it is still not slow enough to make
impression of simultaneous operating. After 20 alternate turning on and off both digits, number
on displays is incremented by 1 and the whole procedure is repeated.
;************************************************************************
;* PROGRAM NAME : 7Seg4.ASM
;* DESCRIPTION: Program displays numbers 0-99 on 7-segment LED displays
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG4.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
LAB1:
MOV P3,#20h ; Activate display D4
MOV A,R2 ; Copy Register with units to A
LCALL Disp ; Find mask for that digit
MOV P1,A ; Write units on display D4
LCALL Delay ; 25ms wait time
MOV P1,#0 ; Turn off all segments on
displays
MOV P3,#10h ; Activate display D3
MOV A,R3 ; Copy Register with tens to A
LCALL Disp ; Find mask for that digit
MOV P1,A ; Write tens on display D3
LCALL Delay ; 25ms wait time
SJMP LOOP
Delay:
MOV R1,#50 ; 25 mS
F01: MOV R0,#250
DJNZ R0,$
DJNZ R1,F01
RET
Program writes data to on-chip EEPROM memory. In this case, data is hexadecimal number 23
which written to location with address 00.
To ensure that number is correctly written, the same location in EEPROM is read 10mS later and
compared with original value. In case the numbers are identical, F will be displayed on LED
display. Otherwise, E will be displayed on LED display (Error).
;************************************************************************
;* PROGRAM NAME: EEProm1.ASM
;* DESCRIPTION: Programming EEPROM at address 0000hex and displaying message
;* on LED display.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(EEPROM1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
In order to enable successful serial communication using UART system, beside having correctly
written program it is also necessary to meet certain rules of RS232 connection. It is about voltage
levels issued by this standard. In accordance to it logic one (1) is represented by -10V in
message, while logic zero (0) is transferred like +10V. The microcontroller converts data serial
format without error but its power supply voltage is only 5V. It is not easy to convert 0V into
10V and 5V into -10V. Because of that, this operation is on both transmit and receive side left
over to specialized IC circuit. In this example, MAX232 circuit manufactured by MAXIM is
used because it is widespread, cheap and reliable.
This example demonstrates message receiving which is sent from PC. Timer T1 generates boud
rate. Since quartz crystal with frequency of 11.0592 MHz is in use it is not problem to obtain
standard baud rate which amout to 9600 baud. Each received data is transferred to port P1 pins.
;************************************************************************
;* PROGRAM NAME : UartR.ASM
;* DESCRIPTION: Each data received from PC via UART appears on the port
;* P1.
;*
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(UARTR.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 023H ; Starting address for UART interrupt
routine
JMP IR_SER
ORG 100H
Program below describes how to use UART modul for data transmission. In concrete example, a
series of numbers (0-255) are transmitted to PC at baud rate of 9600 baud. The circuit MAX 232
is used for voltage level converting.
;************************************************************************
;* PROGRAM NAME : UartS.ASM
;* DESCRIPTION: Sends values 0-255 to PC.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(UARTS.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG AT 03FH
STACK_START: DS 040H
;RESET VECTORS
CSEG AT 0
JMP XRESET ; Reset vector
ORG 100H
The most frequent LCD version which displays text in two lines with 16 characters each is used
in this example. Since I/O ports are always valuable, a method in which only 4 lines are used for
communication is applied here. In this way each byte is transmitted in two steps: first higher one,
afterwards lower nible.
You will see that, LCD needs to be initialized at the beginning (to be prepared for operating).
Besides, specific parts of the program which are repeated are separated in special totalities
(subroutines). All this may seem endlessly complicated at first sight, but the whole program
basically performs several simple operations and displays ”Mikroelektronika Razvojni
sistemi”.
*************************************************************************
;* PROGRAM NAME : Lcd.ASM
;* DESCRIPRTION : Program for testing LCD display.4-bit communication
;* is used.Program does not check BUSY flag but uses pro
;* gram delay between 2 commands. PORT1 is used for con
;* nection to the microcontroller.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(LCD.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;Stack
DSEG AT 0E0h
Stack_Start: DS 020h
;Reset vectors
CSEG AT 0
ORG Start_address
JMP Inic
ORG Start_address+100h
MOV IE,#00 ; All interrupts are disabled
MOV SP,#Stack_Start
;*************************************************
;* MAIN PROGRAM
;*************************************************
;*********************************************
;* Subroutine for wait time (T= r0 x 10ms)
;*********************************************
;****************************************************************************
**********
;* SUBROUTINE: LCD_inic
;* DESCRIPTION: Subroutine for LCD initialization.
;*
;* (is used with 4-bit interface, under condition that pins DB4-7 on LCD
;* are connected to pins PX.4-7 on microcontroller’s ports, i.e. four higher
;* bits on a port are used).
;*
;* NOTE: It is necessary to define port pins for controlling LCD operating:
;* LCD_enable, LCD_read_write, LCD_reg_select,similar to port for connection
to LCD.
;* It is also necessary to define addresses for the first character in each
;* line.
;****************************************************************************
**********
LCD_inic:
;*****************************************
MOV DPTR,#LCD_DB
RET
LCD_inic_status_8:
;******************************************
PUSH B
MOVC A,@A+DPTR
CLR LCD_reg_select ; RS=0 - Write command
CLR LCD_read_write ; R/W=0 - Write data on LCD
POP B
RET
LCD_inic_status:
;****************************************************************************
MOVC A,@A+DPTR
CALL LCD_status
RET
;****************************************************************************
;* SUBROUTINE: LCD_status
;* DESCRIPTION: Subroutine for defining LCD status.
;****************************************************************************
LCD_status: PUSH B
MOV B,#255d
DJNZ B,$
DJNZ B,$
DJNZ B,$
CLR LCD_reg_select ; RS=O: Command is sent on LCD
CALL LCD_port_out
DJNZ B,$
DJNZ B,$
DJNZ B,$
CLR LCD_reg_select ; RS=0: Command is sent on LCD
CALL LCD_port_out
POP B
RET
;****************************************************************************
;* SUBROUTINE: LCD_putc
;* DESCRIPTION: Sending character to be displayed on LCD.
;****************************************************************************
LCD_putc: PUSH B
MOV B,#255d
DJNZ B,$
SETB LCD_reg_select ; RS=1: Character is sent on LCD
CALL LCD_port_out
DJNZ B,$
SETB LCD_reg_select ; RS=1: Character is sent on LCD
CALL LCD_port_out
POP B
RET
;****************************************************************************
;* SUBROUTINE: LCD_port_out
;* DESCRIPTION: Sending commands or characters on LCD display
;****************************************************************************
POP B
POP ACC
RET
While operating with LED and LCD displays, it is often needed to convert numbers from binary
to decimal numerical system. For example, if some register contains a number in binary format
that should be displayed on three digit LED display it is necessary to convert it to decimal
format. Simply, it has to be defined what should be displayed on the far right display (units),
middle display (tens) and far left display (hundreds), respectively.
Subroutine below solves this problem in case of conversion of one byte. Binary number is stored
in Accumulator while digits of that number in decimal format are stored in registers R3, R2 and
accumulator (units, tens and hundreds).
;************************************************************************
;* SUBROUTINE NAME : BinDec.ASM
;* DESCRIPTION : Content of accumulator is converted into three decimal
;* digits
;************************************************************************
As always, beginning is the most difficult. You have bought microcontroller, you have learned
everything about its systems and registers, you have great idea how to apply all that in practice.
The only thing left over to you is to start...
Microcontroller is a good-natured “giant from the bottle” and there is no need for extra
knowledge in order to use it.
In order to create your first device under microcontroller’s control, you need: the simplest PC,
program for compiling into machine code and simple device for “transferring” that code from PC
to chip itself.
The process itself is quite logical but dilemmas are anyway common, not because it is
complicated but for the fact that there are numerous variations. Let’s start...
;RESET VECTOR
CSEG AT 0
JMP XRESET ; Reset vector
CSEG
ORG 100H
If a document is written for being used further by programmer then it has to have an extension,
.asm in its name, for example: Program asm.
If a program is written using a specialized program (mplab), this extension will be automatically
added. If any other program for text processing (Notepad) is used then the document should be
saved and additionally renamed. For example: Program.txt -> Program.asm. This procedure is
not necessary. The document may be saved in original format while Its text may be copied to
programmer for further use.
As seen, text of the program is the only thing that matters.
Microcontroller “does not undrestand” assembly language. That is why this program should be
compiled. If a specialized program is used- nothing simpler - a machine code compiler is a part
of the software! Problem is solved by a click on the appropriate icon. The result is a new
document which has extension .hex in its name. That is the same program you have already
written, but compiled into machine language which microcontroller perfectly understands. The
common name of this document is “hex code” and represents apparently meaningless series of
numbers in hexadecimal numerical system.
:03000000020100FA1001000075813F
7590FFB29012010D80F97A1479D40
90110003278589EAF3698E8EB25B
A585FEA2569AD96E6D8FED9FAD
AF6DD00000001FF255AFED589EA
F3698E8EB25BA585FEA2569AD96
DAC59700D00000278E6D8FED9FA
DAF6DD00000001FF255AFED8FED
9FADAF6DD000F7590FFB29013278
E6D8FED9FADAF6DD00000001FF2
55AFED589EAF3698E8EB25BA585
FEA2569AD96DAC59D9FADAF6D
D00000001FF255AFED8FED9FADA
F6DD000F7590FFB29013278E6D82
78E6D8FED9FA589EAF3698E8EB2
5BA585FEA2569AD96DAF6DD000
00001FF2DAF6DD00000001FF255A
ADAF6DD00000001FF255AFED8FE
D9FA
In case some other software for writing program in assembler is used, a software especially
installed for compiling into machine code must be used. This compiler is activated, document
with extension .asm is open and the appropriate command is executed. The result is the same- a
new document with extension .hex. The only problem is that it is stored in your PC.
Acable for serial communication and a special device called programmer are necessary to
transfer “hex code” to the microcontroller. There are also several options on how to do it.
A great deal of programs and electronic circuits having this purpose can be found on Internet. Do
as follows: open hex code document, adjust a few parameters and click on the icon for
compiling. After a while, a series of zeros and units will be programmed into the microcontroller
through the serial connection cable. The only thing left over is to transfer programmed chip to
the final device. In case it is necessary to change something in the program, the previous
procedure may be repeated.
How it operates?
...Open a new document: File -> New. Introductory header appears. Write your program or copy
text...
... Save and name your document : File -> Save As... (Document name is limited to 8
characters!)
Finally, to compile program into HEX code select: Project -> Build or click on the icon “play”.
If everything works properly, the computer will reward you with a minireport!
Program is written and successfully compiled into machine code. It is only left over to load it to
the microcontroller. For this purpose it is necessary to have programator and software which
interfere between PC and programator hardware.
That’s all! Program is loaded into the microcontroler and everything is ready for operating. If
you are not satisfied, make some changes in your program and repeat the procedure. Until when?
Until you feel satisfied...
This is one of high-quality development systems used for programming 8051 compatible
microcontrollers manufactured by Atmel. Beside chip programming, this system enables direct
testing all parts of a program because it contains the most components which are normally built
in the real devices.
Sockets for placing microcontrollers (14, 16, 20 and 40- pin packages)
Connector for external power supply (DC 12V)
USB programmator
Power Supply Selector (external or via USB cable)
Quartz Crystal Oscillator 8 Mhz
32 LEDs for output pins’ state indication
32 pushbuttons for activating input pins
Four 7-segment LED displays in multiplex mode
Graphic LCD display
Alphanumeric LCD display (4- or 8- bit mode)
Connector and driver for serial communication RS232
Digital thermometer DS1820
12- bit A/D converter (MCP3204)
12- bit D/A converter (MCP4921)
Reference voltage source 4.096V (MCP1541)
Multiple-pin connectors for direct access to I/O ports
Several following pages describe in short some circuits within this development system- it is
more illustration of its possibilities than complete instructions. Besides, familiarizing with details
of this device testifies that microcontrollers and tools for handling them are neither privilege nor
secret of the few.
Sockets
All microcontrollers manufactured by Atmel appear in a few standard DIP packages. In order to
enable their programming using one device, corresponding pins on sockets are connected in
parallel (pins having the same name). In accordance to that, by being placed in the appropriate
socket, each microcontroller will be automatically properly connected! Figure on left shows in
detail microcontroller in 40-pin package and connection of one of its I/O pins (P1.5) as well. As
seen, the pin can be connected to some external device (connector PORT1), LED (microswitch
SW2), pushbutton or resistor through connectors. In the last two cases, polarity of voltage is
selected using on board jumpers.
Programmer
The purpose of the programmer is to transfer HEX code from PC to the appropriate pins and
provide regular voltage levels during chip programming as well. In this case it belongs to
development system and should be connected to PC via USB cable. Once programming is
completed, pins used during that proces are automatically available for other application.
Development system power supply
There is a connector for external power supply source (AC/DC, 8-16V) on the development
board. Besides, voltage necessary for device operating can be also obtained from PC via USB
cable. Jumper J5 is used for power supply selecting.
8MHz Oscillator
EASY8051A Development system has got built in oscillator used as a clock signal generator.
Frequency of this oscillator is stabilized by quartz crystal. Besides, during chip programming,
internal RC oscillator can be selected instead.
LEDs for output pins’ state indication
All I/O ports pins are connected to one LE diode each, which enables visual indication of their
logic state. In case that presence of direct polarized LEDs and serial resistors is not acceptable in
very application, DIP switch SW2 enables them to be disconnected from the port.
Pushbuttons for activating input pins
Similar to LEDs, each I/O port pin is connected to one pushbutton on the development board. It
enables simple activation of input pins. Jumper J6 is used for selecting voltage polarity (+ or -).
Press on the appropriate pushbuttons brings selected voltage to the pins.
7-segment LED displays
For being often applied in industry, four high-performance LED displays set up in multiplex
mode belong to the development board. Displays’ segments are connected to the port P0 through
resistors. Transistor drivers for activation of individual digits are connected to the first four port
P1 pins. It enables testing programs which use 7-segment displays with minimal use of I/O ports.
Similar to LEDs, DIP switch SW2 disconnects transistor drivers from microcontroller’s pins.
LCD displays
In order to enable testing programs which use serial communication, development system has
built in standard 9-pin SUB-D connector. The circuit MAX232 is used as a driver for voltage
adjustment.
As it is case with other embedded systems, electronics which suppports serial communication
can be enabled or disabled by using jumpers J9 and J10.
DS1820 Digital thermometer
Temperature measurement is one of the most common tasks of devices which operate in
industry. For that reason, there is a circuit DS1820 on the EASY8051A development system
board which measure temperature in the range of -55 to +125oC with accuracy greater than 0.50.
Results of measuring are transferred via serial communication to the pins P3.3 or P2.7. Jumper
J7 is used for selecting pins for receiving data. In case that no one jumper is installed, port pins
are available for other application.