Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
In the beginning there was an electricity... People lived in an ignorant bliss, having no idea that
energy was everywhere around them and that it could be tamed. It was good... And then came
Faraday, and the ball started to roll, picking up the speed slowly but surely...
Eventually, first machines using the new energy source were built, and with these came the first
people who could "understand the electricity". Time passed on and just about the time civilized world
got used to this new concept and let the self-proclaimed experts toy with it, somebody came up with
an idea to put electrons in a glass tube. At the first glance, it seemed like a good idea... but there was
no turning back as electronics was born and the ball kept on rolling faster...
New science called for new scientists. White collars took the place of blue collars and there came the
people who could "understand the electronics". And while the world stared in awe, the conspirators
split up in two factions: those who specialized in software and those who specialized in hardware.
Younger and more enthusiastic than their teachers, both groups carried on their efforts, but following
the different paths. While the first advanced steadily to this day, those dedicated to hardware got
carried away by their success and eventually discovered a transistor.
Up to that crucial moment, the situation could have been controlled to a certain extent - but the public
underestimated the importance of this breakthrough and made a grave mistake! In a naive attempt to
slow down the technological revolution, world market opened itself for a flood of electronic products,
thus closing the circle. Market value of components rapidly decreased, electronics making its way to
the younger populace. The ball started to fall freely...
Discovery of the integrated circuits and the processors only sped up the things, making the computers
as available as ever. Computers started to upgrade themselves. The resulting deflation brought
electronics new wave of devotees, making it omnipresent nowadays. Yet another circle closed -
computers fell into the hands of the masses and their rule supreme had begun...
While this drama took place, nameless hobbyists and professionals across the world kept working on
their projects, although still divided into two large factions.
And then somebody came up with another great idea: why not create an all-purpose component? A
cheap and universal integrated circuit that could be programmed and used in any device, anywhere.
Technology was up to the task, there was an interested market... why not? Soul and body were united
into one powerful MICROCONTROLLER.
As with everything that is good, this powerful component is actually very simple in its essence. It was
built using the tested solutions and ingredients by the following recipe:
1. Processor was removed from the simplest of computers to be used as the "brain" for the
upcoming system.
2. Depending on the manufacturers' taste, some memory was added, a few A/D converters,
timers, I/O communication lines, etc.
3. It was all placed in a standard casing.
4. Simple software that everybody could learn was developed for controlling the thing.
A variety of microcontrollers has been constructed in this manner, becoming a man's subtle yet
indispensable companion in everyday life. Their incredible simplicity and flexibility has earned our
trust awhile ago - if you have an idea of utilizing a microcontroller for the most trivial of tasks, know
that somebody has already been there...
There are three decisive facts responsible for such a success of microcontrollers:
Their powerful, cleverly chosen electronics is able to control a variety of processes and
devices (industrial automatics, voltage, temperature, engines, etc) independently or by means
of I/O instruments such as switches, buttons, sensors, LCD screens, relays...
Their low cost makes them suitable for installing in places which attracted no such interest in
the past. This is the fact accountable for today's market being swamped with cheap
automatons and "intelligent" toys.
Writing and loading a program into microcontroller requires practically no previous
schooling. All that is required is: any PC (software is very friendly and intuitive) and one
simple device (programmer) for loading a written program into microcontroller.
So if you are into electronics, you will undoubtedly want to master the great potential of
microcontrollers and put it to good use.
1. Power is off and all is still... Program is loaded, everything is set, with no indications of what
is about to take place...
2. As soon as the power is on, it all happens too quickly to follow! First one to register the
change is the control logic. It halts all the circuits except the quartz oscillator. First few
milliseconds pass in hurried preparations and loading of parasitic capacitances...
3. As voltage reaches its maximum, oscillator frequency stabilizes. SFR registers are loaded
with bits indicating the states of the subsystems, and all the pins are designated as input.
Impulse sequence starts dictating the pace and the electronics is now fully operational. From
this point on, time is measured in microseconds and nanoseconds.
4. Program counter is reset to zero address of the program memory. Instruction is sent from this
address to the instruction decoder where it is interpreted and executed promptly.
5. Program counter is incremented by one as the whole process plays out again... (several
millions of times per second)
Obviously, it all works at tremendous speeds, and is also pretty simple. But it would not be especially
useful if it was not for additional systems which round out the MCU:
ROM is the memory which stores the program to be executed. Apparently, its size dictates the
maximal program length. It can be internal or external with respect to the microcontroller. Both
options have their pros and cons; external memory chip makes the microcontroller cheaper and allows
for longer programs. At the same time, number of available free pins is reduced as external ROM uses
MCU's I/O ports. Internal ROM is usually smaller and more costly but it provides more possibilities
for connecting to the outside world. ROM spans from 512 bytes to 64kB, which is an equivalent to
the number of possible program instructions.
RAM is used for temporary storage of data during runtime. RAM memory does not retain its stored
information when the power is interrupted. RAM spans from tens of bytes to several kilobytes.
EEPROM Memory
EEPROM is a special kind of memory not available with all MCUs. Its contents can be changed
during runtime (as with RAM), but is also saved after the power is off (as with ROM).
SFR Registers
Special Function Registers are special elements of RAM, their purpose predefined by the
manufacturer. Each of these registers is named and controls a certain subsystem of MCU. For
example: by writing zeros and ones to the SFR register which controls an I/O port, each of these pins
can be designated as input or output (each register bit corresponds to one of the port pins).
Program Counter
This is the "engine" which starts the program and points to the memory address of the instruction to
be executed. Immediately upon its execution, value of counter increments by 1. Due to this automatic
increase, program executes one instruction at a time, just the way it was written. However... value of a
counter can be changed anytime with a "jump" to a new program memory location as a result. This is
how routines and branch instructions are carried out. Upon performing a jump to the specified
destination, Program Counter increase carries on steadily, +1, +1, +1...
Bit is the term often found to be confusing by those starting out in electronics. In practice (and in
practice only) bit determines if voltage exists between two points of a circuit. If it does, we say that
logic level is 1, i.e. bit is 1. If not, logic level is 0, i.e. bit is 0.
In theory, things are a little bit more complicated - bit actually represents a digit of binary system. As
such, it can still have only one of two values - zero or one, set or clear (unlike the decimal system we
are used to).
Control Logic
As the name implies, this is the "Big Brother" which supervises and controls every aspect of
operations within MCU, and it cannot be manipulated. It comprises several parts, the most important
ones including:
Instructions Decoder – part of the electronics which "recognizes" different program
instructions and directs the other circuits accordingly.
Arithmetical Logical Unit (ALU) – is in charge of all mathematical and logical operations
over data. Capabilities of this circuit are represented through the so called "instruction set"
which is different for every MCU.
Accumulator – a special SFR register highly interconnected with ALU. It can be described as
a working desk for performing operations on data (adding, shifting, etc). Also, this is the
register which holds the result of the operation. Of SFR registers, Status Register is
specifically associated with the accumulator. It monitors the status of the accumulator's
content at all times (is zero, is greater than zero, etc).
Byte is a set of 8 adjacent bits. As bit represents a digit, it is logical to assume that byte represents a
number. All standard mathematical operations that can be applied to decimal numbers can be applied
to bytes. These are carried out by ALU.
It is important to note that byte has "two sides", i.e. not all positions are of the same significance. The
leftmost bit is the Most Significant Bit (MSb). The rightmost bit is the Least Significant Bit (LSb). As
there are 256 possible variations of 8 bits, the greatest decimal number byte can represent is 255 (zero
is included!) .
A/D Converter
Another convenient instrument not available with all MCUs. Usually there are several separate
channels so that multiple analog values can be measured simultaneously. Commonly, converters are
8, 10, or 12-bit and this is sufficient for most tasks.
As shown on the image below, A/D conversion (converting analog value to a numeral) starts with
changing the bit in the appropriate SFR register. Hence, voltage on input pin is measured (this
sampling takes a few microseconds) and stored in another SFR register as a numeral.
In our example, 8-bit A/D converter is used and the default voltage is 5V. This divides the scale in
256 units, with the smallest voltage range that can be represented of 19.53mV (5V / 256 = 19.53mV).
On such a "crude" scale, voltage of 2.204V is represented by numeral 113 (113 x 19.53mV =
2.207V).
Converters of higher resolutions (10 and 12-bit) have much finer scales of 1024 or 4096 units,
respectively. Using one of these instruments under the same conditions from the previous example
would significantly reduce the inaccuracy (as shown on the image below).
Register is a byte physically realized as electronic component, and represents a basic memory cell.
Beside the 8 bits available to the user, there is also an address part not readily accessible.
ROM and RAM registers are nameless and are usually peers.
SFR registers are named (differently with different MCUs) and each has its role.
When writing a code for MCU in one of the higher programming languages, each register can be
given an arbitrary name, which proved to be useful.
I/O Ports
To be of any practical use, microcontroller needs to be connected to other electronics and to the
environs. For this purpose, every MCU has one or more registers (also known as ports) which are
connected to the pins on its case. Why I/O? Because every pin can be designated as eiher input or
output to suit user's needs.
Oscillator
This is the rhythm section of the miniature orchestra. Stable pace provided by this instrument allows
harmonious and synchronous functioning of all other parts of MCU. Commonly, oscillator frequency
is stabilized using a quartz-crystal or a ceramic resonator. It can also work without an element for
stabilizing frequency (as RC oscillator). Note that instructions are executed at a rate several times
slower than the pace dictated by the oscillator. This happens because instructions take several steps to
be accomplished (execution period of different instructions may vary on different MCUs). Therefore,
if your system uses 20MHz quartz-crystal, execution period of one program instruction will not be 50
ns, but more likely 200, 400 or a "whole" 800 ns.
Timers
Majority of programs utilizes these miniature electronic "stopwatches". Commonly, timers are 8 or
16-bit registers whose value automatically increases upon an impulse. If timer is stimulated by an
internal MCU oscillator, it can be used for measuring time between two occurrences (register value at
the start of measuring = T1, register value at the end of measuring = T2, elapsed time = T2-T1). If
timer is triggered by impulses from an external source, instrument behaves like a counter.
In both cases, filling the register resets the counter and the occurrence is recorded in a particular bit of
SFR register (Overflow flag). This makes possible to measure longer time periods. Also, if enabled,
this flag can cause an interrupt for breaking the program and carrying out a designated routine (see
the image).
Watchdog Timer
The name itself implies the role of this instrument. It is a timer with input connected to an
independent MCU RC oscillator. If Watchdog is enabled, MCU is reset every time it overflows, and
the program execution starts anew (much as if the power had just been turned on). The idea is to
prevent that from happening by means of special instruction. Whole concept is based upon a fact that
every program technically "goes around", i.e. executes within a number of simpler or more complex
loops. If, beside the regular instructions, key places in the program were added an instruction for
resetting the Watchdog, its safeguard function would pass unnoticed. If, for some reason, (in
industrial environment, electrical interference is common) Program Counter "gets stuck" at a memory
location with no return, the ever-increasing Watchdog Timer eventually overflows and voila - MCU
is reset.
Interrupt ; electronics is generally way faster than physical processes in the environment it controls.
Therefore, microcontroller spends most of its time in expecting an occurrence or waiting for tasks to
be accomplished. To avoid the repeated checks of input pins and internal registers, interrupt was
introduced. It is a signal which breaks the standard order of program execution. In case of an
interrupt, MCU comes to a halt, and determines the source of interrupt. If certain action is required,
current value of Program Counter is set aside to Stack and the appropriate routine (interrupt routine)
is executed.
Stack is a special part of RAM for storing the current value of Program Counter, so that program
could "know" where to pick up after the interrupt routine. It can be multi-leveled, i.e. routines can be
executed within other routines.
Two features of the MCU power supply circuit deserve your attention:
Brown out – this is a potentially dangerous state which occurs during the shutdown or in
situations when voltage "oscillates" on the edge of the allowed range due to strong
interference. Since microcontroller comprises a number of elements with various voltage
ranges, this can cause their uncontrolled behavior. To prevent this from happening, brown out
reset circuit is included within MCU. If voltage drops below the specified value for high-
voltage elements of MCU, brown out promptly resets the entire electronics.
Reset pin – frequently marked as MCLR (Master Clear Reset) is used for "external" reset of
microcontroller by bringing the logical zero or one (depending on the MCU). If not
preinstalled, a simple external brown out reset circuit can be connected to this pin.
A struggle has been going on between MCU manufacturers for quite a long time, each of them trying
to best respond to the ever-increasing demands of the market. Every couple of days there is a brand
new chip available, working at higher frequency, with more memory or with better A/D converters.
And yet, a closer look to their interior reveals the same or at least very similar structural design
referred to as "8051 compatibility". What is it all about?
The story began in the 80's when Intel introduced their microcontroller family MCS 8051 to the
market. Although this family had quite limited capabilities by today's notions, it quickly captivated
the world and became the standard for what is today understood as 'microcontroller'. The most
significant cause for such a success can be found in the cleverly chosen configuration which can
satisfy a diversity of needs, yet allowing for continuous upgrades (in form of new controllers). In a
brief period of time, a decent amount of software has been developed for 8051, making further
changes of the hardware core simply uneconomical. Consequently, there is a variety of MCUs
available today, basically just the upgraded 8051 models. What exactly makes this microcontroller so
special and universal that it is still manufactured by all the major companies, just under a different
label?
As can be seen on the image above, there is nothing particularly remarkable about MCU 8051:
1–8: Port 1; Each of these pins can be used as either input or output according to your needs.
Also, pins 1 and 2 (P1.0 and P1.1) have special functions associated with Timer 2.
9: Reset Signal; high logical state on this input halts the MCU and clears all the registers.
Bringing this pin back to logical state zero starts the program anew as if the power had just
been turned on. In another words, positive voltage impulse on this pin resets the MCU.
Depending on the device's purpose and environs, this pin is usually connected to the push-
button, reset-upon-start circuit or a brown out reset circuit (covered in the previous chapter).
The image shows one simple circuit for safe reset upon starting the controller. It is utilized in
situations when power fails to reach its optimal voltage.
10-17: Port 3; As with Port 1, each of these pins can be used as universal input or output.
However, each pin of Port 3 has an alternative function:
Pin 10: RXD - serial input for asynchronous communication or serial output for
synchronous communication.
Pin 11: TXD - serial output for asynchronous communication or clock output for
synchronous communication
Pin 12: INT0 - input for interrupt 0
Pin 13: INT1 - input for interrupt 1
Pin 14: T0 - clock input of counter 0
Pin 15: T1 - clock input of counter 1
Pin 16: WR - signal for writing to external (add-on) RAM memory
Pin 17: RD - signal for reading from external RAM memory
18-19: X2 and X1; Input and output of internal oscillator. Quartz crystal controlling the
frequency commonly connects to these pins. Capacitances within the oscillator mechanism
(see the image) are not critical and are normally about 30pF. Instead of a quartz crystal,
miniature ceramic resonators can be used for dictating the pace. In that case, manufacturers
recommend using somewhat higher capacitances (about 47 pF). New MCUs work at
frequencies from 0Hz to 50MHz+.
Every MCU from 8051 family has 4 I/O ports of 8 bits each. This provides the user with 32 I/O lines
for connecting MCU to the environs. Unlike the case with other controllers, there is no specific SFR
register for designating pins as input or output. Instead, the port itself is in charge: 0=output, 1=input.
If particular pin on the case is needed as output, the appropriate bit of I/O port should be cleared. This
will generate 0V on the specified controller pin. Similarly, if particular pin on the case is needed as
input, the appropriate bit of I/O port should be set. This will designate the pin as input, generating
+5V as a side effect (as with every TTL input).
Port 0
Port 0 has two fold role: if external memory is used, it contains the lower address byte (addresses A0-
A7), otherwise all bits of the port are either input or output. Another feature of this port comes to play
when it has been designated as output. Unlike other ports, Port 0 lacks the "pull up" resistor (resistor
with +5V on one end). This seemingly insignificant change has the following consequences:
When designated as input, pin of Port 0 acts as high impedance offering the infinite input
resistance with no "inner" voltage.
When designated as output, pin acts as "open drain". Clearing a port bit grounds the
appropriate pin on the case (0V). Setting a port bit makes the pin act as high impedance.
Therefore, to get positive logic (5V) at output, external "pull up" resistor needs to be added
for connecting the pin to the positive pole.
Therefore, to get one (5V) on the output, external "pull up" resistor needs to be added for connecting
the pin to the positive pole.
Port 1
This is "true" I/O port, devoid of dual function characteristic for Port 0. Having the "pull up" resistor,
Port 1 is fully compatible with TTL circuits.
Port 2
When using external memory, this port contains the higher address byte (addresses A8–A15), similar
to Port 0. Otherwise, it can be used as universal I/O port.
Port 3
Beside its role as universal I/O port, each pin of Port 3 has an alternate function. In order to use one of
these functions, the pin in question has to be designated as input, i.e. the appropriate bit of register P3
needs to be set. From a hardware standpoint, Port 3 is similar to Port 0.
***
As can be seen from the individual descriptions of the ports, they all share highly similar structure.
However, you need to consider which task should be assigned to which port. For example: if utilizing
port as output with high level (5V), avoid using Port 0 as its pins cannot produce high logical level
without an additional resistor connected to +5V. If using other port to a same end, bear in mind that
built-in resistors have relatively high values, producing the currents limited to few hundreds of
amperes as pin output.
During the runtime, microcontroller uses two different types of memory: one for holding the program
being executed (ROM memory), and the other for temporary storage of data and auxiliary variables
(RAM memory). Depending on the particular model from 8051 family, this is usually few kilobytes
of ROM and 128/256 bytes of RAM. This amount is built-in and is sufficient for common tasks
performed "independently" by the MCU. However, 8051 can address up to 64KB of external
memory. These can be separate memory blocks, (separate RAM chip and ROM chip) totaling 128KB
of memory on MCU which is a real programming goody.
ROM memory
First models from 8051 family lacked the internal program memory, but it could be added externally
in a form of a separate chip. These MCUs can be recognized by their mark which begins with 803
(e.g. 8031 or 8032). New models have built-in ROM, although there are substantial variations. With
some models internal memory cannot be programmed directly by the user. Instead, the user needs to
proceed the program to the manufacturer, so that the MCU can be programmed (masked)
appropriately in the process of fabrication. Obviously, this option is cost-effective only for large
series. Fortunately, there are MCU models ideal for experimentation and small specialized series.
Many manufacturers deliver controllers that can be programmed directly by the user. These come in a
ceramic case with an opening (EPROM version) or in a plastic case without an opening (EEPROM
version). This book deals with one of the latter models that can be programmed via simple
programmer, even if the chip has already been mounted to the designated device.
RAM memory
As previously stated, RAM is used for storing temporary data and auxiliary results generated during
the runtime. Apart from that, RAM comprises a number of registers: hardware counters and timers,
I/O ports, buffer for serial connection, etc. With older versions, RAM spanned 256 locations, while
new models feature additional 128 registers. First 256 memory locations form the basis of RAM
(addresses 0 – FFh) of every 8051 MCU. Locations that are available to the user span addresses from
0 to 7Fh, i.e. first 128 registers, and this part of RAM is split into several blocks as can be seen in the
image below.
First block comprises 4 "banks" of 8 registers each, marked as R0 - R7. To address these, the
parent bank has to be selected.
Second memory block (range 20h – 2Fh) is bit-addressable, meaning that every belonging bit
has its own address (0 to 7Fh). Since the block comprises 16 of these registers, there is a total
of 128 addressable bits. (Bit 0 of byte 20h has bit address 0, while bit 7 of byte 2Fh has bit
address 7Fh).
Third is the group of available registers at addresses 2Fh – 7Fh (total of 80 locations) without
special features or a preset purpose.
Extra Memory Block
To satisfy the programmers' ever-increasing demands for RAM, latest 8051 models were added an
extra memory block of 128 locations. But it is not all that simple... The problem lies in the fact that
the electronics which addresses RAM employs 1 byte (8 bits), reaching only the first 256 locations.
Therefore, a little trick had to be applied in order to keep the existing 8-bit architecture for the sake of
compatibility with older models. The idea is to make the additional memory block share the addresses
with the existent locations intended for SFR registers (80h - FFh). For distinguishing these two
physically separate memory areas, different methods of addressing are used: if SFR registers are in
question, direct addressing is used; for extra RAM locations, indirect addressing is used.
Memory Expanding
In case the built-in amount of memory (either RAM or ROM) is not sufficient for your needs, there is
always an option of adding two external 64KB memory chips. When added, they are addressed and
accessed via I/O ports P2 and P3. From user's point of view it's all very simple, because if properly
connected most of the job is carried out automatically by MCU.
8051 MCU has two separate read signals, RD# (P3.7) and PSEN#. The first one is active when
reading byte from the external data memory (RAM), and the second one is active when reading byte
from the external program memory (ROM). Both signals are active on low logical level. The
following image shows a typical scheme for such expansion using separate chips for RAM and ROM,
known as Harvard architecture.
Memory can be also mapped as a single block, functioning as both data memory and program
memory simultaneously (only one memory chip is used). This approach is known as Von Neumann
architecture. To be able to read the same block using RD# or PSEN#, these two signals were
combined via logical AND. In this way, output of AND circuit is low if any of the two inputs is low.
Using the Harvard architecture effectively doubles MCU memory, but that's not the only advantage
offered by the method. Keeping the program code separated from the data makes the controller more
reliable since there is no writing to the program memory.
SFR registers can be seen as a sort of control panel for managing and monitoring the microcontroller.
Every register and each of the belonging bits has its name, specified address in RAM and strictly
defined role (e.g. controlling the timer, interrupt, serial connection, etc). Although there are 128
available memory slots for allocating SFR registers, the basic core shared by 8051 MCUs has but 22
registers. The rest has been left open intentionally to allow future upgrades while retaining the
compatibility with earlier models. This fact makes possible to use programs developed for obsolete
models long ago.
Introduction
Today, after more than 20 years of continuous improvement, MCU 8051 is being manufactured
across the world by various companies under many different trademarks. Of course, the latest
models are by far more advanced than the original 8051. Many of these are labeled as "8051
compatible", "8051 compliant", or "8051 family" to emphasize their "noble heritage". These tags
should imply that MCUs share common architecture and are programmed in a similar fashion,
using the same instruction set. In practice, if you master one of the models, you will be able to
handle any other from 8051 family which encompasses several hundreds of different controllers.
This book covers the model named AT89S8252, manufactured by Atmel. Why this particular
one? Because it is widespread, cheap and uses Flash memory. The latter makes it ideal for
experimentation due to the fact that program can be loaded and erased a number of times. Also,
thanks to the built-in SPI system (Serial Programming Interface), program can be loaded to the
MCU even if the chip has already been mounted to the designated device.
VCC
GND
If designated as output, each of these pins can be connected up to 8 TTL input circuits. If
designated as input, they are high impedance inputs as their potential is undefined with respect to
the ground. If external memory is used, these pins are used for alternate transfer of data and
addresses (A0-A7) for accessing the extra memory chip. Signal on ALE pin determines the mode
of transfer on port.
If designated as output, each of these pins can be connected up to 4 TTL inputs. If designated as
input, these pins act like standard TTL inputs (that is, they have an internal resistor connected to
the positive supply pole and a +5V voltage). Also, pins of Port 1 have alternate functions
according to the following table:
If designated as input or output, this port is identical to Port 1. If external memory is used, Port 2
stores the higher address byte (A8-A15) for addressing the extra memory chip.
Similar to Port 1, Port 3 can also be used as universal I/O, but pins of Port 3 also have alternate
functions. Each of the functions will be explained in detail later in the chapter.
RST
Positive voltage impulse on RST pin resets the MCU. In order to be detected, this impulse needs
to have duration of at least two operating cycles (this cycle represents the time necessary to
execute one instruction and lasts for 12 oscillator signals).
ALE/PROG
This pin emits an impulse sequence with a frequency equal to 1/6 of the frequency generated by
the main oscillator. If external memory is used, signal from this pin controls the additional
register for temporary storage of the lower address byte (A0 - A7). This pin also serves as a
control input during the writing of program to MCU.
PSEN
Signal of this pin is used for reading from external program memory (ROM).
EA/VPP
When this pin is connected to the ground, MCU gets 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 pole (VCC). During the loading of program to internal Flash
memory, this pin is at +12V.
XTAL 1
This is the input part of internal oscillator. It is used for synchronizing the MCU with another
circuit. Also, if there is need to use an external oscillator, it connects to this pin.
XTAL 2
Input of internal oscillator connects to this pin. In case external oscillator is used, this pin is
without a function.
MCU AT89S8252 has total of 33 Special Function Registers. For the sake of compatibility with
earlier 8051 models, basic group of registers (22 of them) kept their function and addresses, while
the rest were added to manage new functions.
As shown in the following table, each of the registers has its name and specific address in RAM.
Locations not shaded are planned for future expansions and new MCU models, and are generally
not available. This chapter covers "general" SFR registers; specialized registers such as the ones
controlling the timer, or SPI, will be covered in the following chapters.
Accumulator
Accumulator is a general purpose register which stores runtime results. Before performing any
operation upon an operand, operand has to be stored in the accumulator. Results of arithmetical
operations (performed by ALU) are also stored in the accumulator. When transferring data from
one register to another, it has to go through the accumulator. Due to its verastile role, this is the
most frequently used register, essential part of every MCU.
"R" registers (R0 - R7)
Although not true SFR registers, "R" registers deserve to be mentioned at this point. They are
located within one of the 4 banks in RAM, and like the accumulator, serve for temporary storage
of variables and runtime results. Two bits of PSW register are in command which bank will hold
"R" registers.
Note: Since registers are called upon by the name during the writing of program, programmer
needs not to know their exact addresses. When compiled (translated into hex code
comprehensible to the controller), program will automatically replace register names with the
appropriate addresses.
B register
Instructions of multiplication and division can be applied only to operands located in registers A
and B. Other instructions can use this register as a secondary accumulator (A).
If external memory and system for serial communication are not used, user has 4 ports (32 I/O
lines) at disposal for communicating to the environs. Every port bit corresponds to one of the pins
on the casing, thus controlling the voltage on output (0 or 5V). Vice versa, while reading, voltage
on input pins is interpreted into bit logic on port. At the same time, state of port bit designates the
pin as input or output: zero for output, one for input.
After reset, all port bits are set, designating all corresponding pins as input.
The number in Stack Pointer points to the location of the last "valid" address within the Stack.
With the beginning of every new routine, Stack Pointer increases by 1; upon return from routine,
SP decreases by 1. After reset (or turning the power on), this register contains number 7, meaning
that the amount of RAM allocated to Stack begins from this memory location. If another value is
written to SP, entire Stack moves to the new specified location.
Program Status Word (PSW)
Program Status Word is one of the most important SFR registers, and is used for managing
program during the runtime. ALU automatically makes changes to certain bits of this register.
P (bit 0) - Parity bit. If numeral in accumulator is even, bit is automatically set (1),
otherwise it's cleared (0). It is commonly used in data transfers via serial connection.
- (bit 1) - This bit is intended for the upcoming MCU models and shouldn't be used.
OV (bit 2) - Overflow bit. If result of arithmetical operation exceeds 255 (decimal), OV is
set (1), otherwise it's cleared (0).
RS1, RS0 (bits 3 and 4) - Register select. Masking these bits stores registers R0 - R7 into
one of the 4 banks in RAM, according to the following table.
Data Pointer
Data Pointer actually consists of two registers: DPH (Data Pointer High) and DPL (Data Pointer
Low). Data Pointer's 16 bits are used for addressing external memory. Since this is the only 16-bit
register available to programmer, it is commonly used for temporary storage of data and runtime
results not related to memory locations.
It was mentioned in previous chapters that MCU clock employs quartz crystal. As this frequency
is highly stable and accurate, it is ideal for time measuring (similar oscillators can be found in
watches). To determine the amount of time past between two occurrences, all you need to do is
count the generated impulses. This is where the timer takes part; properly programmed, value of
timer register will increase or decrease with every MCU clock impulse. Since one instruction
takes 12 oscillator cycles to complete, the math is easy. For example, if quartz oscillator works at
12 MHz, timer register will increase/decrease every microsecond (million times per second).
AT89S8252 has three timers/counters marked as T0, T1, and T2. Two of them are from the "first
lineup" shared by all models from 8051 family, while the third (T2) was added in the process of
developing the basic model. Their purpose is to measure time and count external occurrences, but
can also be used as clock in serial connection, Baud Rate.
Timer T0
As shown in the image below, T0 consists of two registers - TH0 and TL0, for storing higher and
lower byte of a 16-bit binary numeral.
For example, if T0 = 0, both registers will have value of zero. If T0 has value of 1000 (decimal),
TH0 (higher byte) will hold decimal value of 3, and TL0 (lower byte) will hold decimal value of
232. See the image below.
Timers are technically 16-bit registers, thus the maximal value they can hold is 65.535. If this
number is exceeded, timer will automatically reset and start from zero. This situation is known as
overflow.
Four bits from the previous table determine the operating mode of timers T0 and T1. There are 4
of these modes, and each will be covered in details.
Mode 1 uses all bits of registers TH0 and TL0, and is commonly used. Counting process is same
as with Mode 0, except the timer reaches value of 65.536 (max for 16 bits) before reset.
Advantages of this mode will be illustrated on the following example: suppose that there is a need
to report every 55th impulse of the clock. If Mode 0 or Mode 1 was used, you would need to store
200 (decimal) into T0, and then continually check for the overflow (exceeding 255 decimal).
Upon hit, value of 200 would need to be written to T0 again. In Mode 2, MCU performs this task
automatically. Namely, TL0 works as an 8-bit timer, while TH0 stores the starting value,
specifically 200 in our example. When TL0 is filled, instead of reset, it will load value from TH0.
Thus, to register every 55th impulse, all you need to do is write 200 to TH0, and set the Timer
Mode 2.
When Timer T0 is configured to Mode 3, you actually get an additional timer. In this mode,
registers TH0 and TL0 act as separate 8-bit timers: TH0 substitutes Timer 0, while TL0
substitutes Timer 1. Consequently, all control bits associated with the original Timer 1 (16-bit
register consisting of TH1 and TL1) are now in control of newly created "Timer 1". This means
that, although it can be set to any mode (Mode 1, 2, or 3), the original Timer 1 cannot be stopped
anymore, because there is simply no control bit to do it. In this mode, it will be constantly active
in the background.
Of the 8 bits, TCON uses only 4 bits for controlling the timers, while the other 4 are associated
with interrupts.
Starting Timer T0
Right after the command for setting the bit TR0, Timer is operational. Assuming that 12MHz
quartz crystal is installed, value in T0 will increase every microsecond. After passing of 65.536
microseconds, both registers of the Timer will be full. MCU automatically resets them and the
Timer continues the loop, as long as the bit TR0 is set.
Reading Timer
Depending on the application, you need either the value written in Timer registers, or the exact
point of time at which the Timer is reset.
If you need to read the value of the Timer which uses only one register for counting
(Mode 3, for example) just read the value of that register.
If the Timer works in Mode 2, reading is a bit more complicated. For example, you might
have obtained values of the lower and the higher byte, respectively:
TH0=15, TL0=255.
Seemingly, the results are valid, but the true state of registers at the moment of reading
was:
TH0=14, TL0=255.
This widely inaccurate reading (255 impulses) may happen due to not so obvious, yet
perfectly logical reason. Lower byte was read ok (255), but while the Program Counter
was "loading" your new instruction for reading TH0, overflow occurred, changing both
registers (TH0: 14 -> 15, TL0: 255 -> 0). Solution to the problem is simple: you need to
read the higher byte first, then the lower byte, and then the higher byte again. If two
readings of higher byte do not match, the sequence has to be repeated (this is a mini-loop
in the program, not more than 3 instructions).
There is also another solution: just turn off the Timer for the time of reading (clear the bit
TR0 in TCON), and turn it on afterwards.
Detection of Overflow
Usually, there is no need to continually read the Timer registers; it is sufficient to detect the
moment at which they are reset, the so-called Overflow. When it happens, bit TF0 in TCON will
be automatically set. This moment can be "awaited", by writing a small loop for testing the bit
continually, or by enabling an interrupt. Suppose that there is a need to suspend a program for
duration of 0.05 seconds (5000 cycles):
After that, when started (bit TR0 = 1), Timer will continue the counting up from our written
value. Now a program instruction can be used to test if the bit TF0 was set, which should take
place after exactly 50.000 cycles, i.e. 0.05 seconds.
Measuring time past between two events is a common task in electronics; for example, measuring
for how long has device been active. Note the bit named GATE0 (in TMOD Register) in the
Timer schematics. If this bit is cleared, pin P3.2 has no effect on the Timer. But, if GATE0 = 1,
Timer will work only for as long as the pin P3.2 is set. This means that, by bringing 5V externally
to this bit, simultaneously with turning the power on, Timer can measure the active period of the
device, which was the original idea.
Counting Impulses
The answer is in bit C/T0 in TCON Register. Similar to the previous example, C/T0 "brings in"
an external signal: if bit is cleared, Timer measures the time, i.e. impulses generated by MCU
clock. If bit is set, impulses from P3.4 (T0) are conducted to Timer's input. Having no
predetermined order or sequence, these impulses cannot be used for measuring time, effectively
turning the Timer into Counter. The highest frequency this Counter can record equals 1/24 of
frequency of used quartz-crystal.
Timer T1
This is the "twin brother" of Timer T0. It can fulfill same roles, it is also controlled by TMOD
and TCON, and has 4 different modes of work.
Timer T2
This is the third 16-bit timer/counter, installed only in newer MCU models. Unlike T0 and T1,
this timer comprises 4 registers. TH2 and TL2 are connected serially, forming a 16-bit counting
register. Other two registers, RCAP2H and RCAP2L are also conected serially, and their purpose
is to "capture" the contents of the counting register.
Main advantage of this organization lies in the fact that all reading and swapping takes place
concurrently by means of single instruction, with no need for programming acrobatics. T2, like its
older relatives, T0 and T1, has several different modes of work that will be explained in this
chapter.
Register T2CON contains Timer 2 control bits. Each of the bits is explained in the following
table:
Bit Role
TF2 This bit is automatically set on counter overflow (16-bit).
In order to register next overflow, bit needs to be cleared
from within a program. If bits RCLK or TCLK are set,
overflow has no effect on TF2.
EXF2 This bit is automatically set whenever impulse on pin
T2EX causes transfer from counter to buffer or vice versa.
If enabled, it generates interrupt, unless bit DCEN in
T2CON register is set. EXF2 is cleared from within a
program.
RCLK 1 - Receive rate of serial connection is determined by
Timer T2
0 - Stop Timer T2
C/T2 1 - 16-bit register (T2H and T2L) counts impulses on pin
C/T2
Modes of Timer T2
Capture mode
If bit CP/RL2 of T2CON register is set, timer T2 will operate according to the scheme presented
below. This is the so-called Capture mode in which value of the counter (comprises registers T2H
and T2L) can be "captured" and copied to the capture register (comprises registers RCAP2H and
RCAP2L). The transfer has no effect on the counting process.
1. 16-bit register (TH2+TL2) holds the number OD from which the counting starts.
2. Setting the bit TR2 in register TCON starts the timer; each incoming impulse increments
the value by 1. If both registers are full (decimal value of 65536), impulse causes
overflow, then reset, and counting starts from zero.
To set the Timer T2 to Auto Reload mode, you need to clear the bit CP/RL2. Then, Timer will be
able to count up or down from the designated value, depending on the bit DCEN in register
T2MOD:
TCEN - When set, it enables counting in either direction - "up" and "down"
Unlike Capture mode, here is value of the capture register (RCAP2H, RCAP2L) copied to the
counter (TH2, TL2) upon overflow. Settings of Auto Reload mode are shown in the following
table:
Everything previously stated on Timer T2 is in effect only if register T2MOD hasn't been
changed, i.e. if bit DCEN = 0. Otherwise, if this bit is set, timer (or counter) is enabled to count in
either direction. Direction depends on pin T2EX:
If counting down, overflow occurs when values of the counter and the buffer match. At that
moment, bit TF2 and all bits of T2H and T2L are set, while the counting goes on "from the top":
65535, 65534, 65533...
In either case, bit EXF2 is assigned a new role. Upon overflow, it inverts the signal and cannot be
used for generating interrupt anymore. Instead, EXF2 now serves as supplementary bit of the
counter, making the counter virtually 17-bit register!
If bits RCLK or TCLK (register TCON) are set, timer T2 turns into Baud Rate generator which
determines the transfer rate of serial communication. This mode is very similar to Auto-Reload,
with the rate of serial connection calculated according to the following formula:
In previous examples, pin P1.0 (marked as T2 in figures) served as an alternative clock generator
for this timer - i.e. it acted as input. It can be also used as output for generating sequence of
impulses. Using the 16MHz quartz crystal, frequency of generated impulses ranges from 61Hz to
4MHz, with impulse-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 equal to:
One of the things that makes this MCU so powerful is the hardware integrated UART, better
known as serial port. It is a duplex port capable of sending and receiving data simultaneously.
Without it, serial data transfer would be an endlessly complicated task, with numerous checks
performed at strictly defined pace. UART represents an elegant solution: programmer just needs
to set the mode and the rate of transfer. Register SBUF holds data to be sent to line, and the same
register accepts data from the line. Controller takes care of all the details of transfer with no room
for error.
Before using the serial port, it should be appropriately configured. SFR register SCON (Serial
Control) is in control of the transfer parameters: size of one serial "word" in bits, baud rate, and
the source of impulses for synchronization.
As shown in the table, combination of bits SM0 and SM1 determines the mode of work for serial
port:
Obviously, baud rate in modes 0 and 2 is fixed, and can be adjusted in modes 1 and 3 (details can
be found in the chapter on timers). In addition, baud rate in modes 1, 2, and 3 is doubled if bit
SMOD in register PCON is set (see below).
Mode 0
Mode 0 is not used for standard serial communication, but serves to provide additional I/O pins.
External shift registers convert the data into binary sequence, which is then serially transferred to
the controller. Although there is no limit on the number of I/O ports that can be gained in this
manner, the existing 32 I/O lines are sufficient for most of the tasks, making this mode rarely
used.
Mode 1
This is the standard RS-232 mode for serial transfer of 8-bit data. Sequence of ten bits is sent via
pin TXD or received via pin RXD in the following order: one start bit (always 0), followed by 8
data bits (LSB bit is first), and one stop bit (always 1). Start bit is not registered anywhere as its
sole purpose is to start the mechanism for receiving data. When data is received, stop bit is
automatically copied to bit RB8 in register SCON. In order to connect the controller to RS-232
line, this "raw" serial data needs to be inverted - this is carried out automatically by the
designated drivers.
Modes 2 and 3
These modes are frequently used for speedy transfers at short range (Mode 2) and for standard
RS-232 transfers with parity bit (Mode 3). Both modes transfer 9-bit data in the following order:
one start bit (always 0), followed by 8 data bits (LSB bit is first), 9th bit which is copied from the
bit TB8 before transfer, and to the bit RB8 after transfer, and finally one stop bit (always 1).
Once you have selected the mode of UART, you need to set the Baud Rate.
Baud Rate in modes 0 and 2 depends solely on the frequency of quartz crystal. Crystals designed
specifically for this purpose can be found in the market. Although their frequencies might seem a
bit exotic at first (e.g. 11.059 MHz), they produce standard rates for serial communication after
the clock has been divided by the controller.
Baud Rate in modes 1 and 3 is determined by timers T1 and/or T2. Timer T1 is most commonly
used in "Auto-Reload" mode (TMOD = 0010xxxx). In this case, rate is determined by the
frequency of overflow occurrence, and can be calculated according to the formula:
Here, bits which are automatically set upon overflow are of no use, and should be cleared to
avoid causing an interrupt.
If timer T2 is used for setting the Baud Rate, its bits will always have priority, allowing the
microcontroller to send and receive data at different rates:
Once UART is prepared for transfer, sending and receiving data is very simple. It all comes down
to simple writing and reading of register SBUF.
As soon as data is written to this port, MCU starts sending it, one bit at a time. At the end of the
sequence, bit TI in register SCON is set to indicate that one byte has been sent. Similar procedure
takes place when receiving data - after the bit RI (also in SCON) has been set, you just need to
read the register SBUF.
Watchdog timer relies on impulses from an independent internal RC oscillator. After reset and
during the so-called Power Down mode, this timer is disabled and has no effect on program
execution. Setting the bit WDTEN in register WMCON starts the Watchdog timer. In case of
normal behavior, program will manage to set the bit WDTRST (Watchdog Timer Reset, register
WMCON) on time, thus keeping the timer's doing unnoticed. Otherwise, if Watchdog manages to
count a full cycle, it indicates that the program went astray for some reason, and the timer will
reset the microcontroller. The trick is to include the instruction in the main program loop which
will unceasingly reset the Watchdog timer.
Several bits of register WMCON are in charge of this simple, yet efficient mechanism:
These 3 bits are in control of prescaler and determine the so-called nominal time of Watchdog
timer. If program does not set the bit WDTRST within nominal time, timer will reset the MCU.
EEMWE
When set, EEMWE enables writing to internal EEPROM memory. Upon writing, it needs to be
cleared from within the program.
EEMEN
When set, EEMEN allows access to external memory. When cleared, it allows access to internal
EEPROM
DPS
WDTRST (RDY/BSY)
This bit has twofold role. When set (from within a program), it will reset the Watchdog timer. Bit
is automatically cleared in the following machine cycle. When accessing internal EEPROM, it
behaves like a flag indicating the state of the controller:
WDTEN
This SFR register is in control of SPI. The following table describes individual bits of SPCR:
Bit Purpose
SPIE When set, this bit enables SPI interrupt
SPE When set, this bit turns on SPI system
DORD 1 - When sending data, Lsb bit goes first
0 - When sending data, Msb bit goes first
MSTR 1 - SPI system is selected as Master
0 - SPI system is selected as Slave
CPOL 1 - During waiting, state of pin SCK is high
0 - During waiting, state of pin SCK Master is low
CPHA Along with bit CPOL, CPHA determines the phase of clock signal of
Master device
SPR1 Combination of these two bits determines the frequency of clock signal of
SPR0 Master device (see table below)
Bit Purpose
SPIF Upon data transfer, this bit is automatically set. If enabled by means of bits
SPIE and ES, it will cause an interrupt.
WCOL Each accessing to register SPDR during SPI transmittal may cause an error
in transfer. If it occurs, this bit will be automatically set.
This is the register for storing data to be transferred via SPI. On writing data to SPDR (in Master
device), CPU automatically starts the clock generator, and the data appears in serial format on
controller pin MOSI. Upon sending an entire byte, bit SPIF is set to indicate the end of transfer. If
enabled by bits SPIE and ES, this will cause an interrupt.
Interrupts
AT89S8252 supports total of 6 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 configuring the register IE. Also, as shown in the figure below, whole
system of interrupts can be disabled by clearing the bit EA in the same register.
There is one not so obvious detail which requires an additional explanation, and it concerns the
external interrupts - INT0 and INT1. Namely, if bits IT0 and IT1 (in register TCON) are set,
program will be interrupted on change of pins from 1 to 0, i.e. on falling edge of the impulse. If
these two bits are cleared, same signal will trigger an interrupt, but in this case it will be
continually executed as long as the state on pins is low.
IE (Interrupt Enable)
Following table describes the bits of register IE
(same rule applies to all bits - logical state of 1 enables the appropriate interrupt):
Bit Purpose
EA Enables/disables all interrupt sources
ET2 Timer T2 interrupt
ES UART and SPI interrupts
ET1 Timer T1 interrupt
EX1 External interrupt: pin INT1
ET0 Timer T0 interrupt
EX0 External interrupt: pin INT0
Interrupt Priorities
It cannot be predicted with absolute certainty when will interrupt request take place. If multiple
interrupts are enabled, it's quite possible to have interrupt requests during execution of another
interrupt routine. In such cases, controller needs to resolve whether to proceed with the current
interrupt routine, or to enter a new one, based on a priority check. Our microcontroller can
differentiate between three priority levels:
1. Reset. If there is a request for reset, all processes are halted and the controller behaves as
if the power had just been turned on.
2. Priority 1 interrupts. Can be interrupted only by reset.
3. Priority 2 interrupts. Can be interrupted by any of above.
IP (Interrupt Priority)
SFR register IP determines the priority of existing interrupt sources
(Same rule applies to all bits : logical state of 1 assigns higher priority to the appropriate
interrupt):
Bit Purpose
PT2 Timer T2 interrupt priority
PS Serial port interrupt priority
PT1 Timer T1 interrupt priority
PX1 External interrupt INT1 priority
PT0 Timer T0 interrupt priority
PX0 External interrupt INT0 priority
If two interrupt requests collide, the one with higher priority has precedence in execution. If both
interrupts are of same priority, the one with the later request has to hold one and let the controller
handle the first one.
These addresses should hold the appropriate subroutines for handling the interrupts. In
practice, instead of actual routines, they only point to the location of appropriate routines in
the code.
4. Upon accomplishing the interrupt routine, address of the next instruction to be executed
is retrieved from the stack, and the program proceeds from the location where it was
interrupted.