Sei sulla pagina 1di 55

Chapter 1 : Introduction to microcontrollers

Introduction - It is all Faraday's fault

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.

What are microcontrollers and what are they for?

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.

How does microcontroller work


Although there are plenty of different microcontrollers and programs available, they all share a lot in
common between them. This means that if you master one model, you will be able to handle them all
eventually.

Typical scenario goes something like this:

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:

Read Only Memory (ROM)

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.

Random Access Memory (RAM)

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...

In case you forgot...

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).

In case you forgot...

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).

In case you forgot...

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.

In case you forgot...

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.

Power Supply Circuit

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.

Chapter 2 : Parts of the MCU

Introduction - 8051 Under The Magnifier

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:

4 kilobytes of ROM is neither too little nor too much.


128 bytes of RAM (SFR registers included) can satisfy the basic needs, but is not really
astounding.
4 ports totaling 32 I/O lines, are usually sufficient for connecting to the environs and are by
no means luxury.
Obviously, 8051 configuration is intended to satisfy the needs of programmers developing the
controlling devices and instruments. This is one part of its key to success: there is nothing missing,
yet there is no lavishness; it is meant for the average user. The other clue can be found in the
organization of RAM, Central Processor Unit (CPU), and ports - all of which maximally utilize the
available resources and allow further upgrades.

Pins On The Case

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+.

20: GND; Ground


21- 28: Port 2; If external memory is not present, pins of Port 2 act as universal input/output.
If external memory is present, this is the location of the higher address byte, i.e. addresses A8
– A15. It is important to note that in cases when not all the 8 bits are used for addressing the
memory (i.e. memory is smaller than 64kB), the rest of the unused bits are not available as
input/output.
29: PSEN; MCU activates this bit (brings to low state) upon each reading of byte (instruction)
from program memory. If external ROM is used for storing the program, PSEN is directly
connected to its control pins.
30: ALE; Before each reading of the external memory, MCU sends the lower byte of the
address register (addresses A0 – A7) to port P0 and activates the output ALE. External
register (74HCT373 or 74HCT375 circuits are common), memorizes the state of port P0 upon
receiving a signal from ALE pin, and uses it as part of the address for memory chip. During
the second part of the mechanical MCU cycle, signal on ALE is off, and port P0 is used as
Data Bus. In this way, by adding only one cheap integrated circuit, data from port can be
multiplexed and the port simultaneously used for transferring both addresses and data.
31: EA; Bringing this pin to the logical state zero (mass) designates the ports P2 and P3 for
transferring addresses regardless of the presence of the internal memory. This means that
even if there is a program loaded in the MCU it will not be executed, but the one from the
external ROM will be used instead. Conversely, bringing the pin to the high logical state
causes the controller to use both memories, first the internal, and then the external (if
present).
32-39: Port 0; Similar to Port 2, pins of Port 0 can be used as universal input/output, if
external memory is not used. If external memory is used, P0 behaves as address output (A0 –
A7) when ALE pin is at high logical level, or as data output (Data Bus) when ALE pin is at
low logical level.
40: VCC; Power +5V

Input – Output (I/O) Ports

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.

Memory Under The Magnifier

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 (Special Function Registers)

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.

MCU AT89S8252 ID Card

Member of 8051 family.


8KB of Flash memory for storing the program.
Program is loaded via SPI serial interface.
Program may be written/erased up to 1.000 times.
2KB of EEPROM memory for data storage.
Contents of EEPROM may be changed up to 100.000 times.
Power Supply: 4 - 6V.
Clock: 0 - 24MHz.
256 bytes of internal RAM for storing variables.
32 I/O lines.
Three 16-bit timers / counters.
9 interrupt sources.
2 additional low-consumption modes.
Programmable UART serial communication.
Programmable Watch Dog timer.

Pins on the casing:

VCC

Power Supply (4 - 6V).

GND

Negative supply pole (ground).

Port 0 (P0.0 - P0.7)

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.

Port 1 (P1.0 - P1.7)

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:

Pin Alternate function


P1.0 T2 (Timer 2 input)
P1.1 T2EX (Timer 2 control input)
P1.4 SS (SPI control input)
P1.5 MOSI (I/O of SPI system)
P1.6 MISO (I/O of SPI system)
P1.7 SCK (SPI clock signal)

Each of the functions will be explained in details later in the chapter.

Port 2 (P2.0 - P2.7)

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.

Port 3 (P3.0 - P3.7)

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.

Pin Alternate function


P3.0 RXD (Serial input)
P3.1 TXD (Serial output)
P3.2 INT0 (External interrupt 0)
P3.3 INT1 (External interrupt 1)
P3.4 T0 (Timer 0 external input)
P3.5 T1 (Timer 1 external input)
P3.6 WR (Signal write to external
memory)
P3.7 RD (Signal read from external
memory)

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.

SFR Registers (Special Function Registers)

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).

P0, P1, P2, P3 - I/O Ports

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.

Stack Pointer (SP)

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.

RS1 RS2 Location in RAM


0 0 Bank 0 00h-07h
0 1 Bank 1 08h-0Fh
1 0 Bank 2 10h-17h
1 1 Bank 3 18h-1Fh

F0 (bit 5) - Flag 0. An all-purpose flag.


AC (bit 6) - Auxiliary Carry Flag, used only for operations with BCD (Binary Coded
Decimals).
CY (bit 7) - Carry Flag. Auxiliary (ninth) bit for arithmetical and shift operations.

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.

Counters and Timers

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.

Formula for calculating the value of 16-bit register is simple:

TH0 * 256 + TL0 = T

On our previous example:

3 * 256 + 232 = 1000

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.

Two registers tightly connected to Timer T0 are TMOD and TCON.

TMOD - Timer Mode


This register sets mode for timers T0 and T1. As shown in the image below, lower 4 bits (bit 0 -
bit 3) are associated with T0, while the higher 4 bits (bit4 - bit7) are associated with T1.

The following table gives details on bits 0 - 7 :

Bit Bit Name Purpose Timer


7 GATE1 1 Timer works only if INT1 (P3.3) is set T1
0 Timer works regardless of INT1 (P3.3)
6 C/T1 1 Timer counts impulses on T1 (P3.5) T1
0 Timer counts impulses of internal oscillator
5 T1M1 Timer mode T1
4 T1M0 Timer mode T1
3 GATE0 1 Timer works only if INT0 (P3.2) is set T0
0 Timer works regardless of INT0 (P3.2)
2 C/T0 1 Timer counts impulses on T0 (P3.4) T0
0 Timer counts impulses of internal oscillator
1 T0M1 Timer mode T0
0 T0M0 Timer mode T0

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.

T0M1 T0M0 Mode Description


0 0 0 13-bit Timer
0 1 1 16-bit Timer
1 0 2 8-bit auto-reload
1 1 3 Split mode

Mode 0 (13-bit Timer)


This mode is an antiquity kept just for the sake of compatibility with older MCUs. When
activated, whole higher byte TH0 and only the first 5 bits of lower byte TL0 are accessible. Thus,
with Mode 0, Timer T0 uses only 13 of its 16 bits. How does it work? On each impulse, lower
register is changed (the "trimmed" one). When TL0 is filled after 32 impulses, it is automatically
reset, and TH0 is increased by one. This process repeats itself until 8192 impulses are registered,
upon which both registers are reset to zero.

Mode 1 (16-bit Timer)

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.

Mode 2 (8-bit "auto reload" Timer)


What is "auto reload" ? Simply, only one of two registers is used for counting; however, it does
not start from zero, but from a specified value stored in the other register (0-255).

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.

Mode 3 ("Split" Timer)

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.

TCON - Timer Control

TCON is another register in direct control of the timers.

Of the 8 bits, TCON uses only 4 bits for controlling the timers, while the other 4 are associated
with interrupts.

Bit Bit Name Purpose Timer


7 TF1 This bit is automatically set in T1
case of overflow in Timer T1
6 TR1 1 - Timer T1 is on T1
0 - Timer T1 is off
5 TF0 This bit is automatically set in T0
case of overflow in Timer T0
4 TR0 1 - Timer T0 is on T0
0 - Timer T0 is off

Starting Timer T0

Select this timer and set the desired mode.


This sets the Timer T0 to operate in Mode 1, and count the impulses of internal source with
frequency equal to 1/12 of the quartz oscillator's frequency.

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):

First, you need to calculate a number to be written to Timer registers:


This value should be stored to Timer registers TH0 and TL0:

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 Impulse Duration

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.

T2CON (Timer/Counter 2 Control Register)

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 - Receive rate of serial connection is determined by


Timer T1
TCLK 1 - Transmit rate of serial connection is determined by T2

0 - Transmit rate of serial connection is determined by T1


EXEN2 1 - Allow signal on pin T2EX to cause transfer between
counter and buffer

0 - Ignore logic state on pin T2EX


TR2 1 - Start Timer T2

0 - Stop Timer T2
C/T2 1 - 16-bit register (T2H and T2L) counts impulses on pin
C/T2

0 - 16-bit register (T2H and T2L) acts like a timer


CP/RL2 1 - If enabled, (bit EXEN=1) impulse on pin T2EX will
cause transfer from counter to buffer

0 - Under same condition, signal on pin T2EX will cause


transfer from buffer to counter

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.

How does it work?

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.

Register Bit Mode


0 - Upon overflow, counter is reset, and
bit TF2 in register T2CON is set. If
enabled, it can cause interrupt.

1 - Same as above, except now timer


"follows" the state on the pin T2 also. On
T2CON
EXEN2 change from 1 to 0 (falling edge of the
impulse), values currently in the registers
TH2 and TL2 are instantly copied to the
registers RCAP2H and RCAP2L,
respectively. In addition, bit EXF2 is set,
which can cause an interrupt. Transfer
between the registers has no effect on the
counting process.

0 - Counts the machine cycles (every


12th impulse of the quartz oscillator)
C/T2

1 - Counts the impulses brought to pin T2

Auto Reload Mode

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:

T2OE - Allows timer to act as independent clock

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:

Register Bit Mode


0 - Upon overflow, bit TF2 in register
T2CON is set. If enabled, it can cause
interrupt. At the same time, values stored
in registers RCAP2H and RCAP2L are
copied to the counter, and the counting
proceeds from this newly specified point

1 - Same as above, except now timer


EXEN2
"follows" the state on the pin T2 also. On
change from 1 to 0 (falling edge of the
T2CON
impulse), values currently in the registers
RCAP2H and RCAP2L are instantly
copied to the registers TH2 and TL2,
respectively. In addition, bit EXF2 is set,
which can also cause an interrupt.

0 - Counts the machine cycles (every


12th impulse of the quartz oscillator)
C/T2

1 - Counts the impulses brought to pin T2

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:

T2EX = 0: T2 counts down


T2EX = 1: T2 counts up
If counting up, situation is similar to the previously described mode, with one exception being the
bit EXF2, which attains a new role.

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!

Timer T2 as clock generator in serial communication

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:

Quartz oscillator frequency


Baud Rate =
32 * (65536 - (RCAP2H, RCAP2L))

Take into account that:


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 in this mode.
4. 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.

Timer T2 as independent clock generator

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:

Quartz oscillator frequency


Frequency =
4 * (65536 - (RCAP2H, RCAP2L))

UART (Universal Asynchronous Communication)

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.

SCON (Serial Port Control Register)

Bit Name Bit Address Purpose


SM0 9Fh Mode of work
SM1 9Eh Mode of work
SM2 9Dh Enables connecting multiple MCU's
REM 9Ch When set, enables receiving data
TB8 9Bh 9th bit for sending data in modes 2 and 3
RB8 9Ah 9th bit for sending data in modes 2 and 3
TI 99h Bit is automatically set when the whole byte is
sent
RI 98h Bit is automatically set when the whole byte is
received

As shown in the table, combination of bits SM0 and SM1 determines the mode of work for serial
port:

SM0 SM1 Mode Description Baud Rate


0 0 0 8-bit Shift register Quartz frequency / 12
0 1 1 8-bit UART Determined by timer T1 or T2
1 0 2 9-bit UART Quartz frequency / 32
1 1 3 9-bit UART Determined by timer T1 or T2

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).

Other bits of register SCON have following roles:


Bit Purpose
SM2 This bit is used if multiple microcontrollers exchange data using the same
line. Otherwise, it needs to be cleared to provide normal functioning of the
communication
REN Needs to be set to enable receiving data via serial communication
TB8 Auxiliary 9th bit in 9-bit transfer (modes 2 and 3)
RB8 Similar to TB8, but on receiving. When accepting 9-bit data, it stores value
of the ninth bit.
TI This bit is automatically set when the last bit of one byte has been
proceeded to the line. In this way, processor "knows" that the line is free
for sending another byte.
RI Similar to TI, but on receiving. It is a "doorbell" of a kind, which indicates
that one byte has been received, and that it should be read before another
one arrives.

Setting the Baud Rate

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:

Quartz oscillator frequency


Baud Rate =
384 * (256 - TH1)

If bit SMOD in register PCON is set, rate will be doubled:


Quartz oscillator frequency
Baud Rate =
192 * (256 - TH1)

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:

RCLK TCLK Mode of work


0 0 Rates of sending and receiving are equal and set by timer T1 only
0 1 Receiving rate is set by T1, sending rate is set by T2
1 0 Receiving rate is set by T2, sending rate is set by T1
1 1 Rates of sending and receiving are equal and set by timer T2 only

Sending and Receiving Data via UART

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 (WDT)

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:

PS2, PS1, PS0

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.

PS2 PS1 PS0 Mode of work


0 0 0 16 ms
0 0 1 32 ms
0 1 0 64 ms
0 1 1 128 ms
1 0 0 256 ms
1 0 1 512 ms
1 1 0 1024 ms
1 1 1 2048 ms

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

0 : Registers DP0L and DP0H are used as data pointer


1 : Registers DP1L and DP1H are used as data pointer

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:

0 : Writing in progress. Bit is automatically set afterwards


1 : Controller is ready for writing to EEPROM

WDTEN

0 : Disables the Watchdog timer


1 : Enables the Watchdog timer

SPI (Serial Peripheral Interface) System

SPI (Serial Peripheral Interface) provides a fast synchronous communication between


microcontroller and peripherals or between multiple microcontrollers. Connection is realized via
three wires, two of which are data lines, and third line serves for synchronization.
As shown in the figure above, one system is always considered primary in this type of
configuration - Master device, while the other is subordinate - Slave device. System is controlled
by means of three registers: SPCR (Control Register), SPSR (Status Register), and SPDR (Data
Register).

SPCR (SPI Control Register)

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)

SPR1 SPR0 SCK


0 0 Fosc. / 4
0 1 Fosc. / 16
1 0 Fosc. / 64
1 1 Fosc. / 128

SPSR (SPI Status Register)

This SFR register has two SPI related bits:

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.

SPDR (SPI Data Register)

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.

How does interrupt execute?

Upon receiving an interrupt request, following scenario takes place:

1. Current instruction is executed first.


2. Address of the instruction that would be executed next if there was no interrupt request is
put away to stack.
3. Depending on the interrupt in question, program counter will take value of one of
possible 6 vectors (addresses) according to the table below.

Interrupt source Vector (address in hex)


IE0 3h
TF0 Bh
IE1 13h
TF1 1Bh
RI, TI, SPIF 23h
TF2, EXF2 2Bh

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.

Potrebbero piacerti anche