Professional Documents
Culture Documents
Each of these applications will have a processing unit and special hardware to meet
the specific requirements of the application along with the embedded software that is
executed by the processor for meeting that specific requirement of the job. The embedded
software is also called as "firmware".
In contrast the desktop/ laptop computer is general purpose computer. We can use
it for a variety of applications such as playing games, word processing, accounting,
software development and so on. Where as the software in the embedded systems are
always fixed.
Note: A Microcontroller is a small CPU with many support devices built into the single
chip. Self Contained (CPU, RAM, ROM, I/O pins, timers, interrupt sources, serial port,
A/D and D/A interfaces etc). A microcontroller is designed such that for an application or
Task Specific (Not a general-purpose computer).
Microprocessor:
CPU is stand-alone, RAM, ROM, I/O, timer are separate.
Designer can decide on the amount of ROM, RAM and I/O ports.
Expansive.
Versatility.
General-purpose.
Microcontroller
CPU, RAM, ROM, I/O and timer are all on a single chip
Fix amount of on-chip ROM, RAM, I/O ports
For applications in which cost, power and space are critical
Single-purpose
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...etc
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.
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.
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, the 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...
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:
Register
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
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” whole” 800 ns.
Timers
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.
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.
Stack
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.
Derivative Chips
Intel wisely licensed their MCU core to other semiconductor firms. This allowed
the architecture to become an industry-wide standard. Now, more than 20 years later,
dozens of semiconductor companies produce microcontrollers that are based on the
original 8051 and 8052 core. The term derivative chip, will refer to any 8051 or 8052-
compatible MCU that is produced by any semiconductor firm. There are currently
hundreds of derivative chips produced by dozens of semiconductor firms. A derivative
chip will generally (but not always) be able to execute a standard 8051 or 8052 program
without modification.
Intel,
Atmel,
Philips,
Siemens,
Dallas,
National Semiconductors. etc
Block diagram and Pin configuration of 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+.
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
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.
Note: 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(pull up resistors).
Memory
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 also called as Data memory 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.
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.
As the name suggests, External RAM is any random access memory that is found
off-chip. Since the memory is off-chip the assembly language instructions to access it are
slower and less flexible. For example, to increment an Internal RAM location by 1
requires only 1 instruction and 1 instruction cycle. To increment a 1-byte value stored in
External RAM requires 4 instructions and 7 instruction cycles. In this case, external
memory is 7 times slower and requires 4 times as much program memory! What External
RAM loses in speed and flexibility it gains in quantity. While Internal RAM is normally
limited to 256 bytes in 8052 and 128 bytes with 8051s, the 8052 supports External RAM
and External ROM up to 64K bytes.
Programming Tip: Since memory is restricted to 64K, 8051 programs are limited to 64K.
Some compilers offer ways to get around this limit when used with specially wired
hardware and a technique known as memory banking. However, without such special
compilers and hardware, programs are limited to 64K.
Hardware Tip: Some manufacturers such as Dallas, Intel and Philips have special 8051
derivatives that can address several megabytes of 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.
Accumulator
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
The "B" register is very similar to the Accumulator in the sense that it may hold an 8-bit
(1-byte) value. The "B" register is only used implicitly by two 8052 instructions: MUL
AB and DIV AB. Thus, if you want to quickly and easily multiply or divide A by another
number, you may store the other number in "B" and make use of these two instructions.
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.
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 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.
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.
The Stack
The stack is a last in, first out (LIFO). Storage area that exists in Internal RAM. It is used
by the 8052 to store values that the user program manually pushes onto the stack as well
as to store the return addresses for CALLs and interrupt service routines (more on these
topics later). The stack is defined and controlled by a Special Function Register called the
Stack Pointer, or SP. SP, as a standard 8-bit SFR, holds a value between 0 and 255 that
represents the Internal RAM address of the end of the current stack. If a value is removed
from the stack, it will be taken from the Internal RAM address pointed to by SP and SP
will subsequently be decremented by 1. If a value is pushed onto the stack, SP will first
be incremented and then the value will be inserted in Internal RAM at the address now
pointed to by SP. SP is initialized to 07h when an 8052 is first booted. This means the
first value to be pushed onto the stack will be placed at Internal RAM address 08h (07h +
1), the second will be placed at 09h, etc.
Programming Tip: By default, the 8052 initializes the Stack Pointer (SP) to 07h when the
microcontroller is booted. This means that the stack will start at address 08h and expand
upwards. If you will be using the alternate register banks (banks 1, 2 or 3) you must
initialize the stack pointer to an address above the highest register bank you will be using,
otherwise the stack will overwrite your alternate register banks. Similarly, if you will be
using bit variables it is usually a good idea to initialize the stack pointer to some value
greater than 2Fh to guarantee that your bit variables are protected from the stack. We will
talk about the register banks and Bit Memory below.
ADD A,R4
Thus if the Accumulator (A) contained the value 6 and R4 contained the value 3, the
Accumulator would contain the value 9 after this instruction was executed. However, as
the memory map shows, the "R" Register R4 is really part of Internal RAM. Specifically,
R4 is address 04h of Internal RAM. This can be seen in the bright green section of the
memory map. Thus the above instruction accomplishes the same thing as the following
operation:
ADD A,04H
This instruction adds the value found in Internal RAM address 04h to the value of the
Accumulator, leaving the result in the Accumulator. Since R4 is really Internal RAM
address 04h, the above instruction effectively accomplishes the same thing as the
previous ADD instruction.
But watch out! As the memory map shows, the 8052 has four distinct register banks.
When the 8052 is first booted up register bank 0 (addresses 00h through 07h) is used by
default. However, your program
may instruct the 8052 to use one of the alternate register banks; i.e., register banks 1, 2, or
3. In this case, R4 will no longer be the same as Internal RAM address 04h. For example,
if your program instructs the 8052 to use register bank 1, register R4 will now be
synonymous with Internal RAM address 0Ch. If you select register bank 2, R4 is
synonymous with 14h, and if you select register bank 3 it is synonymous with address
1Ch. Setting or clearing the bits RS0 and RS1 in the Program Status Word (PSW) Special
Function Register selects the register bank. For example:
MOV PSW,#00H ; sets register bank 0
MOV PSW,#08H ; sets register bank 1
MOV PSW,#10H ; sets register bank 2
MOV PSW,#18H ; sets register bank 3
The above instructions will make more sense after we cover the topics of Special
Function Registers. The concept of register banks adds a great level of flexibility to the
8052, especially when dealing with interrupts (we'll talk about interrupts later). However,
always remember that the register banks really reside in the first 32 bytes of Internal
RAM.
Programming Tip: If you only use the first register bank (i.e. bank 0), you may use
Internal RAM locations 08h through 1Fh for your own use. If you plan to use register
banks 1, 2, or 3, be very careful about using addresses below 20h as you may end up
overwriting the value of "R" registers from other register banks.
Bit Memory
The 8052, being a communications and control-oriented microcontroller that often has to
deal with “ON” and “off” situations, gives the developer the ability to access a number of
bit variables directly with simple instructions to set, clear, and compare these bits. These
variables may be either 1 or 0. There are 128 bit variables available to the developer,
numbered 00h through 7Fh. The developer may make use of these variables with
commands such as SETB and CLR. For example, to set bit number 24h(hex) to 1 you
would execute the instruction:
SETB 24H
It is important to note that Bit Memory, like the Register Banks above, is really a part of
Internal RAM. Infact, the 128 bit variables occupy the 16 bytes of Internal RAM from
20h through 2Fh. Thus, if you write the value FFh to Internal RAM address 20h you’ve
effectively set bits 00h through 07h. That is to say that the instruction:
MOV 20H,#0FFH
SETB 00H
SETB 01H
SETB 02H
SETB 03H
SETB 04H
SETB 05H
SETB 06H
SETB 07H
As illustrated above, Bit Memory isn’t really a new type of memory. It’s really just a
subset of Internal RAM. Since the 8052 provide special instructions to access these 16
bytes of memory on a bit-by-bit basis it is useful to think of it as a separate type of
memory. But always keep in mind that it is just a subset of Internal RAM--and that
operations performed on Internal RAM can change the values of the bit variables.
Programming Tip: If your program does not use bit variables you may use Internal RAM
locations 20h through 2Fh for your own use. If you plan to use bit variables be very
careful about using addresses from 20h through 2Fh as you may end up overwriting the
value of your bits.
Programming Tip: By default, the 8052 initialize the Stack Pointer (SP) to 07h when the
microcontroller is booted. This means that the stack will start at address 08h and expand
upwards. If you will be using the alternate register banks (banks 1, 2 or 3) you must
initialize the stack pointer to an address above the highest register bank you will be using,
otherwise the stack will overwrite your alternate register banks. Similarly, if you will be
using bit variables it is usually a good idea to initialize the stack pointer to some value
greater than 2Fh to guarantee that your bit variables are protected from the stack.
While Bit Memory 00h through 7Fh are for developer-defined functions in their
programs, Bit Memory 80h and above are used to access certain SFRs (see below) on a
bit-by-bit basis. For example, if output lines P0.0 through P0.7 are all clear (0) and you
want to turn on the P0.1 output line you may either execute:
MOV P0,#02H
SETB 81H
Both of these instructions accomplish the same thing. However, using the SETB
command will turn on the P0.0 line without affecting the status of any of the other P0
output lines. The MOV command effectively turns off all the other output lines which, in
some cases, may not be acceptable. When dealing with bit addresses of 80h and above
remember that the bits refer to the bits of corresponding SFRs that are divisible by 8. This
is a complicated way of saying that bits 80h through 87h refer to bits 0 through 7 of SFR
80h. Bits 88h through 8Fh refer to bits 0 through 7 of SFR 88h. Bits 90h through 97F
refer to bits 0 through 7 of 90h, etc.
MOV 50H,#01H
Similarly, if you want to write the value "1" to the 8052.s serial port you would write this
value to the SBUF SFR, which has an SFR address of 99 Hex. Thus, to write the value
"1" to the serial port you would execute the instruction:
MOV 99H,#01H
As you can see, it appears as if the SFR is part of Internal Memory. This is not the case.
When using this method of memory access (it’s called. direct address. more on that
soon), any instruction that has an address of 00h through 7Fh refers to an Internal RAM
memory address; any instruction with an address of 80h through FFh refers to an SFR
control register.
Programming Tip #1: SFRs are used to control the way the 8052 functions. Each SFR has
a specific purpose and format that will be discussed later. Not all addresses above 80h are
assigned to SFRs. However, this area may NOT be used as additional RAM memory
even if a given address has not been assigned to an SFR.
Programming Tip #2: Since direct access to addresses 80h through FFh refers to SFRs,
direct access cannot be used to access Internal RAM addresses 80h through FFh. The
upper 128 bytes of Internal RAM must be accessed using. Indirect Addressing. Which
will be explained in a subsequent chapter.
SFRs are accessed as if they were normal Internal RAM. The only difference is that
Internal RAM is addressed in direct mode. with addresses 00h through 7Fh whereas SFR
registers are accessed in the range of 80h through FFh. Each SFR has an address (80h
through FFh) and a name. The following chart provides a graphical presentation of the
8052's SFRs, their names, and their address.
As you can see, although the address range of 80h through FFh offers 128 possible
addresses, there are only 26 SFRs in a standard 8052 (21 with an 8051). All other
addresses in the SFR range (80h through FFh) are considered invalid. Writing to or
reading from these registers may produce undefined values or behavior.
Programming Tip: It is recommended that you not read or write to SFR addresses that
have not been assigned to an SFR. Doing so may provoke undefined behavior and may
cause your program to be incompatible with other 8052-derivatives that use the given
SFR for some other purpose.
Immediate Addressing:
In this addressing mode, a constant value is specified in the instruction itself. The
“#” symbol precedes the constant values in the assembly instructions. The constants can
be decimal numbers, hexadecimal numbers, binary numbers or characters.
1. Hexadecimal numbers are written with “H” suffix (e.g. 3AH). Moreover, a
hexadecimal number must start with a digit. If not, put a leading 0. For example,
if the hexadecimal number that you want to specify is D3H, then you have to
write it in a program as 0D3H.
4. Characters must be written between double quotation marks (e.g. "Z"). Actually,
the ASCII code of the character is processed here.
Register Addressing:
The register banks, containing registers R0 through R7, can be accessed by certain
instructions that carry a 3-bit register specification within the opcode of the instruction.
Instructions that access the registers this way are code efficient, since this mode
eliminates an address byte. When the instruction is executed, one of the eight registers in
the selected bank is accessed.
In the latter example the address of the B register (F0) register is actually used in the
encoded form.
Indirect Addressing:
In indirect addressing the instruction specifies a register which contains the
address of the operand. Both internal and external data memory can be indirectly
addressed (SFRs are not indirectly addressed). The address register for 8-bit addresses
can only be R0 or R1 of the selected bank. The “@” symbol is used before the register is
to specify the indirect addressing mode in instructions. The address register for 16-bit
addresses can only be the 16-bit “data pointer” register, DPTR (this is not the case in
labs).
Example:
MOV A,@R0 ;move the content of internal data memory
location whose address is in register R0.
Q) Write an ALP to fill 10 successive locations Starting at 40h with decimal numbers 0
to 9.
Programming Tip: Technically, accessing external memory with the MOVX @DPTR
instruction is indirect addressing since the address to be accessed is referred to indirectly
by the DPTR register. However, to directly access a specific external RAM memory
location the most direct way is to load DPTR with the address in question and access it
with the MOVX instruction. Thus while this approach is technically "indirect," I called it
"External Direct" since it is the most direct method of accessing a specific external RAM
memory location and to differentiate it from the following addressing mode (External
Indirect) which is very similar to the "indirect addressing"
org 0000h
start: mov dptr,#MSG
mov r0,#40h
mov r2,#7
loop: clr a
movc a,@A+dptr
mov @r0,a
inc DPTR
inc r0
djnz r2,loop
nop
org 0200h
MSG: DB 'THUNDER'
We start with DPTR = 200H, and A = 0. The instruction “MOVC A,@A+DPTR” moves
the contents of ROM location 200H (200H + 0 = 200H ) to register A. Register A
contains the ASCII value for “T”. This is moved to 40H location. Next, the DPTR is
incremented to make DPTR = 201. Accumulator is set to 0 again to get contents of the
next ROM location 201H, which holds the ASCII value of “H” and it is moved into the
location 41H. After the program execution is completed we have the characters of the
string starting from 40H.
Definitions:
Instruction: Indicates the correct syntax for the given opcode.
OpCode: The operation code, in the range of 0x00 through 0xFF, that represents the
given instruction in machine code.
Bytes: The total number of bytes (including the opcode byte) that make up the
instruction.
Cycles: The number of machine cycles required to execute the instruction.
Some notations:
bitAddr: Bit address value (00-FF)
data8: Immediate 8-bit data value
data16: Immedate 16-bit data value
address16: 16-bit code address
direct: Direct address (IRAM 00-7F, SFR 80-FF)
relAddr: Relative address (-127 to +128 bytes)
The new value for the Program Counter is calculated by replacing the least-significant-
byte of the Program Counter with the second byte of the ACALL instruction, and
replacing bits 0-2 of the most-significantbyte of the Program Counter with bits 5-7 of the
opcode value. Bits 3-7 of the most-significant-byte of the Program Counter remain
unchaged. Since only 11 bits of the Program Counter are affected by ACALL, calls may
only be made to routines located within the same 2k block as the first byte that follows
ACALL.
JB . Jump if Bit Se t
Syntax: JB bitAddr,relAddr
JB branches to the address indicated by relAddr if the bit indicated by bitAddr is set. If
the bit is not set program execution continues with the instruction following the JB
instruction.
JBC . Jump if Bit Set and Clear Bit
Syntax: JBC bitAddr,relAddr
JBC will branch to the address indicated by relAddr if the bit indicated by bitAddr is set.
Before branching to relAddr the instruction will clear the indicated bit. If the bit is not set
program execution continues with the instruction following the JBC instruction and the
value of the bit is not changed.
JC . Jump if Carry Se t
Syntax: JC relAddr
JC will branch to the address indicated by relAddr if the Carry Bit is set. If the Carry Bit
is not set program execution continues with the instruction following the JC instruction.
NOTE: In the case of "MOV direct1,direct2 ", the operand bytes of the instruction are
stored in reverse order. That is, the instruction consisting of the bytes 85h, 20h, 50h
means "Move the contents of Internal RAM location 0x20 to Internal RAM location
0x50" whereas the opposite would be generally presumed.
NOP . No Operation
Syntax: NOP
NOP, as it.s name suggests, causes no operation to take place for one machine cycle.
NOP is generally used only for timing purposes. Absolutely no flags or registers are
affected.
ORL . Bitwise OR
Syntax: ORL operand1,operand2
ORL does a bitwise "OR" operation between operand1 and operand2, leaving the
resulting value in operand1. The value of operand2 is not affected. A logical "OR"
compares the bits of each operand and sets the corresponding bit in the resulting byte if
the bit was set in either of the original operands, otherwise the resulting bit is cleared.
POP "pops" the last value placed on the stack into the direct address specified. In other
words, POP will load direct with the value of the Internal RAM address pointed to by the
current Stack Pointer. The stack pointer is then decremented by 1.
NOTE #1: The address of direct must be an Internal RAM or SFR address. You cannot
POP directly into .R. registers, such as R0, R1, etc. To pop a value off the stack into R0,
for example, you must pop the value into the accumulator and then move the value of the
accumulator into R0. NOTE #2: When popping a value off the stack into the
Accumulator, you must code the instruction as POP ACC, not POP A. The latter is
invalid and will result in an error at assembletime.
NOTE #1: The address of direct must be an Internal RAM or SFR address. You cannot
PUSH directly from .R. registers, such as R0, R1, etc. To push a value onto the stack
from R0, for example, you must move R0 into the accumulator, then PUSH the value of
the accumulator onto the stack.
NOTE #2: When pushing a value from the accumulator onto the stack into the, you must
code the instruction as PUSH ACC, not PUSH A. The latter is invalid and will result in
an error at assemble-time.
Program Flow
When an 8052 is first initialized the PC SFR is reset to 0000h. The 8052 then begins to
execute instructions sequentially in memory unless a program instruction causes the PC
to be otherwise altered. There are various instructions that can modify the value of the
PC; specifically, conditional branching instructions, direct jumps and calls, and "returns"
from subroutines. Additionally, interrupts, when enabled, can cause the program flow to
deviate from its otherwise sequential scheme.
Conditional Branching
The 8052 contains a suite of instructions which, as a group, are referred to as "conditional
branching" instructions. These instructions cause program execution to follow a non-
sequential path if a certain condition is true. Take, for example, the JB instruction. This
instruction means "Jump if Bit Set." An example of the JB instruction might be:
In this case, the 8052 will analyze the contents of bit 45h. If the bit is set program
execution will jump immediately to the label HELLO, skipping the NOP instruction. If
the bit is not set the conditional branch fails and program execution continues, as usual,
with the NOP instruction that follows.
Conditional branching is the fundamental building block of program logic since all
"decisions" are accomplished by using conditional branching. Conditional branching can
be thought of as the "IF... THEN" structure in 8052 assembly language. An important
note worth mentioning about conditional branching is that the program may only branch
to instructions located within 128 bytes prior to or 127 bytes after the address that follows
the conditional branch instruction. This means that in the above example the label
HELLO must be within +/- 128 bytes of the memory address that contains the conditional
branching instruction.
Direct Jumps
While conditional branching is extremely important, it is often necessary to make a direct
branch to a given memory location without basing it on a given logical decision. This is
equivalent to saying "GOTO" in BASIC. In this case you want the program flow to
continue at a given memory address without considering any conditions. This is
accomplished in the 8052 using "Direct Jump and Call" instructions. s illustrated in the
last paragraph, this suite of instructions causes program flow to change unconditionally.
Consider the example:
The LJMP instruction in this example means "Long Jump." When the 8052 executes this
instruction the PC is loaded with the address of NEW_ADDRESS and program execution
continues sequentially from
there. The obvious difference between the Direct Jump and Call instructions and the
conditional branching is that with Direct Jumps and Calls program flow always changes.
With conditional branching program flow only
changes if a certain condition is true.
It is worth mentioning that, aside from LJMP, there are two other instructions that cause a
direct jump to occur: the SJMP and AJMP commands. Functionally, these two
commands perform the exact same
function as the LJMP command--that is to say, they always cause program flow to
continue at the address indicated by the command. However, these instructions differ
from LJMP in that they are not capable of jumping to any address. They both have
limitations as to the .range. of the jumps.
1. The SJMP command, like the conditional branching instructions, can only jump to an
address within +/- 128 bytes of the SJMP command.
2. The AJMP command can only jump to an address that is in the same 2k block of
memory as the AJMP command. That is to say, if the AJMP command is at code memory
location 650h, it can only do a jump to addresses 0000h through 07FFh (0 through 2047,
decimal).
You may ask yourself, "Why would I want to use the SJMP or AJMP command which
have restrictions as to how far they can jump if they do the same thing as the LJMP
command which can jump anywhere in memory?" The answer is simple: The LJMP
command requires three bytes of code memory whereas both the SJMP and AJMP
commands require only two. If you are developing an application that has memory
restrictions you can often save quite a bit of memory using the 2-byte AJMP/SJMP
instructions instead of the 3-byte instruction.
Direct Calls
Another operation that will be familiar to seasoned programmers is the LCALL
instruction. When the 8052 executes an LCALL instruction it immediately pushes the
current Program Counter onto the stack and then continues executing code at the address
indicated by the LCALL instruction.
Similar in format to the AJMP instruction that was described in the previous section, the
ACALL instruction provides a way to perform the equivalent of an "LCALL" with a 2-
byte instruction (instead of 3) as long as the target routine is within the same 2k block of
memory.
11,059,200 / 12 = 921,600
This means that the 8052 can execute 921,600 single-cycle instructions per second. Since
a large number of 8052 instructions are single-cycle instructions it is often considered
that the 8051 can execute roughly 1
million instructions per second (MIPS), although in reality it is less--and, depending on
the instructions being used, an estimate of about 600,000 instructions per second is more
realistic. For example, if you are using exclusively 2-cycle instructions you would find
that the 8052 executes
460,800 instructions per second. The traditional 8052 also has two really slow
instructions (MUL AB and DIV AB) that require a full 4 cycles to execute--if you were
to execute nothing but those instructions you.d find performance to be about 230,400
instructions per second. It is again important to emphasize that not all instructions
execute in the same amount of time. The fastest instructions require one instruction cycle
(12 clock cycles), many others require two instruction cycles (24 clock cycles), and the
two very slow math operations require four instruction cycles (48 clock cycles).
Since all the instructions require different amounts of time to execute, a very obvious
question comes to mind: How can one keep track of time in a time-critical application if
we have no reference to time in the outside world?
NOTE: Many derivative chips change instruction timing. For example, many optimized
versions of the 8052 execute instructions in 4 oscillator cycles instead of 12; such a chip
would be effectively 3 times faster than the 8052 when used with the same 11.0592 MHz
crystal.
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).
AT89S52 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.
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.
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.
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 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.
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.
Serial 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.
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).
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:
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.
Interrupts
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.
4. 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.
5. 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.
LCD Interfacing:
Frequently, an 8051 program must interact with the outside world using input and
output devices that communicate directly with a human being. One of the most common
devices attached to an 8051 is an LCD display. Some of the most common LCDs
connected to the 8051 are 16x2 and 20x2 displays. This means 16 characters per line by 2
lines and 20 characters per line by 2 lines, respectively.
The 44780 standard requires 3 control lines as well as either 4 or 8 I/O lines for the data
bus. The user may select whether the LCD is to operate with a 4-bit data bus or an 8-bit
data bus. If a 4-bit data bus is used, the LCD will require a total of 7 data lines (3 control
lines plus the 4 lines for the data bus). If an 8-bit data bus is used, the LCD will require a
total of 3 control lines plus the 8 lines for the data bus.
Pin
Symbol I/O Description
NO.
1 Vss -- Ground
2 Vcc -- +5V power supply
3 VEE -- Power supply to control contrast
RS=0 to select command register
4 RS I
RS=1to select data register
R/W=0 for write
5 R/W I
R/W=1 for read
6 E I/O Enable; H- L pulse
7 DBO I/O The 8-bit data bus
8 DB1 I/O The 8-bit data bus
9 DB2 I/O The 8-bit data bus
10 DB3 I/O The 8-bit data bus
11 DB4 I/O The 8-bit data bus
12 DB5 I/O The 8-bit data bus
13 DB6 I/O The 8-bit data bus
14 DB7 I/O The 8-bit data bus
The RS line is the "Register Select" line. When RS is low (0), the data is to be
treated as a command or special instruction (such as clear screen, position cursor, etc.).
When RS is high (1), the data being sent is text data which should be displayed on the
screen. For example, to display the letter "T" on the screen you have to set RS high.
The RW line is the "Read/Write" control line. When RW is low (0), the
information on the data bus is being written to the LCD. When RW is high (1), the
program is effectively querying (or reading) the LCD. Only one instruction ("Get LCD
status") is a read command. All others are write commands--so RW will almost always be
low.
The EN line is called "Enable." This control line is used to tell the LCD that you are
sending it data. To send data to the LCD, your program should first set this line high (1)
and then set the other two control lines and/or put data on the data bus. When the other
lines are completely ready, bring EN low (0) again. A high to low transition tells the
LCD to take the data currently found on the other control lines and on the data bus and to
treat it as a command. The high to pulse must be minimum of 450ns wide.
Finally, the data bus consists of 4 or 8 lines (depending on the mode of operation
selected by the user). In the case of an 8-bit data bus, the lines are referred to as DB0,
DB1, DB2, DB3, DB4, DB5, DB6, and DB7.
A sample schematic of how the LCD will be connected to the 8051 is as follows:
As you can see, we've established a 1-to-1 relation between a pin on the 8051 and a line
on the LCD. Thus as we write our assembly program to access the LCD, we are going to
equate constants to the 8051 ports so that we can refer to the lines by their names as
opposed to P0.1, P0.2, etc. Let's go ahead and write our initial equates:
Having established the above equates, we may now refer to our I/O lines by their name.
For example, to set the RW line high (1), we can execute the following instruction:
SETB RW
SETB RS
SETB EN
As we mentioned above, the EN line is used to tell the LCD that you are ready for it to
execute an instruction that you've prepared on the data bus and on the other control lines.
Note that the EN line must be raised/lowered before/after each instruction sent to the
LCD regardless of whether that instruction is read or write text or instruction. In short,
you must always manipulate EN when communicating with the LCD. EN is the LCD's
way of knowing that you are talking to it. If you don't raise/lower EN, the LCD doesn't
know you're talking to it on the other lines.
Thus, before we interact in any way with the LCD we will always bring the EN line high
with the following instruction:
SETB EN
And once we've finished setting up our instruction with the other control lines and data
bus lines, we'll always bring this line back low:
CLR EN
Programming Tip: The LCD interprets and executes our command at the instant the EN
line is brought low. If you never bring EN low, your instruction will never be executed.
Additionally, when you bring EN low and the LCD executes your instruction, it requires
a certain amount of time to execute the command. The time it requires to execute an
instruction depends on the instruction and the speed of the crystal which is attached.
While it is possible to write code that waits for a specific amount of time to allow the
LCD to execute instructions, this method of "waiting" is not very flexible. If the crystal
frequency is changed, the software will need to be modified. Additionally, if the LCD
itself is changed for another LCD which, although 44780 compatible, requires more time
to perform its operations, the program will not work until it is properly modified.
A more robust method of programming is to use the "Get LCD Status" command to
determine whether the LCD is still busy executing the last instruction received.
The "Get LCD Status" command will return to us two tidbits of information; the
information that is useful to us right now is found in DB7. In summary, when we issue
the "Get LCD Status" command the LCD will immediately raise DB7 if it's still busy
executing a command or lower DB7 to indicate that the LCD is no longer occupied. Thus
our program can query the LCD until DB7 goes low, indicating the LCD is no longer
busy. At that point we are free to continue and send the next command.
Since we will use this code every time we send an instruction to the LCD, it is useful to
make it a subroutine. Let's write the code:
Thus, our standard practice will be to send an instruction to the LCD and then call our
WAIT_LCD routine to wait until the instruction is completely executed by the LCD.
This will assure that our program gives the LCD the time it needs to execute instructions
and also makes our program compatible with any LCD, regardless of how fast or slow it
is.
Programming Tip: The above routine does the job of waiting for the LCD, but was it to
be used in a real application a very definite improvement would need to be made: as
written, if the LCD never becomes "not busy" the program will effectively "hang,"
waiting for DB7 to go low. If this never happens, the program will freeze. Of course, this
should never happen and won't happen when the hardware is working properly. But in a
real application it would be wise to put some kind of time limit on the delay--for
example, a maximum of 256 attempts to wait for the busy signal to go low. This would
guarantee that even if the LCD hardware fails, the program would not lock up.
Before you may really use the LCD, you must initialize and configure it. This is
accomplished by sending a number of initialization instructions to the LCD.
The first instruction we send must tell the LCD whether we'll be communicating with it
with an 8-bit or 4-bit data bus. We also select a 5x8 dot character font. These two options
are selected by sending the command 38h to the LCD as a command. As you will recall
from the last section, we mentioned that the RS line must be low if we are sending a
command to the LCD. Thus, to send this 38h command to the LCD we must execute the
following 8051 instructions:
Having executed this code the LCD will be fully initialized and ready for us to send
display data to it.
When the LCD is first initialized, the screen should automatically be cleared by the
44780 controller. However, it's always a good idea to do things yourself so that you can
be completely sure that the display is the way you want it. Thus, it's not a bad idea to
clear the screen as the very first operation after the LCD has been initialized.
An LCD command exists to accomplish this function. Not surprisingly, it is the command
01h. Since clearing the screen is a function we very likely will wish to call more than
once, it's a good idea to make it a subroutine:
How that we've written a "Clear Screen" routine, we may clear the LCD at any time by
simply executing an LCALL CLEAR_LCD.
Programming Tip: Executing the "Clear Screen" instruction on the LCD also positions
the cursor in the upper left-hand corner as we would expect.
Now we get to the real meat of what we're trying to do: All this effort is really so we can
display text on the LCD. Really, we're pretty much done.
Once again, writing text to the LCD is something we'll almost certainly want to do over
and over--so let's make it a subroutine.
The WRTDAT routine that we just wrote will send the character in the accumulator to
the LCD which will, in turn, display it. Thus to display text on the LCD all we need to do
is load the accumulator with the byte to display and make a call to this routine.
Now that we have all the component subroutines written, writing the classic "Hello
World" program--which displays the text "Hello World" on the LCD, is a relatively
trivial matter. Consider:
LCALL INIT_LCD
LCALL CLEAR_LCD
MOV A,#'H'
LCALL WRTDAT
MOV A,#'E'
LCALL WRTDAT
MOV A,#'L'
LCALL WRTDAT
MOV A,#'L'
LCALL WRTDAT
MOV A,#'O'
LCALL WRTDAT
MOV A,#'W'
LCALL WRTDAT
MOV A,#'O'
LCALL WRTDAT
MOV A,#'R'
LCALL WRTDAT
MOV A,#'L'
LCALL WRTDAT
MOV A,#'D'
LCALL WRTDAT
The above "Hello World" program should, when executed, initialize the LCD, clear the
LCD screen, and display "Hello World" in the upper left-hand corner of the display.
KEYPAD INTERFACING:
Note: But some times key press detected in the previous step could be due to noise or
transients so in order to be sure that it is key press we need to do key debounce
Key debounce involves giving a small delay of 20 ms and then checking again for a key
press,if we find a key press the second time also,we can be assured that we have a valid
key press,else we have to again go back to key scan mode.
MOTORS
When trying to move things with microcontrollers, there are basically three kinds of .
motors that are most useful: DC motors, servomotors, and stepper motors. Following is
a brief introduction to these three. More notes can be found all over the web, and in
many good electronics and robotics books.
Most all motors work on the electrical principle of induction. When you put electric
current through a wire, it generates a magnetic field around the wire. By placing a
charged coil of wire in an existing magnetic field (say, between two magnets), the coil
will be either attracted to one magnet and repelled by the other, or vice versa,
depending on the current flow. The higher the current, the greater the magnetic field,
and therefore the greater the attraction or repulsion. The coil is mounted on a spinning
shaft in the middle of the motor. As the coil is alternately attracted to one magnet and
repulsed by the other, it spins from one to the other, and we get circular motion.
All inductive loads (like motors, electromagnets, and solenoids) work on this same
principle: induce a magnetic field by putting current through a wire, use it to attract or
repulse a magnetic body. However, the principle works in reverse as well. When you
spin a wire in an existing magnetic field, the field induces a current in the wire. So if
you've got a motor spinning, and you turn it off, the fact that the motor's coil is
spinning in a magnetic field will generate a current in the wire for a brief amount of
time. This current comes back in the reverse direction of the current flow you
generated to run the motor. It's called blowback, or back voltage, and it can cause
damage to your electronics. Usually it's stopped by putting a diode in line with your
motor, to stop the back voltage.
Motor Characteristics
There are a few characteristics common to all motors that you should keep in mind
when looking for motors:
Voltage
The rated voltage of a motor is the voltage at which it operates at peak efficiency. Most
DC motors can be operated somewhat above or below their range, but it's best to plan
to operate them at their rated voltage. Dropping below rated voltage reduces the
motor's power, and operating above the rated voltage may burn the motor out. Plan on
the motor's top speed being at rated voltage, and slowest speed at no more than 50%
less than the rated voltage.
Current
Motors draw current depending on the load they're pulling. Usually more load means
more current. Every motor has a stall current, which is the current it draws when it's
stopped by an opposing force. This stall current is much greater than the running
current, or current that it draws under no load. Your power supply for a motor should
be able to handle the stall current with extra amperage to spare. Motors may draw near
the stall current for a brief period of time when starting up, to overcome their inertia.
Speed
Torque is the measure of a motor's pulling force. It's measured by the force a motor
can pull when the opposing force is attached to a shaft attached to its center rod. If the
shaft sticks out a foot from the motor's center, and the motor can pull one pound on
that shaft, the motor's torque is one foot-pound. Motor manufacturers haven't
standardized this measurement, so sometimes you will see it as ft.-lb., lb-ft., oz.-in, in.-
oz., g-cm (gram-centimeter), and any other weight to length variation you can think of.
Resistance
Often you'll see a motor rated in ohms. This just gives you the resistance that the
motor's coil offers. Using Ohm's Law (voltage = current x resistance), you can
calculate the motor's current draw if you know the rated voltage and the coil resistance.
The DC Motor .
The DC Motor is the simplest of the motors discussed here. It works on exactly the
principle discussed above. There are two terminals, and when you apply direct current
to one terminal and ground the other, the motor spins in one direction. When you apply
current to the other terminal and ground the first terminal, the motor spins in the
opposite direction. By switching the polarity of the terminals, you reverse the direction
of the motor. By varying the current supplied to the motor, you vary the speed of the
motor. Specific techniques for doing these tasks are discussed below.
DC motors are usually very fast, spinning at several thousand revolutions per minute
(RPM).
Gearhead motors are a subset of DC motors. They have a box on the top of the motors
containing a series of gears that slow the rotational speed of the motor down and
increase the torque. They are useful when you don't need a lot of speed, but you do
need power.
Servo motors are a variation on the gearhead motor coupled with a potentiometer to
give feedback on the motor's position. The gears of the gearbox on a servo are attached
to a potentiometer inside the case, and the pot is turned by the turning of the motor.
The pot is connected to a capacitor in a resistor-capacitor circuit (R-C), and by pulsing
this R-C circuit, you give the motor power to turn. When the motor turns, it changes
the resistance of the R-C circuit, which in turn feeds the motor again. By pulsing the
R-C circuit, you set the motor's position in a range from 0 to 180 degrees.
Servos have three wires to them, unlike most DC and gearhead motors, which have
two. The first two in a servo are power and ground, and the third is a digital control
line. This third line is used to set the position of a servo. Unlike other DC motors, you
do not have to reverse the polarity of a servo's power connections to reverse its
direction.
Hobby servos, the kind most often used in small physical computing projects, usually
take a pulse of between 1-2 ms every 18-20 ms. They rotate 0 to 180 degrees
depending on the pulsewidth. A pulse of 1 ms will turn the motor to 0 degrees; 2 ms
will turn it to 180 degrees. A servo needs to see a pulse every 18-20 ms even when it is
not turning, to keep it in its current position, so once you've moved the motor to a new
position, it's essential to keep pulsing it with the same pulsewidth to keep it there.
Stepper motors are different than regular DC motors in that they don't turn
continuously, but move in a series of steps. A stepper motor is a motor controlled by a
series of electromagnetic coils. The center shaft has a series of magnets mounted on it,
and the coils surrounding the shaft are alternately given current or not, creating
magnetic fields which repulse or attract the magnets on the shaft, causing the motor to
rotate.
This design allows for very precise control of the motor: by proper pulsing, it can be
turned in very accurate steps of set degree increments (for example, two-degree
increments, half-degree increments, etc.). They are used in printers, disk drives, and
other devices where precise positioning of the motor is necessary. Steppers usually
move much slower than DC motors, since there is an upper limit to how fast you can
step them (5-600 pulses per second, typically. However, unlike DC motors, steppers
often provide more torque at lower speeds. They can be very useful for moving a
precise distance. Furthermore, stepper motors have very high torque when stopped,
since the motor windings are holding the motor in place like a brake.
To control a stepper, it's necessary to create a stepper driver that will energize the coils
in the right order to make the motor move forward.
The first thing to do is to understand the wiring for a stepper motor. The most common
type is a unipolar stepper motor, with six wires and four coils (actually two coils
divided by center wires on each coil). To do this, take an ohmmeter to the wires and
measure the resistance from one wire to another. The outer wires for each coil will
have a definite resistance that is double the resistance between the inner wire and
either of the two outer wires, as follows in the diagram below:
e.g.: if the resistance between wires 1 and 2 is x Ohms, then that between 1 and 3 is 2x
Ohms. Remember, two wires that are not connected (e.g. 1 and 4, 5, or 6) have infinite
resistance, which should read as an error on your meter. When you put voltage across
two wires of a coil (e.g. 1 to 3, or 2 to 4), you should find that the motor is very
difficult to turn (don't force it, that's bad for the motor).
Like other motors, the stepper requires more power than a microcontroller can give it,
so you'll need a separate power supply for it. Ideally you'll know the voltage from the
manufacturer, but if not, get a variable DC power supply, apply the minimum voltage
(hopefully 1V or so), apply voltage across two wires of a coil (e.g. 1 to 3 or 4 to 6) and
slowly raise the voltage until the motor is difficult to turn. It is possible to damage a
motor this way, so don't go too far. Typical voltages for a stepper might be 5V, 9V,
12V, 24V.
Typically, you would drive the stepper by connecting the 4 phase wires to a good
power transistor or MOSFET,and the 2 common wires to the supply voltage, as
follows:
In this diagram, the transistors are TIP120 Darlington transistors. A convenient way to
do this is with a ULN2003 or ULN2004 Darlington transistor array from Allegro
Micro.
Once you have the motor stepping in one direction, stepping in the other direction is
simply a matter of doing the steps in reverse order. Knowing the position is a matter of
knowing how many degrees per step, and counting the steps and multiplying by that
many degrees. So for examples, if you have a 2-degree stepper, and it's turned 180
steps, then it's turned 2 x 180 degrees, or 360 degrees, or one full revolution.
Another advantage of stepper motors is the fact that their speed of rotation can be achieved almo
change the spinning
Stepper motor consists of a rotor - the permanent magnet that rotates inside, and stator - four c
west) that are part of the case, and which don't move. Rotor can be moved by sequentially applying
one or two coils at a time.
Unipolar motor should have five or six connections depending on the model. If the motor has six c
pictured above, you have to join pins 1 and 2 (red) together and connect them to a (+) 12-24V voltag
pins; a1 (yellow), b1 (black), a2 (orange), b2 (brown) should be connected to a driver (ULN2003) as s
Stepping Modes
There are several stepping modes that you can use to drive the stepper motor.
1. Single Stepping - the simplest mode turns one coil ON at a time. 48 pulses are needed to comp
Each pulse moves rotor by 7.5 degrees. The following sequence has to be repeated 12 times for mot
revolution.
2. High Torque Stepping - high power / precision mode turns ON two coils on at a time. 48 pulses
complete one revolution. Each pulse moves rotor by 7.5 degrees. The following sequence has to be r
for motor to complete one revolution.
3. Half Stepping - stepping is doubled and motor needs 96 pulses to complete one revolution. Each p
approximately 3.75 degrees. Notice the mix of single stepping mode (lighter green) and high torque
green).
In able to move the rotor you will need a driver. Driver is a circuit that applies a
voltage to any of the four stator coils. Driver can be built with IC such as ULN2003
(pictured on the circuit diagram), or four darlington transistors or four power
transistors such as 2N3055.
Controlling Stepper Motor with a Port pins:
Controlling DC Motors
There are two easily controllable parameters of a DC motor, direction and speed. To control the direction, the polarity of the motor
is reversed. To control the speed, the input voltage is varied using pulsewidth modulation.
Direction Control
To control a DC motor from a microcontroller, you use switching arrangement known as an H bridge. It looks like this:
When switches 1 and 4 are closed and 2 and 3 are open, voltage flows from the supply to 1 to the motor to 4 to ground. When 2
and 3 are closed and 1 and 4 are open, polarity is reversed, and voltage flows from the supply to 3 to the motor to 2 to ground.
An H-bridge can be built from transistors, so that a microcontroller can switch the motor, like this:
You can see that there are six transistors here; the outer two are used to switch the inner four, in pairs, so that the proper two
transistors always switch together. If you were using this circuit, you'd want to make sure that control pins 1 and 2 were always
reversed; when one is high, the other is low.
Although you can make your own H-bridges, it's usually easier to use a controller manufactured specifically for the job. A pre-
manufactured H-bridge chip will include diodes to protect the transistors from back voltage, sometimes a current sensing pin to
sense the current the motor is drawing, and much more. There are many motor drivers available from various electronics suppliers.
Look around to find one that suits your needs and price range.
Speed
A DC motor's speed is proportional to the supplied voltage. If the voltage drops too far, the motor won't get enough power to turn,
but within a certain range, usually 50% of the rated voltage, the motor will run at varying speeds. The most effective way to adjust
the speed is by using pulsewidth modulation. This means that you pulse the motor on and off at varying rates, to simulate a
voltage. Here are some examples of puleswidths and the voltages they would simulate:
When the time that the voltage is high (the duty cycle) is half the total time in question, the effective voltage is about half the total
voltage.
When the duty cycle is reduced to one quarter of the total time, the effective voltage is about one quarter of the total voltage.
As with direction, there are many controllers that will vary the speed of your motor, so if you don't want to delve into the timing
issues yourself, you can rely on products made for the job.
Introduction
This requires just seven LEDs (plus an eighth one for the decimal point, if
that is needed). A common technique is to use a shaped piece of translucent
plastic to operate as a specialized optical fiber, to distribute the light from the
LED evenly over a fixed bar shape. The seven bars are laid out as a squared-off
figure "8". The result is known as a seven-segment LED.
The illustration to the right shows the basic layout of the segments in a
seven-segment display. The segments themselves are identified with lower-case
letters "a" through "g," with segment "a" at the top and then counting
clockwise. Segment "g" is the center bar.
Most seven-segment digits also include a decimal point ("dp"), and some
also include an extra triangle to turn the decimal point into a comma. This
improves readability of large numbers on a calculator, for example. The
decimal point is shown here on the right, but some display units put it on the
left, or have a decimal point on each side.
In addition, most displays are actually slanted a bit, making them look as if
they were in italics. This arrangement allows us to turn one digit upside down
and place it next to another, so that the two decimal points look like a colon
between the two digits. The technique is commonly used in LED clock
displays.
Seven-segment displays can be packaged in a number of ways. Three typical
packages are shown above. On the left we see three small digits in a single 12-
pin DIP package. The individual digits are very small, so a clear plastic bubble
is molded over each digit to act as a magnifying lens. The sides of the end
bubbles are flattened so that additional packages of this type can be placed end-
to-end to create a display of as many digits as may be needed.
One limitation of the DIP package is that it cannot support larger digits. To
get larger displays for easy reading at a distance, it is necessary to change the
package size and shape. The package on the right above is larger than the other
two, and thus can display a digit that is significantly larger than will fit on a
standard DIP footprint. Even larger displays are also available; some digital
clocks sport digits that are two to five inches tall.
Schematic Diagram
As shown in the two schematic diagrams above, the LEDs in a seven-
segment display are not isolated from each other. Rather, either all of the
cathodes, or all of the anodes, are connected together into a common lead,
while the other end of each LED is individually available. This means fewer
electrical connections to the package, and also allows us to easily enable or
disable a particular digit by controlling the common lead. (In some cases, the
common connections are made to groups of LEDs, and the external wiring
must make the final connections between them. In other cases, the common
connection is made available at more than one location for convenience in
laying out printed circuit boards. When laying out circuits using such devices,
you simply need to take the specific connection details into account.)
CHIP SELECT (CS): Chip select is an active low input used to activate the ADC804
chip. To access the ADC804, this pin must be low.
READ (RD): This is an input signal and is active low. The ADC converts the analog
input to its binary equivalent and holds it an internal register. RD is used to get the
converted data out of the ADC804 chip. When CS=0, if a high to low pulse is applied to
the RD pin, the 8 bit digital output shows up at the D0-D7 data pins. The RD is referred
to as output enable.
WRITE (WR): This is an active low input used to inform the ADC804 to start
conversion process. If CS = 0 when WR makes a low to high transition, the ADC804
starts converting the analog input value of Vin to an 8 bit digital number. The amount of
time it takes to convert varies depending on the CLK IN and CLK R values. When the
conversion is completed , the INTR pin is forced low by the ADC804.
INTERRUPT (INTR):
This is an active low
output pin which indicates
the end of conversion. It
is a normally high pin
when the conversion is
finished; it goes low to
signal the MCU that the
converted data is ready to
be picked up. After INTR
goes low, we make CS =
0 and send a high to low
pulse to the RD pin to get
the data out of the
ADC804 chip.
CLK IN and CLK R: CLK IN is an input pin connected to an external clock source
when an external clock is used for timing. However, the 804 has an internal clock
generator. To use the internal clock generator of the ADC804, the CLK IN and CLK R
pins are connected to a capacitor and a resistor as shown in the figure. The clock
frequency is determined by the equation
f = 1/ 1.1RC
Vin(+) and Vin(-): These are the differential analog inputs where. Vin = Vin(+) – Vin(-).
Often the Vin(-) pin is connected to ground and the Vin(+) pin is used as the analog input
to be inverted to digital.
VCC and Vref: This is the +5v power supply. It is also used as a reference voltage when
the Vrer/2 input is open. Vref/2 is an input voltage used for the reference voltage. If this
pin pin is open( not connected ), the analog input voltage for the AD804 is in the range of
0 to 5v. However , there are many applications where the analog input applied to Vin
needs to be other than the 0 to 5V. For example, if the analog input range needs to be 0 to
4 volts. Vref/2 is connected to 2 volts.
D0 – D7: D0 – D7 are the digital data output pins. These are tri state buffered and the
converted data is accessed only when CS = 0 and RD is forced to low. To calculate the
output voltage, use the formula
Numerical Systems
Introduction
It was always difficult for people to accept the fact that some things differ from them or
their way of thinking. That is probably one of the reasons why numerical systems which
differ from a decimal are still hard to understand. Still, whether we want it or not, reality
is different. Decimal numerical system that people use in everyday life is so far behind
the binary system used by millions of computers around the world.
Each numerical system are based on some basis. With a decimal numerical system, that
basis is 10, with binary 2, and with a hexadecimal system 16. The value of each decimal
is determined by its position in relation to the whole number represented in the given
numerical system. The sum of values of each decimal gives the value of the whole
number. Binary and hexadecimal numerical systems are especially interesting for the
subject of this book. Beside these, we will also discuss a decimal system, in order to
compare it with the other two. Even though a decimal numerical system is a subject we
are well acquainted with, we will discuss it here because of its relatedness to other
numerical systems.
Decimal numerical system is defined by its basis 10 and decimal space that is counted
from right to left, and consists of numbers 0,1, 2, 3, 4, 5, 6, 7, 8, 9. That means that the
end right digit of the total sum is multiplied by 1, next one by 10, next by 100, etc.
Example:
Binary numerical system differs in many aspects from the decimal system we are used to
in our everyday lives. Its numerical basis is 2, and each number can have only two
values, '1' or '0'. Binary numerical system is used in computers and microcontrollers
because it is far more suitable for processing than a decimal system. Usually, binary
number consists of binary digits 8, 16 or 32, and it is not important in view of the
contents of our book to discuss why. It will be enough for now to adopt this information.
Example:
In order to understand the logic of binary numbers, we will consider an example. Let's
say that we have a small chest with four drawers, and that we need to tell someone to
bring something from one of the drawers to us. Nothing is more simple, we will say left
side, bottom (drawer), and the desired drawer is clearly defined. However, if we had to
do this without the use of instructions like left, right, beneath, above, etc., then we would
have a problem. There are many solution to this problem, but we should look for one that
is most beneficent and practical! Lets designate rows with A, and types with B. If A=1, it
refers to the upper row of drawers, and for A=0, bottom row. Similarly with columns,
B=1 represents the left column, and B=0, the right (next picture). Now it is already easier
to explain from which drawer we need something. We simply need to state one of the
four combinations: 00, 01, 10 or 11. This characteristic naming of each drawer
individually is nothing but binary numerical representation, or conversion of common
numbers from a decimal into binary form. In other words, references like "first, second,
third and fourth" are exchanged with "00,01, 10 and 11".
What remains is for us to get acquainted with logic that is used with binary numerical
system, or how to get a numerical value from a series of zeros and ones in a way we can
understand, of course. This procedure is called conversion from a binary to a decimal
number.
Example:
As you can see, converting a binary number into a decimal number is done by calculating
the expression on the left side. Depending on the position in a binary number, digits carry
different values which are multiplied by themselves, and by adding them we get a
decimal number we can understand. Let's further suppose that there are few marbles in
each of the drawers: 2 in the first one, 4 in the second drawer, 7 in the third and 3 in the
fourth drawer. Let's also say to the one who's opening the drawers to use binary
representation in answer. Under these conditions, question would be as follows: "How
many marbles are there in 01?", and the answer would be: "There are 100 marbles in 01."
It should be noted that both question and the answer are very clear even though we did
not use the standard terms. It should further be noted that for decimal numbers from 0 to
3 it is enough to have two binary digits, and that for all values above that we must add
new binary digits. So, for numbers from 0 to 7 it is enough to have three digits, for
numbers from 0 to 15, four, etc. Simply said, the biggest number that can be represented
by a binary digit is the one obtained when basis 2 is graded onto a number of binary
digits in a binary number and thus obtained number is decremented by one.
Example:
This means that it is possible to represent decimal numbers from 0 to 15 with 4 binary
digits, including numbers '0' and '15', or 16 different values.
Operations which exist in decimal numerical system also exist in a binary system. For
reasons of clarity and legibility, we will review addition and subtraction only in this
chapter.
Addition is done so that digits in the same numerical positions are added, similar to the
decimal numerical system. If both digits being added are zero, their sum remains zero,
and if they are '0' and '1', result is '1'. The sum of two ones gives two, in binary
representation it will be a zero, but with transferring '1' to a higher position that is added
to digits from that position.
Example:
We can check whether result is correct by transferring these number to decimal numerical
system and by performing addition in it. With a transfer we get a value 10 as the first
number, value 9 as the second, and value 19 as the sum. Thus we have proven that
operation was done correctly. Trouble comes when sum is greater than what can be
represented by a binary number with a given number of binary digits. Different solutions
can be applied then, one of which is expanding the number of binary digits in the sum as
in the previous example.
Subtraction, like addition is done on the same principle. The result of subtraction between
two zeros, or two ones remains a zero. When subtracting one from zero, we have to
borrow one from binary digit which has a higher value in the binary number.
Example:
By checking the result as we did with addition, when we translate these binary numbers
we get decimal numbers 10 and 9. Their difference corresponds to number 1 which is
what we get in subtraction.
Hexadecimal numerical system has a number 16 as its basis. Since the basis of a
numerical system is 16, there are 16 different digits that can be found in a hexadecimal
number. Those digits are "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F". Letters A, B, C, D,
E and F are nothing but values 10, 11, 12, 13, 14 and 15. They are introduced as a
replacement to make writing easier. As with a binary system, here too, we can determine
with same formula what is the biggest decimal number we can represent with a specific
number of hexadecimal digits.
Usually, hexadecimal number is written with a prefix "$" or "0x" ,or suffix"h" , to
emphasize the numerical system. Thus, number A37E would be written more correctly as
$A37E, 0xA37E, or A37Eh. In order to translate a hexadecimal number into a binary
numerical system it is not necessary to perform any calculation but simple exchange of
hexadecimal digits with binary digits. Since the maximum value of a hexadecimal
number is 15, that means that it is enough to use 4 binary digits for one hexadecimal
digit.
Example:
By checking, that is transferring both numbers into decimal numerical system, we get a
number 228 which proves the accuracy of our action.
Example:
Example:
We need to add corresponding number digits. If their sum is equal 16, write 0 and
transfer one to the next higher place. If their sum is greater than 16, write value above
and transfer 1 to the next higher digit.Eg. if sum is 19 (19=16+3) write 3 and transfer 1 to
the next higher place. By checking, we get 14891 as the first number, and second is
43457. Their sum is 58348, which is a number $E3EC when it is transferred into a
decimal numerical system. Subtraction is an identical process to those in previous two
numerical systems. If the number we are subtracting is smaller, we borrow from the next
place of higher value.
Example:
By checking this result, we get values 11590 for the first number and 5970 for the
second, where their difference is 5620, which corresponds to a number $15F4 after a
transfer into a decimal numerical system.
Conclusion
Binary numerical system is still the one that is most in use, decimal the one that's easiest
to understand, and a hexadecimal is somewhere between those two systems. It's easy
conversion to a binary numerical system and easy memorization make it, along with
binary and decimal systems, one of the most important numerical systems.
Glossary
Microcontroller
A processing unit with peripherals in one chip.
I/Opin
External microcontroller's connector pin which can be configured as input or
output. In most cases I/O pin enables a microcontroller to communicate,
control or read information.
Software
Information that microcontroller needs in order to be able to function.
Software can not have any errors if we want the program and a device to
function properly. Software can be written in different languages such as:
Basic, C, pascal or assembler. Physically, that is a file on computer disc.
Hardware
Microcontroller, memory, supply, signal circuits and all components
connected with microcontroller.The other way of viewing this (especially if
it's not working) is, that, hardware is something you can kick.
Simulator
Software package for PC which simulates the internal function of
microcontroller. It is ideal for checking software routines and all the parts of
the code which do not have over demanding connections with an outside
world. Options are installed to watch the code, movement around the
program back and forth step by step, and debugging.
ICE
ICE (In Circuit Emulator), internal emulator, very useful part of the
equipment which connects a PC instead of microcontroller on a device that
is being developed. It enables software to function on the PC computer, but
to appear as if a real microcontroller exists in the device. ICE enables you to
move through program in real time, to see what is going on in the
microcontroller and how it communicates with an outside world.
EPROM-emulator
EPROM Emulator is a device which does not emulate the entire
microcontroller like ICE emulator, but it only emulates its memory. It is
mostly used in microcontrollers that have external memory. By using it we
avoid constant erasing and writing of EPROM memory.
Assembler
Software package which translates source code into a code which
microcontroller can understand. It contains a section for discovering errors.
This part is used when we debug a program from errors made when program
was written.
HEX-file
This is a file made by assembler translator when translating a source file,
and has a form "understood" by microcontrollers. A continuation of the file
is usually Filename .HEX where the name HEX file comes from.
List-file
This is a file made by assembler translator and it contains all instructions
from source file with addresses and comments programmer has written. This
is a very useful file for keeping track of errors in the program. File extension
is LST which is where its name comes from.
Source-File
File written in the language understood by man and assembler translator. By
translating the source file, we get HEX and LIST files.
Debugging
Error made in writing a program, which error we are not aware of. Errors
can be quite simple such as typing errors, and quite complex such as
incorrect use of program language. Assembler will find most of these errors
and report them to '.LST' file. Other errors will need to be searched for by
trying it out and watching how device functions.
ROM,EPROM,EEPROM,FLASH,RAM
Types of memories we meet with microcontroller use. First one can not be
erased, what you write in it once, stays forever, and can not be erased. The
second is erasable with UV lamp. Third one can be erased electrically, using
voltage which microcontroller operates on. Fourth one is electrically
erasable, but unlike EEPROM memory it does not have such a great number
of cycles of writing and erasing at memory locations. Fifth one is fast, but it
does not hold back the contents as the previous when there is supply
shortage. Thus, program is not stored in it, but it serves for different
variables and inter-results.
Addressing
Determines and designates certain memory locations.
ASCII
Short for "American Standard Code for Information Interchange". It is
widely accepted type of coding where each number and letter have their
eight-bit code.
Carry
Transfer bit connected with arithmetic operations
Code
File, or section of a file which contains program instructions.
Flag
Bits from a status register. By their activation, programmer is informed
about certain actions. Program activates its response if necessary.
Programmer
Device which makes it possible to write software in microcontroller
memory, thus enabling the microcontroller to work independently. It
consists of the hardware section usually connected with one of the ports and
software section used on the computer as a program.
Von-Neumann Architecture
Harvard Architecture
Microcontrollers based on the Harvard Architecture have separate data bus and
an instruction bus. This allows execution to occur in parallel. As an instruction is being
"pre-fetched", the current instruction is executing on the data bus. Once the current
instruction is complete, the next instruction is ready to go. This pre-fetch theoretically
allows for much faster execution than Von-Neumann architecture, but there is some
added silicon complexity.
CISC
Almost all of today's microcontrollers are based on the CISC Complex Instruction
Set Computer) concept. The typical CISC microcontroller has well over 80 instructions,
many of them very powerful and very specialized for specific control tasks. It is quite
common for the instructions to all behave quite differently. Some might only operate on
certain address spaces or registers, and others might only recognize certain addressing
modes.
The advantage of the CISC architecture is that many of the instructions are macro-
like, allowing the programmer to use one instruction in place of many simpler
instructions.
RISC
The industry trend for microprocessor design is for Reduced Instruction Set
Computers (RISC) designs. This is beginning to spill over into the microcontroller
market. By implementing fewer instructions, the chip designed is able to dedicate some
of the precious silicon real-estate for performance enhancing features. The benefits of
RISC design simplicity are a smaller chip, smaller pin count, and very low power
consumption.
Simulators
A simulator runs your microcontroller program on a host machine (such as your PC).
You can step through the code to see exactly what is happening as the program runs.
Contents of registers or variables can be altered to change the way the program runs.
Eliminates the erase/burn/program EPROM cycle common in microcontroller program
development. You can work out ideas or learn about microcontrollers by experimenting
with small code fragments and watching on the screen what happens. A simulator can't
support real interrupts or devices, and usually runs much slower than the real device the
program is intended for.
Some manufacturers have a cross between a software simulator and the hardware
emulator - a hardware simulator. This is a piece of equipment that plugs into your
target, and the pins will toggle and react like they should - just MUCH slower.
Emulators
If you've got the money, this is the equipment you want to develop your system with
(yeah, that's right, a preposition at the end of a sentence!). A [usually] expensive piece
of hardware that even for the cheaper versions will run you at least $700. An emulator is
a sophisticated device that pretends that it is the microprocessor itself, while at the same
time capturing information. It provides full and total control over your target, while at
the same time not requiring any resources from the target. The emulator can either be a
stand alone device with its own display, or it can be interface to a PC.
An assembly/machine language program is fast and small. This is because you are in
complete charge of what goes into the program. Of course, if you write a slow, large,
stupid program, then it will run slowly, be too big, and be stupid.
Interpreters
An interpreter is a high level language translator that is closer to natural language.
The interpreter itself is a program that sits resident in the microcontroller. It executes a
program by reading each language statement one at a time and then doing what the
statement says to do. The two most popular interpreters for microcontrollers are BASIC
and FORTH.
Compilers
A compiler is a high level language translator that combines the programming ease
of an interpreter with greater speed. This is accomplished by translating the program (on
a host machine such as a desktop PC) directly into machine language. The machine
language program is then burned onto an EPROM or downloaded directly to the
microcontroller. The microcontroller then executes the translated program directly,
without having to interpret first.
The most popular microcontroller compilers are C and BASIC. PL/M, from Intel,
also has some popular support due to that company's extensive use of that language.
Fuzzy logic is not a complete design solution. It supplements rather than replaces
traditional event control and PID (proportional, integral, and derivate) control techniques.
Fuzzy logic relies on grade of membership and artificial intelligence techniques. It works
best when it is applied to non-linear systems with many inputs that cannot be easily
expressed in either mathematical equations used for PID control or IF-THEN
statements used for event control.
In an effort to change fuzzy logic from a "buzzword" (as it is in most parts of the
world) to a well established design method (as it is in Japan), most manufacturers of
microcontrollers have introduced fuzzy logic software. Most software generates code for
specific microcontrollers, while other generates C code which can be compiled for any
microcontroller.