Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 178

Architecture and programming of 8051 MCU's

TOC
Chapter 1

Chapter 2

Chapter 3

Chapter 4

Chapter 5

Chapter 6

Chapter 7

Chapter 3 : The 8051 Instruction Set

3.1 Types of instructions


3.2 Description of the 8051 instructions

Introduction
The process of writing program for the microcontroller mainly consists of giving instructions
(commands) in the specific order in which they should be executed in order to carry out a
specific task. As electronics cannot understand what for example an instruction if the push
button is pressed- turn the light on means, then a certain number of simpler and precisely
defined orders that decoder can recognise must be used. All commands are known as
INSTRUCTION SET. All microcontrollers compatibile with the 8051 have in total of 255
instructions, i.e. 255 different words available for program writing.
At first sight, it is imposing number of odd signs that must be known by heart. However, It is not
so complicated as it looks like. Many instructions are considered to be different, even though
they perform the same operation, so there are only 111 truly different commands. For example:
ADD A,R0, ADD A,R1, ... ADD A,R7 are instructions that perform the same operation (additon
of the accumulator and register). Since there are 8 such registers, each instruction is counted
separately. Taking into account that all instructions perform only 53 operations (addition,
subtraction, copy etc.) and most of them are rarely used in practice, there are actually 20-30
abbreviations to be learned, which is acceptable.

3.1 Types of instructions


Depending on operation they perform, all instructions are divided in several groups:

Arithmetic Instructions
Branch Instructions

Data Transfer Instructions

Logic Instructions

Bit-oriented Instructions

The first part of each instruction, called MNEMONIC refers to the operation an instruction
performs (copy, addition, logic operation etc.). Mnemonics are abbreviations of the name of
operation being executed. For example:

INC R1 - Means: Increment register R1 (increment register R1);


LJMP LAB5 - Means: Long Jump LAB5 (long jump to the address marked as

LAB5);

JNZ LOOP - Means: Jump if Not Zero LOOP (if the number in the accumulator is

not 0, jump to the address marked as LOOP);

The other part of instruction, called OPERAND is separated from mnemonic by at least one
whitespace and defines data being processed by instructions. Some of the instructions have no
operand, while some of them have one, two or three. If there is more than one operand in an
instruction, they are separated by a comma. For example:

RET - return from a subroutine;


JZ TEMP - if the number in the accumulator is not 0, jump to the address

marked as TEMP;

ADD A,R3 - add R3 and accumulator;

CJNE A,#20,LOOP - compare accumulator with 20. If they are not equal, jump

to the address marked as LOOP;

Arithmetic instructions
Arithmetic instructions perform several basic operations such as addition, subtraction, division,
multiplication etc. After execution, the result is stored in the first operand. For example:
ADD A,R1

- The result of addition (A+R1) will be stored in the accumulator.


Arithmetic Instructions

Mnemonic Description

Byt Cycl
e e

ADD A,Rn

Adds the register to the accumulator

ADD
A,direct

Adds the direct byte to the accumulator

ADD A,@Ri Adds the indirect RAM to the accumulator

ADD
A,#data

Adds the immediate data to the accumulator

ADDC A,Rn Adds the register to the accumulator with a carry flag 1

ADDC
A,direct

Adds the direct byte to the accumulator with a carry


flag

ADDC
A,@Ri

Adds the indirect RAM to the accumulator with a carry


1
flag

ADDC
A,#data

Adds the immediate data to the accumulator with a


carry flag

SUBB A,Rn

Subtracts the register from the accumulator with a


borrow

SUBB
A,direct

Subtracts the direct byte from the accumulator with a


2
borrow

SUBB
A,@Ri

Subtracts the indirect RAM from the accumulator with


1
a borrow

SUBB
A,#data

Subtracts the immediate data from the accumulator


with a borrow

INC A

Increments the accumulator by 1

INC Rn

Increments the register by 1

INC Rx

Increments the direct byte by 1

INC @Ri

Increments the indirect RAM by 1

DEC A

Decrements the accumulator by 1

DEC Rn

Decrements the register by 1

DEC Rx

Decrements the direct byte by 1

DEC @Ri

Decrements the indirect RAM by 1

INC DPTR

Increments the Data Pointer by 1

MUL AB

Multiplies A and B

DIV AB

Divides A by B

DA A

Decimal adjustment of the accumulator according to 1

BCD code

Branch Instructions
There are two kinds of branch instructions:
Unconditional jump instructions: upon their execution a jump to a new location from where the
program continues execution is executed.
Conditional jump instructions: a jump to a new program location is executed only if a specified
condition is met. Otherwise, the program normally proceeds with the next instruction.
Branch Instructions
Mnemonic

Description

Byt Cycl
e e

ACALL addr11 Absolute subroutine call

LCALL addr16 Long subroutine call

RET

Returns from subroutine

RETI

Returns from interrupt subroutine

AJMP addr11

Absolute jump

LJMP addr16

Long jump

SJMP rel

Short jump (from 128 to +127 locations relative to the


following instruction)

JC rel

Jump if carry flag is set. Short jump.

JNC rel

Jump if carry flag is not set. Short jump.

JB bit,rel

Jump if direct bit is set. Short jump.

JBC bit,rel

Jump if direct bit is set and clears bit. Short jump.

JMP @A+DPTR Jump indirect relative to the DPTR

JZ rel

Jump if the accumulator is zero. Short jump.

JNZ rel

Jump if the accumulator is not zero. Short jump.

CJNE
A,direct,rel

Compares direct byte to the accumulator and jumps if not


equal. Short jump.

CJNE
A,#data,rel

Compares immediate data to the accumulator and jumps if


3
not equal. Short jump.

CJNE
Rn,#data,rel

Compares immediate data to the register and jumps if not


equal. Short jump.

CJNE
Compares immediate data to indirect register and jumps if
@Ri,#data,rel not equal. Short jump.

DJNZ Rn,rel

Decrements register and jumps if not 0. Short jump.

DJNZ Rx,rel

Decrements direct byte and jump if not 0. Short jump.

NOP

No operation

Data Transfer Instructions


Data transfer instructions move the content of one register to another. The register the content of
which is moved remains unchanged. If they have the suffix X (MOVX), the data is exchanged
with external memory.
Data Transfer Instructions
Mnemonic

Description

Byt Cycl
e e

MOV A,Rn

Moves the register to the accumulator

MOV A,direct

Moves the direct byte to the accumulator

MOV A,@Ri

Moves the indirect RAM to the accumulator

MOV A,#data

Moves the immediate data to the accumulator

MOV Rn,A

Moves the accumulator to the register

MOV Rn,direct Moves the direct byte to the register

MOV Rn,#data Moves the immediate data to the register

MOV direct,A

MOV direct,Rn Moves the register to the direct byte

MOV
direct,direct

Moves the direct byte to the direct byte

MOV
direct,@Ri

Moves the indirect RAM to the direct byte

Moves the accumulator to the direct byte

MOV
direct,#data

Moves the immediate data to the direct byte

MOV @Ri,A

Moves the accumulator to the indirect RAM

MOV
@Ri,direct

Moves the direct byte to the indirect RAM

MOV
@Ri,#data

Moves the immediate data to the indirect RAM

MOV
DPTR,#data

Moves a 16-bit data to the data pointer

MOVC
A,@A+DPTR

Moves the code byte relative to the DPTR to the


accumulator (address=A+DPTR)

MOVC
A,@A+PC

Moves the code byte relative to the PC to the accumulator


(address=A+PC)

MOVX A,@Ri

Moves the external RAM (8-bit address) to the accumulator 1

3-10

MOVX
A,@DPTR

Moves the external RAM (16-bit address) to the accumulator 1

3-10

MOVX @Ri,A

Moves the accumulator to the external RAM (8-bit address) 1

4-11

MOVX
@DPTR,A

Moves the accumulator to the external RAM (16-bit address) 1

4-11

PUSH direct

Pushes the direct byte onto the stack

POP direct

Pops the direct byte from the stack/td>

XCH A,Rn

Exchanges the register with the accumulator

XCH A,direct

Exchanges the direct byte with the accumulator

XCH A,@Ri

Exchanges the indirect RAM with the accumulator

XCHD A,@Ri

Exchanges the low-order nibble indirect RAM with the


accumulator

Logic Instructions
Logic instructions perform logic operations upon corresponding bits of two registers. After
execution, the result is stored in the first operand.
Logic Instructions

Mnemonic

Description

Byt Cycl
e e

ANL A,Rn

AND register to accumulator

ANL A,direct

AND direct byte to accumulator

ANL A,@Ri

AND indirect RAM to accumulator

ANL A,#data

AND immediate data to accumulator

ANL direct,A

AND accumulator to direct byte

ANL
direct,#data

AND immediae data to direct register

ORL A,Rn

OR register to accumulator

ORL A,direct

OR direct byte to accumulator

ORL A,@Ri

OR indirect RAM to accumulator

ORL direct,A

OR accumulator to direct byte

ORL
direct,#data

OR immediate data to direct byte

XRL A,Rn

Exclusive OR register to accumulator

XRL A,direct

Exclusive OR direct byte to accumulator 2

XRL A,@Ri

Exclusive OR indirect RAM to


accumulator

XRL A,#data

Exclusive OR immediate data to


accumulator

XRL direct,A

Exclusive OR accumulator to direct byte 2

XORL
direct,#data

Exclusive OR immediate data to direct


byte

CLR A

Clears the accumulator

CPL A

Complements the accumulator (1=0,


0=1)

SWAP A

Swaps nibbles within the accumulator

RL A

Rotates bits in the accumulator left

RLC A

Rotates bits in the accumulator left


through carry

RR A

Rotates bits in the accumulator right

RRC A

Rotates bits in the accumulator right


through carry

Bit-oriented Instructions
Similar to logic instructions, bit-oriented instructions perform logic operations. The difference is
that these are performed upon single bits.
Bit-oriented Instructions
Mnemo
Description
nic

Byt Cycl
e e

CLR C

Clears the carry flag

CLR bit

Clears the direct bit

SETB C

Sets the carry flag

SETB bit Sets the direct bit

CPL C

Complements the carry flag

CPL bit

Complements the direct bit

ANL
C,/bit

AND complements of direct bit to the


2
carry flag

ORL
C,bit

OR direct bit to the carry flag

ORL
C,/bit

OR complements of direct bit to the


carry flag

MOV
C,bit

Moves the direct bit to the carry flag

MOV
bit,C

Moves the carry flag to the direct bit

ANL C,bit AND direct bit to the carry flag

3.2 Description of all 8051 instructions


Here is a list of the operands and their meanings:

A - accumulator;
Rn - is one of working registers (R0-R7) in the currently active RAM memory
bank;
Direct - is any 8-bit address register of RAM. It can be any general-purpose
register or a SFR (I/O port, control register etc.);

@Ri - is indirect internal or external RAM location addressed by register R0 or


R1;

#data - is an 8-bit constant included in instruction (0-255);

#data16 - is a 16-bit constant included as bytes 2 and 3 in instruction (065535);

addr16 - is a 16-bit address. May be anywhere within 64KB of program


memory;

addr11 - is an 11-bit address. May be within the same 2KB page of program
memory as the first byte of the following instruction;

rel - is the address of a close memory location (from -128 to +127 relative to
the first byte of the following instruction). On the basis of it, assembler
computes the value to add or subtract from the number currently stored in
the program counter;

bit - is any bit-addressable I/O pin, control or status bit; and

C - is carry flag of the status register (register PSW).

ACALL addr11 - Absolute subroutine call


addr11: Subroutine address
Description: Instruction unconditionally calls a subroutine located at the specified code address.
Therefore, the current address and the address of called subroutine must be within the same 2K
byte block of the program memory, starting from the first byte of the instruction following
ACALL.
Syntax: ACALL [subroutine name];
Bytes: 2 (instruction code, subroutine address);
STATUS register flags: No flags are affected.
EXAMPLE:

Before execution: PC=0123h


After execution: PC=0345h
ADD A,Rn - Adds the register Rn to the accumulator
A: accumulator
Rn: any R register (R0-R7)
Description: Instruction adds the register Rn (R0-R7) to the accumulator. After addition, the
result is stored in the accumulator.
Syntax: ADD A,Rn;
Byte: 1 (instruction code);
STATUS register flags: C, OV and AC;
EXAMPLE:

Before execution: A=2Eh (46 dec.) R4=12h (18 dec.)


After execution: A=40h (64 dec.) R4=12h
ADD A,@Ri - Adds the indirect RAM to the accumulator
A: accumulator
Ri: Register R0 or R1
Description: Instruction adds the indirect RAM to the accumulator. Address of indirect RAM is
stored in the Ri register (R0 or R1). After addition, the result is stored in the accumulator.
Syntax: ADD A,@Ri;
Byte: 1 (instruction code);
STATUS register flags: C, OV and AC;
EXAMPLE:

Register address: SUM = 4Fh R0=4Fh


Before execution: A= 16h (22 dec.) SUM= 33h (51 dec.)
After execution : A= 49h (73 dec.)
ADD A,direct - Adds the direct byte to the accumulator

A: accumulator
Direct: Arbitrary register with address 0 - 255 (0 - FFh)
Description: Instruction adds the direct byte to the accumulator. As it is direct addressing, the
direct can be any SFR or general-purpose register with address 0-7 Fh. The result is stored in the
accumulator.
Syntax: ADD A, register name;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: C, OV and AC;
EXAMPLE:

Before execution: SUM= 33h (51 dec.) A= 16h (22 dec.)


After execution: SUM= 33h (73 dec.) A= 49h (73 dec.)
ADDC A,Rn - Adds the register to the accumulator with a carry flag
A: accumulator
Rn: any R register (R0-R7)
Description: Instruction adds the accumulator with a carry flag and Rn register (R0-R7). After
addition, the result is stored in the accumulator.
Syntax: ADDC A,Rn;
Byte: 1 (instruction code);
STATUS register flags: C, OV and AC;
EXAMPLE:

Before execution: A= C3h (195 dec.) R0= AAh (170 dec.) C=1
After execution: A= 6Eh (110 dec.) AC=0, C=1, OV=1
ADD A,#data - Adds the immediate data to the accumulator
A: accumulator
Data: constant within 0-255 (0-FFh)
Description: Instruction adds data (0-255) to the accumulator. After addition, the result is stored
in the accumulator.
Syntax: ADD A,#data;
Bytes: 2 (instruction code, data);
STATUS register flags: C, OV and AC;
EXAMPLE:

Before execution: A= 16h (22 dec.)


After execution: A= 49h (73 dec.)
ADDC A,direct - Adds the direct byte to the acumulator with a carry flag
A: accumulator
Direct: arbitrary register with address 0-255 (0-FFh)

Description: Instruction adds the direct byte to the accumulator with a carry flag. As it is direct
addressing, the register can be any SFRs or general purpose register with address 0-7Fh (0127dec.). The result is stored in the accumulator.
Syntax: ADDC A, register address;
Bytes: 2 (instruction code, direct);
STATUS register flags: C, OV and AC;
EXAMPLE:

Before execution: A= C3h (195 dec.) TEMP = AAh (170 dec.) C=1
After execution: A= 6Eh (110 dec.) AC=0, C=1, OV=1
ADDC A,@Ri - Adds the indirect RAM to the accumulator with a carry flag
A: accumulator
Ri: Register R0 or R1
Description: Instruction adds the indirect RAM to the accumulator with a carry flag. RAM
address is stored in the Ri register (R0 or R1). After addition, the result is stored in the
accumulator.
Syntax: ADDC A,@Ri;
Byte: 1 (instruction code);
STATUS register flags: C, OV and AC;
EXAMPLE:

Register address: SUM = 4Fh R0=4Fh


Before execution: A= C3h (195 dec.) SUM = AAh (170 dec.) C=1
After execution: A= 6Eh (110 dec.) AC=0, C=1, OV=1
ADDC A,#data - Adds the immediate data to the accumulator with a carry flag
A: accumulator
Data: constant with address 0-255 (0-FFh)
Description: Instruction adds data (0-255) to the accumulator with a carry flag. After addition,
the result is stored in the accumulator.
Syntax: ADDC A,#data;
Bytes: 2 (instruction code, data);
STATUS register flags: C, OV and AC;
EXAMPLE:

Before execution: A= C3h (195 dec.) C=1


After execution: A= 6Dh (109 dec.) AC=0, C=1, OV=1
AJMP addr11 - Absoulte jump
addr11: Jump address
Description: Program continues execution after executing a jump to the specified address.
Similar to the ACALL instruction, the jump must be executed within the same 2K byte block of
program memory starting from the first byte of the instruction following AJMP.
Syntax: AJMP address (label);
Bytes: 2 (instruction code, jump address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: PC=0345h SP=07h


After execution: PC=0123h SP=09h
ANL A,Rn - AND register to the accumulator
A: accumulator
Rn: any R register (R0-R7)
Description: Instruction performs logic AND operation between the accumulator and Rn
register. The result is stored in the accumulator.
Syntax: ANL A,Rn;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: A= C3h (11000011 Bin.)


R5= 55h (01010101 Bin.)
After execution: A= 41h (01000001 Bin.)
ANL A,direct - AND direct byte to the accumulator
A: accumulator
Direct: arbitrary register with address 0 - 255 (0 - FFh)
Description: Instruction performs logic AND operation between the accumulator and drect
register. As it is direct addressing, the register can be any SFRs or general-purpose register with
address 0-7Fh (o-127 dec.). The result is stored in the accumulator.
Syntax: ANL A,direct;
Byte: 2 (instruction code, direct);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: A= C3h (11000011 Bin.)


MASK= 55h (01010101 Bin.)
After execution: A= 41h (01000001 Bin.)
ANL A,@Ri - AND indirect RAM to the accumulator
A: accumulator
Ri: Register R0 or R1
Description: Instruction performs logic AND operation between the accumulator and register. As
it is indirect addressing, the register address is stored in the Ri register (R0 or R1). The result is
stored in the accumulator.

Syntax: ANL A,@Ri;


Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Register address SUM = 4Fh R0=4Fh


Before execution: A= C3h (11000011 Bin.)
R0= 55h (01010101 Bin.)
After execution: A= 41h (01000001 Bin.)
ANL A,#data - AND immediate data to the accumulator
A: accumulator
Data: constant in the range of 0-255 (0-FFh)
Description: Instruction performs logic AND operation between the accumulator and data. The
result is stored in the accumulator.
Syntax: ANL A,#data;
Bytes: 2 (instruction code, data);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: A= C3h (11000011 Bin.)


After execution: A= 41h (01000001 Bin.)
ANL direct,A - AND accumulator to direct byte
Direct: arbitrary register with address 0-255 (0-FFh)
A: accumulator
Description: Instruction performs logic AND operation between direct byte and accumulator. As
it is direct addressing, the register can be any SFRs or general-purpose register with address 07Fh (0-127 dec.). The result is stored in the direct byte.
Syntax: ANL register address,A;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: No flags are affected.
EXAMPLE:

Before execution: A= C3h (11000011 Bin.)


MASK= 55h (01010101 Bin.)
After execution: MASK= 41h (01000001 Bin.)
ANL direct,#data - AND immediate data to direct byte

Direct: Arbitrary register with address 0 - 255 (0 - FFh)


Data: constant in the range between 0-255 (0-FFh)
Description: Instruction performs logic AND operation between direct byte and data. As it is
direct addressing, the register can be any SFRs or general-purpose register with address 0-7Fh
(0-127 dec.). The result is stored in the direct byte.
Syntax: ANL register address ,#data;
Bytes: 3 (instruction code, direct byte address, data);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: X= C3h (11000011 Bin.) MASK= 55h (01010101 Bin.) After execution:
MASK= 41h (01000001 Bin.)
ANL C,bit - AND direct bit to the carry flag
C: Carry flag
Bit: any bit of RAM
Description: Instruction performs logic AND operation between the direct bit and the carry flag.
bi C AND
C
t
bit
0 00
0 10
1 00
1 11

Syntax: ANL C, bit address;


Bytes: 2 (instruction code, bit address);
STATUS register flags: C;
EXAMPLE:

Before execution: ACC= 43h (01000011 Bin.)


C=1
After execution: ACC= 43h (01000011 Bin.)
C=0
ANL C,/bit - AND complements of direct bit to the carry flag
C: carry flag
Bit: any bit of RAM
Description: Instruction performs logic AND operation between inverted addressed bit and the
carry flag. The result is stored in the carry flag.
bi bi C AND
C
t t
bit
0 1 00
0 1 11
1 0 00
1 0 10

Syntax: ANL C,/[bit address];


Bytes: 2 (instruction code, bit address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: ACC= 43h (01000011 Bin.)


C=1
After execution: ACC= 43h (01000011 Bin.)
C=1
CJNE A,direct,rel - Compares direct byte to the accumulator and jumps if not equal
A: accumulator
Direct: arbitrary register with address 0-255 (0-FFh)
addr: jump address
Description: Instruction first compares the number in the accumulator with the directly
addressed byte. If they are equal, the program proceeds with execution. Otherwise, a jump to the
specified address will be executed. This is a short jump instruction, which means that the address
of a new location must be relatively near the current one (-128 to +127 locations relative to the
first following instruction).
Syntax: CJNE A,direct,[jump address];
Bytes: 3 (instruction code, direct byte address, jump address);
STATUS register flags: C;
EXAMPLE:

Before execution: PC=0145h A=27h


After execution: if MAX27: PC=0123h
If MAX=27: PC=0146h
CJNE A,#data,rel - Compares immediate data to the accumulator and jumps if not equal
A: accumulator
Data: constant in the range of 0-255 (0-FFh)
Description: Instruction first compares the number in the accumulator with the immediate data. If
they are equal, the program proceeds with execution. Otherwise, a jump to the specified address
will be executed. This is a short jump instruction, which means that the address of a new location
must be relatively near the current one (-128 to +127 locations relative to the first following
instruction).
Syntax: CJNE A,X,[jump address];
Bytes: 3 (instruction code, data, jump address);
STATUS register flags: C;
EXAMPLE:

Before execution: PC=0445h


After execution: If A33: PC=0423h
If A=33: PC=0446h
CJNE Rn,#data,rel - Compares immediate data to the register Rn and jumps if not equal
Rn: Any R register (R0-R7)
Data: Constant in the range of 0 - 255 (0-FFh)
addr: Jump address
Description: Instruction first compares immediate data to the register Rn. If they are equal, the
program proceeds with execution. Otherwise, a jump to the specified address will be executed.
This is a short jump instruction, which means that the address of a new location must be
relatively near the current one (-128 to + 127 locations relative to the first following instruction).
Syntax: CJNE Rn,data,[jump address];
Bytes: 3 (instruction code, data, jump address);
STATUS register flags: C;
EXAMPLE:

Before execution: PC=0345h


After execution: If R544h: PC=0323h
If R5=44h: PC=0346h
CJNE @Ri,#data,rel - Compares immediate data to indirectly addressed register and jumps if not
equal
Ri: Register R0 or R1
Data: Constant in the range of 0 - 255 (0-FFh)
Description: This instruction first compares immediate data to indirectly addressed register. If
they are equal, the program proceeds with execution. Otherwise, a jump to the specified address
in the program will be executed. This is a short jump instruction, which means that the address of
a new location must be relatively near the current one (-128 to +127 locations relative to the next
instruction).
Syntax: CJNE @Ri,data,[jump address];
Bytes: 3 (instruction code, data, jump address);
STATUS register flags: C;
EXAMPLE:

Before execution: Register Address SUM=F3h


PC=0345h R0=F3h
After execution: If SUM44h: PC=0323h
If SUM=44h: PC=0346h
CLR A - Clears the accumulator
A: accumulator
Description: Instruction clears the accumulator.
Syntax: CLR A;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected.
EXAMPLE:

After execution: A=0


CLR C - clears the carry flag
C: Carry flag
Description: Instruction clears the carry flag.
Syntax: CLR C;
Byte: 1 (instruction code);
STATUS register flags: C;
EXAMPLE:

After execution: C=0


CLR bit - clears the direct bit
Bit: any bit of RAM
Description: Instruction clears the specified bit.

Syntax: CLR [bit address];


Bytes: 2 (instruction code, bit address);
STATUS register flags: No flags are affected.
EXAMPLE:

Before execution: P0.3=1 (input pin)


After execution: P0.3=0 (output pin)
CPL A - Complements the accumulator
A: accumulator
Description: Instruction complements all the bits in the accumulator (1==>0, 0==>1).
Syntax: CPL A;
Bytes: 1 (instruction code);
STATUS register flags: No flags are affected.
EXAMPLE:

Before execution: A= (00110110)


After execution: A= (11001001)
CPL bit - Complements the direct bit

Bit: any bit of RAM


Description: Instruction coplements the specified bit of RAM (0==>1, 1==>0).
Syntax: CPL [bit address];
Bytes: 2 (instruction code, bit address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: P0.3=1 (input pin)


After execution: P0.3=0 (output pin)
CPL C - Complements the carry flag
C: Carry flag
Description: Instruction complements the carry flag (0==>1, 1==>0).
Syntax: CPL C;
Byte: 1 (instruction code);
STATUS register flags: C;
EXAMPLE:

Before execution: C=1


After execution: C=0
DA A - Decimal adjust accumulator
A: accumulator
Description: Instruction adjusts the contents of the accumulator to correspond to a BCD number
after two BCD numbers have been added by the ADD and ADDC instructions. The result in form
of two 4-digit BCD numbers is stored in the accumulator.
Syntax: DA A;
Byte: 1 (instruction code);
STATUS register flags: C;
EXAMPLE:

Before execution: A=56h (01010110) 56 BCD


B=67h (01100111) 67BCD
After execution: A=BDh (10111101)
After BCD conversion: A=23h (00100011), C=1 (Overflow)
(C+23=123) = 56+67
DEC A - Decrements the accumulator by 1
A: accumulator
Description: Instruction decrements the value in the accumulator by 1. If there is a 0 in the
accumulator, the result of the operation is FFh. (255 dec.)
Syntax: DEC A;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: A=E4h


After execution: A=E3h
DEC Rn - Decrements the register Rn by 1
Rn: any R register (R0-R7)
Description: Instruction decrements the value in the Rn register by 1. If there is a 0 in the
register, the result of the operation will be FFh. (255 dec.)
Syntax: DEC Rn;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: R3=B0h


After execution: R3=AFh
DEC direct - Decrements the direct byte by 1
Direct: arbitrary register with address 0-255 (0-FFh)

Description: Instruction decrements the value of directly addressed register by 1. As it is direct


addressing, the register must be within the first 255 locations of RAM. If there is a 0 in the
register, the result will be FFh.
Syntax: DEC [register address];
Byte: 2 (instruction code, direct);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: CNT=0


After execution: CNT=FFh
DIV AB - Divides the accumulator by the register B
A: accumulator
B: Register B
Description: Instruction divides the value in the accumulator by the value in the B register. After
division the integer part of result is stored in the accumulator while the register contains the
remainder. In case of dividing by 1, the flag OV is set and the result of division is unpredictable.
The 8-bit quotient is stored in the accumulator and the 8-bit remainder is stored in the B register.
Syntax: DIV AB;
Byte: 1 (instruction code);
STATUS register flags: C, OV;
EXAMPLE:

Before execution: A=FBh (251dec.) B=12h (18 dec.)


After execution: A=0Dh (13dec.) B=11h (17dec.)
1318 + 17 =251
DEC @Ri - Decrements the indirect RAM by 1
Ri: Register R0 or R1
Description: This instruction decrements the value in the indirectly addressed register of RAM
by 1. The register address is stored in the Ri register (R0 or R1). If there is a 0 in the register, the
result will be FFh.
Syntax: DEC @Ri;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Register Address CNT = 4Fh R0=4Fh


Before execution: CNT=35h
After execution: CNT= 34h
DJNZ direct,rel - Decrements direct byte by 1 and jumps if not 0
Direct: arbitrary register with address 0-255 (0-FFh)
addr: Jump address

Description: This instruction first decrements value in the register. If the result is 0, the program
proceeds with execution. Otherwise, a jump to the specified address in the program will be
executed. As it is direct addressing, the register must be within the first 255 locations of RAM.
This is a short jump instruction, which means that the address of a new location must be
relatively near the current one (-128 to +127 locations relative to the first following instruction).
Syntax: DJNZ direct,[jump address];
Bytes: 3 (instruction code, direct, jump address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: PC=0445h


After execution: If CNT0: PC=0423h
If CNT=0: PC=0446h
DJNZ Rn,rel - Decrements the Rn register by 1 and jumps if not 0
Rn: any R register (R0-R7)
addr: jump address
Description: This instruction first decrements the value in the Rn register. If the result is 0, the
program proceeds with execution. Otherwise, a jump to the specified address in the program will

be executed. This is a short jump instruction, which means that the address of a new location
must be relatively near the current one (- 128 to +127 locations relative to the first following
instruction).
Syntax: DJNZ Rn, [jump address];
Bytes: 2 (instruction code, jump address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: PC=0445h


After execution: If R10: PC=0423h
If R1=0: PC=0446h
INC Rn - Increments the Rn register by 1
Rn: any R register (R0-R7)
Description: Instruction increments the value in the Rn register by 1. If the register includes the
number 255, the result of the operation will be 0.
Syntax: INC Rn;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: R4=18h


After execution: R4=19h
INC A - Increments the accumulator by 1
A: accumulator
Description: This instruction increments the value in the accumulator by 1. If the accumulator
includes the number 255, the result of the operation will be 0.
Syntax: INC A;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: A=E4h


After execution: A=E5h
INC @Ri - Increments the value of indirectly addressed register of RAM by 1
Ri: Register R0 or R1

Description: This instruction increments the value in the directly addressed register of RAM by
1. The register address is stored in the Ri Register (R0 or R1). If the register includes the number
255, the result of the operation will be 0.
Syntax: INC @Ri;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Register Address CNT = 4Fh


Before execution: CNT=35h R1=4Fh
After execution: CNT=36h
INC direct - Increments the direct byte by 1
Direct: arbitrary register with address 0-255 (0-FFh)
Description: Instruction increments the direct byte by 1. If the register includes the number 255,
the result of the operation will be 0. As it is direct addressing, the register must be within the first
255 RAM locations.
Syntax: INC direct;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: CNT=33h


After execution: CNT=34h
JB bit,rel - Jump if direct bit is set
addr: Jump address
Bit: any bit of RAM
Description: If the bit is set, a jump to the specified address will be executed. Otherwise, if the
value of bit is 0, the program proceeds with the next instruction. This is a short jump instruction,
which means that the address of a new location must be relatively near the current one (-128 to +
127 locations relative to the first following instruction).
Syntax: JB bit, [jump address];
Bytes: 3 (instruction code, bit address, jump address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: PC=0323h


After execution: If P0.5=0: PC=0324h
If P0.5=1: PC=0345h
INC DPTR - Increments the Data Pointer by 1
DPTR: Data Pointer
Description: Instruction increments the value of the 16-bit data pointer by 1. This is the only 16bit register upon which this operation can be performed.
Syntax: INC DPTR;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: DPTR = 13FF (DPH = 13h DPL = FFh )


After execution: DPTR = 1400 (DPH = 14h DPL = 0)
JC rel - Jump if carry flag is set
addr: Jump address
Description: Instruction first checks if the carry flag is set. If set, a jump to the specified address
is executed. Otherwise, the program proceeds with the next instruction. This is a short jump
instruction, which means that the address of a new location must be relatively near the current
one (-129 to + 127 locations relative to the first following instruction).
Syntax: JC [jump address];
Bytes: 2 (instruction code, jump value);
STATUS register flags: No flags are affected;
EXAMPLE:

Before instruction: PC=0323h


After instruction: If C=0: PC=0324h
If C=1: PC=0345h
JBC bit,rel - Jump if direct bit is set
Bit: any bit of RAM
addr: Jump Address

Description: This instruction first checks if the bit is set. If set, a jump to the specified address is
executed and the bit is cleared. Otherwise, the program proceeds with the first following
instruction. This is a short jump instruction, which means that the address of a new location must
be relatively near the current one (-129 to + 127 locations relative to the first following
instruction).
Syntax: JBC bit, [jump address];
Bytes: 3 (instruction code, bit address, jump address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: PC=0323h


After execution: If TEST0.4=1: PC=0345h, TEST0.4=0
If TEST0.4=0: PC=0324h, TEST0,4=0
JNB bit,rel - Jump if direct bit is not set
addr: Jump address
Bit: any bit of RAM
Description: If the bit is cleared, a jump to the specified address will be executed. Otherwise, if
the bit value is 1, the program proceeds with the first following instruction. This is a short jump
instruction, which means that the address of a new location must be relatively near the current
one (-129 to + 127 locations relative to the first following instruction).

Syntax: JNB bit,[jump address];


Bytes: 3 (instruction code, bit address, jump address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: PC=0323h


After execution: If P0.5=1: PC=0324h
If P0.5=0: PC=0345h
JMP @A+DPTR - Jump indirect relative to the DPTR
A: accumulator
DPTR: Data Pointer
Description: This instruction causes a jump to the address calculated by adding value stored in
the accumulator to the 16-bit number in the DPTR Register. It is used with complex program
branching where the accumulator affects jump address, for example when reading a table.
Neither accumulator nor DPTR register are affected.
Syntax: JMP @A+DPTR;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: PC=223 DPTR=1400h


After execution: PC = 1402h if A=2
PC = 1404h if A=4
PC = 1406h if A=6
Note:
As instructions AJMP LABELS occupy two locations each, the values in the accumulator
specifying them must be different from each other by 2.
JNZ rel - Jump if accumulator is not zero
addr: Jump Address
Description: This instruction checks if the value stored in the accumulator is 0. If not, a jump to
the specified address will be executed. Otherwise, the program proceeds with the first following
instruction. This is a short jump instruction, which means that the address of a new location must
be relatively near the current one (-129 to + 127 locations relative to the first following
instruction).
Syntax: JNZ [jump address]:
Bytes: 2 (instruction code, jump value);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: PC=0323h


After execution: If A=0: PC=324h
If A0: PC=283h
JNC rel - Jump if carry flag is not set
addr: Jump Address
Description: This instruction first checks whether the carry flag is set. If not, a jump to the
specified address will be executed. Otherwise, the program proceeds with the first following
instruction. This is a short jump instruction, which means that the address of a new location must
be relatively near the current one (-129 to + 127 locations relative to the first following
instruction).
Syntax: JNC [jump address];
Bytes: 2 (instruction code, jump value);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: PC=0323h


After execution: If C=0: PC=360h
If C=1: PC=324h
LCALL addr16 - Long subroutine call
addr16: Subroutine Address
Description: This instruction unconditionally calls a subroutine located at the specified address.
The current address and the start of the subroutine called can be located anywhere within the
memory space of 64K.
Syntax: LCALL [subroutine name];
Bytes: 3 (instruction code, address (15-8), address (7-0));
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: PC=0123h


After execution: PC=1234h
JZ rel - Jump if accumulator is zero
addr: Jump Address
Description: The instruction checks whether the value stored in the accumulator is 0. If yes, a
jump to the specified address will be executed. Otherwise, the program proceeds with the
following instruction. This is a short jump instruction, which means that the address of a new
location must be relatively near the current one (-129 to + 127 locations relative to the first
following instruction).
Syntax: JZ [jump address];
Bytes: 2 (instruction code, jump value);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: PC=0323h


After execution: If A0: PC=324h
If A=0: PC=283h
MOV A,Rn - Moves the Rn register to the accumulator
Rn: any R register (R0-R7)
A: accumulator
Description: The instruction moves the Rn register to the accumulator. The Rn register is not
affected.
Syntax: MOV A,Rn;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: R3=58h


After execution: R3=58h A=58h
LJMP addr16 - Long jump
addr16: jump address
Description: Instruction causes a jump to the specified 16-bit address.
Syntax: LJMP [jump address];
Bytes: 3 (instruction code, address (15-8), address (7-0));
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: PC=0123h


After execution: PC=1234h
MOV A,@Ri - Moves the indirect RAM to the accumulator
Ri: Register R0 or R1
A: accumulator
Description: Instruction moves the indirectly addressed register of RAM to the accumulator. The
register address is stored in the Ri register (R0 or R1). The result is stored in the accumulator.
The register is not affected.
Syntax: MOV A,@Ri;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Register Address SUM=F2h R0=F2h


Before execution: SUM=58h
After execution: A=58h SUM=58h
MOV A,direct - Moves the direct byte to the accumulator
Direct: arbitrary register with address 0-255 (0-FFh)
A: accumulator
Description: Instruction moves the direct byte to the accumulator. As it is direct addressing, the
register can be any SFRs or general-purpose register with address 0-7Fh. (0-127 dec.). After
executing the instruction, the register is not affected.
Syntax: MOV A,direct;
Byte: 2 (instruction code, direct byte address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: Rx=68h


After execution: Rx=68h A=68h
MOV Rn,A - Moves the accumulator to the Rn register
Rn: any R register (R0-R7)
A: accumulator
Desription: Instruction moves the accumulator to the Rn register. The accumulator is not
affected.
Syntax: MOV Rn,A;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: A=58h


After execution: R3=58h A=58h
MOV A,#data - Moves the immediate data to the accumulator
A: accumulator
Data: Constant in the range of 0-255 (0-FFh)
Desription: Instruction moves the immediate data to the accumulator.
Syntax: MOV A,#data;
Bytes: 2 (instruction code, data);
STATUS register flags: No flags are affected;
EXAMPLE:

After execution: A=28h


MOV Rn,#data - Moves the immediate data to the Rn register
Rn: any R register (R0-R7) Data: Constant in the range of 0-255 (0-FFh)
Description: Instruction moves the immediate data to the Rn register.

Syntax: MOV Rn,#data;


Bytes: 2 (instruction code, data);
STATUS register flags: No flags are affected;
EXAMPLE:

After execution: R5=32h


MOV Rn,direct - Moves the direct byte to the Rn register
Rn: Any R registar (R0-R7)
Direct: arbitrary register with address 0-255 (0-FFh)
Description: Instruction moves the direct byte to the Rn register. As it is direct addressing, the
register can be any SFRs or general-purpose register with address 0-7Fh. (0-127 dec.). After
executing the instruction, the register is not affected.
Syntax: MOV Rn,direct;
Bytes: 2 (instruction code, direct);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: SUM=58h


After execution: SUM=58h R3=58h

MOV direct,Rn - Moves the Rn register to the direct byte


Rn: any R register (R0-R7)
Direct: arbitrary register with address 0-255 (0 - FFh)
Description: Instruction moves the Rn register to the direct byte. As it is direct addressing, the
register can be any SFRs or general-purpose register with address 0-7Fh. (0-127 dec.). After
executing the instruction, the register is not affected.
Syntax: MOV direct,Rn;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: R3=18h


After execution: R3=18h CIF=18h
MOV direct,A - Moves the accumulator to the direct byte
Direct: arbitrary register with address 0-255 (0 - FFh)
A: accumulator
Description: Instruction moves the accumulator to the direct byte. As it is direct addressing, the
register can be any SFRs or general-purpose register with address 0-7Fh. (0-127 dec.). After
executing the instruction, the register is not affected.
Syntax: MOV direct,A;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: A=98h


After execution: A=98h REG=98h
MOV direct,@Ri - Moves the indirect RAM to the direct byte
Direct: arbitrary register with address 0-255 (0 - FFh)
Ri: Register R0 or R1
Description: Instruction moves the indirectly adressed register of RAM to the direct byte. The
register is not affected.
Syntax: MOV direct,@Ri;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: No flags are affected;
EXAMPLE:

Register Address SUM=F3


Before execution: SUM=58h R1=F3
After execution: SUM=58h TEMP=58h
MOV direct1,direct2 - Moves the direct byte to the direct byte
Direct: Arbitrary register with address 0-255 (0-FFh)
Direct: Arbitrary register with address 0-255 (0-FFh)

Description: Instruction moves the direct byte to another direct byte. As it is direct addressing,
both registers can be any SFRs or general-purpose registers with address 0-7Fh. (0-127 dec.).
The direct1 is not affected.
Syntax: MOV direct1,direct2;
Bytes: 3 (instruction code, direct1 address, direct2 address);
STATUS register flags: No flags are affected.
EXAMPLE:

Before execution: TEMP=58h


After execution: TEMP=58h SUM=58h
MOV @Ri,A - Moves the accumulator to the indirect RAM
A: accumulator
Ri: register R0 or R1
Description: Instruction moves the accumulator to the indirectly addressed register of RAM.
The register address is stored in the Ri register (R0 or R1). After executing the instruction, the
accumulator is not affected.
Syntax: MOV @Ri,A;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Register Address SUM=F2h


Before execution: R0=F2h A=58h
After execution: SUM=58h A=58h
MOV direct,#data - Moves the immediate data to the direct byte
Direct: Arbitrary register with address 0-255 (0-FFh)
Data: Constant in the range of 0-255 (0-FFh)
Description: Instruction moves the immediate data to the direct byte. As it is direct addressing,
the direct byte can be any SFRs or general-purpose register with address 0-7Fh. (0-127 dec.).
Syntax: MOV direct,#data;
Bytes: 3 (instruction code, direct byte address, data);
STATUS register flags: No flags are affected;
EXAMPLE:

After execution: TEMP=22h


MOV @Ri,#data - Moves the immediate data to the indirect RAM
Ri: Register R0 or R1
Data: Constant in the range of 0-255 (0-FFh)
Description: Instruction moves the immediate data to the idirectly addressed register of RAM.
The register address is stored in the Ri register (R0 or R1).
Syntax: MOV @Ri,#data;
Bytes: 2 (instruction code, data);
STATUS register flags: No flags are affected;
EXAMPLE:

Register address TEMP=E2h


Before execution: R1=E2h
After execution: TEMP=44h
MOV @Ri,direct - Moves the direct byte to the indirect RAM
Direct: Arbitrary register with address 0-255 (0-FFh)
Ri: Register R0 or R1
Description: Instruction moves the direct byte to a register the address of which is stored in the
Ri register (R0 or R1). After executing the instruction, the direct byte is not affected.
Syntax: MOV @Ri,direct;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: No flags are affected;
EXAMPLE:

Register address TEMP=E2h


Before execution: SUM=58h R1=E2h
After execution: SUM=58h TEMP=58h
MOV bit,C - Moves the carry flag to the direct bit
C: Carry flag
Bit: any bit of RAM

Description: Instruction moves the carry flag to the direct bit. After executing the instruction,
the carry flag is not affected.
Syntax: MOV bit,C;
Bytes: 2 (instruction code, bit address);
STATUS register flags: No flags are affected;
EXAMPLE:

After execution: If C=0 P1.2=0


If C=1 P1.2=1
MOV C,bit - Moves the direct bit to the carry flag
C: Carry flag
Bit: any bit of RAM
Description: Instruction moves the direct bit to the carry flag. After executing the instruction,
the bit is not affected.
Syntax: MOV C,bit;
Bytes: 2 (instruction code, bit address);
STATUS register flags: C;
EXAMPLE:

After execution: If P1.4=0 C=0


If P1.4=1 C=1
MOVC A,@A+DPTR - Moves the code byte relative to the DPTR to the accumulator
A: accumulator
DPTR: Data Pointer
Description: Instruction first adds the 16-bit DPTR register to the accumulator. The result of
addition is then used as a memory address from which the 8-bit data is moved to the
accumulator.
Syntax: MOVC A,@A+DPTR;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution:
DPTR=1000:
A=0
A=1
A=2
A=3
After execution:
A=66h
A=77h
A=88h
A=99h

Note: DB (Define Byte) is a directive in assembly language used to define constant.


MOV DPTR,#data16 - Loads the data pointer with a 16-bit constant
Data: constant in the range of 0-65535 (0-FFFFh)
DPTR: Data Pointer
Description: Instruction stores a 16-bit constant to the DPTR register. The 8 high bits of the
constant are stored in the DPH register, while the 8 low bits are stored in the DPL register.
Syntax: MOV DPTR,#data;
Bytes: 3 (instruction code, constant (15-8), constant (7-0));
STATUS register flags: No flags affected;
EXAMPLE:

After execution: DPH=12h DPL=34h


MOVX A,@Ri - Moves the external RAM (8-bit address) to the accumulator
Ri: register R0 or R1
A: accumulator
Description: Instruction reads the content of a register in external RAM and moves it to the
accumulator. The register address is stored in the Ri register (R0 or R1).
Syntax: MOVX A,@Ri;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;
EXAMPLE:

Register Address: SUM=12h


Before execution: SUM=58h R0=12h
After execution: A=58h
Note:
SUM Register is stored in external RAM which is 256 bytes in size.
MOVC A,@A+PC - Moves the code byte relative to the PC to the accumulator
A: accumulator
PC: Program Counter
Description: Instruction first adds the 16-bit PC register to the accumulator (the current program
address is stored in the PC register). The result of addition is then used as a memory address
from which the 8-bit data is moved to the accumulator.
Syntax: MOVC A,@A+PC;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;
EXAMPLE:

After the subroutine "Table" has been executed, one of four values is stored in the accumulator:
Before execution:
A=0
A=1
A=2
A=3
After execution:
A=66h
A=77h
A=88h
A=99h
Note: DB (Define Byte) is a directive in assembly language used to define constant.
MOVX @Ri,A - Moves the accumulator to the external RAM (8-bit address)
Ri: register R0 or R1
A: accumulator
Description: Instruction moves the accumulator to a register stored in external RAM. Its address
is stored in the Ri register.
Syntax: MOVX @Ri,A;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;

EXAMPLE:

Register address: SUM=34h


Before execution: A=58 R1=34h
After execution: SUM=58h
NOTE:
Register SUM is located in external RAM which is 256 bytes in size.
MOVX A,@DPTR - Moves the external memory (16-bit address) to the accumulator
A: accumulator
DPRTR: Data Pointer
Description: Instruction moves the content of a register in external memory to the accumulator.
The 16-bit address of the register is stored in the DPTR register (DPH and DPL).
Syntax: MOVX A,@DPTR;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;
EXAMPLE:

Register address: SUM=1234h


Before execution: DPTR=1234h SUM=58
After execution: A=58h

Note:
Register SUM is located in external RAM which is up to 64K in size.
MUL AB - Multiplies A and B
A: accumulator
B: Register B
Description: Instruction multiplies the value in the accumulator with the value in the B register.
The low-order byte of the 16-bit result is stored in the accumulator, while the high byte remains
in the B register. If the result is larger than 255, the overflow flag is set. The carry flag is not
affected.
Syntax: MUL AB;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: A=80 (50h) B=160 (A0h)


After execution: A=0 B=32h
AB=80160=12800 (3200h)
MOVX @DPTR,A - Moves the accumulator to the external RAM (16-bit address)
A: accumulator
DPTR: Data Pointer
Description: Instruction moves the accumulator to a register stored in external RAM. The 16-bit
address of the register is stored in the DPTR register (DPH and DPL).
Syntax: MOVX @DPTR,A;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;
EXAMPLE:

Register address: SUM=1234h


Before execution: A=58 DPTR=1234h
After execution: SUM=58h
Note:
Register SUM is located in RAM which is up to 64K in size.
ORL A,Rn - OR register to the accumulator
Rn: any R register (R0-R7)
A: accumulator
Description: Instruction performs logic OR operation between the accumulator and Rn register.
The result is stored in the accumulator.
Syntax: ORL A,Rn;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: A= C3h (11000011 Bin.)


R5= 55h (01010101 Bin.)
After execution: A= D7h (11010111 Bin.)
NOP - No operation

Description: Instruction doesnt perform any operation and is used when additional time delays
are needed.
Syntax: NOP;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;
EXAMPLE:

Such a sequence provides a negative pulse which lasts exactly 5 machine cycles on the P2.3. If a
12 MHz quartz crystal is used then 1 cycle lasts 1uS, which means that this output will be a lowgoing output pulse for 5 uS.
ORL A,@Ri - OR indirect RAM to the accumulator
Ri: register R0 or R1
A: accumulator
Description: Instruction performs logic OR operation between the accumulator and a register.
As it is indirect addressing, the register address is stored in the Ri register (R0 or R1). The result
is stored in the accumulator.
Syntax: ANL A,@Ri;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;
EXAMPLE:

Register address: TEMP=FAh


Before execution: R1=FAh
TEMP= C2h (11000010 Bin.)
A= 54h (01010100 Bin.)
After execution: A= D6h (11010110 Bin.)
ORL A,direct - OR direct byte to the accumulator
Direct: arbitrary register with address 0-255 (0-FFh)
A: accumulator
Description: Instruction performs logic OR operation between the accumulator and a register.
As it is direct addressing, the register can be any SFRs or general-purpose register with address
0-7Fh (0-127 dec.). The result is stored in the accumulator.
Syntax: ORL A,direct;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: A= C2h (11000010 Bin.)


LOG= 54h (01010100 Bin.)
After execution: A= D6h (11010110 Bin.)
ORL direct,A - OR accumulator to the direct byte

Direct: arbitrary register with address 0-255 (0-FFh)


A: accumulator
Description: Instruction performs logic OR operation between a register and accumulator. As it
is direct addressing, the register can be any SFRs or general- purpose register with address 0-7Fh
(0-127 dec.). The result is stored in the register.
Syntax: ORL [register address], A;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: TEMP= C2h (11000010 Bin.)


A= 54h (01010100 Bin.)
After execution: A= D6h (11010110 Bin.)
ORL A,#data - OR immediate data to the accumulator
Data: constant in the range of 0-255 (0-FFh)
A: accumulator
Description: Instruction performs logic OR operation between the accumulator and the
immediate data. The result is stored in the accumulator.
Syntax: ORL A, #data;
Bytes: 2 (instruction code, data);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: A= C2h (11000010 Bin.)


After execution: A= C3h (11000011 Bin.)
ORL C,bit - OR direct bit to the carry flag
C: Carry flag
Bit: any bit of RAM
Description: Instruction performs logic OR operation between the direct bit and the carry flag.
The result is stored in the carry flag.
Syntax: ORL C,bit;
Bytes: 2 (instruction code, direct bit address);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: ACC= C6h (11001010 Bin.)


C=0
After execution: C=1
ORL direct,#data - OR immediate data to direct byte
Direct: arbitrary register with address 0-255 (0-FFh)
Data: constant in the range of 0-255 (0-FFh)

Description: Instruction performs logic OR operation between the immediate data and the direct
byte. As it is direct addressing, the direct byte can be any SFRs or general-purpose register with
address 0-7Fh (0-127 dec.). The result is stored in the direct byte.
Syntax: ORL [register address],#data;
Bytes: 3 (instruction code, direct byte address, data);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: TEMP= C2h (11000010 Bin.)


After execution: A= D2h (11010010 Bin.)
POP direct - Pop the direct byte from the stack
Direct: arbitrary register with address 0-255 (0-FFh)
Description: Instruction first reads data from the location being pointed to by the Stack. The
data is then copied to the direct byte and the value of the Stack Pointer is decremented by 1. As it
is direct addressing, the direct byte can be any SFRs or general-purpose register with address 07Fh. (0-127 dec.).
Syntax: POP direct;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: Address Value


030h 20h
031h 23h
SP==> 032h 01h
DPTR=0123h (DPH=01, DPL=23h)
After execution: Address Value
SP==> 030h 20h
031h 23h
032h 01h
ORL C,/bit - OR complements of direct bit to the carry flag
C: carry flag
Bit: any bit of RAM
Description: Instruction performs logic OR operation between the addressed inverted bit and the
carry flag. The result is stored in the carry flag.
bi bi C AND
C
t t
bit
0 1 00
0 1 11
1 0 00
1 0 10

Syntax: ORL C,/bit;


Bytes: 2 (instruction code, bit address);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: ACC= C6h (11001010 Bin.)


C=0
After execution: C=0
RET - Return from subroutine
Description: This instruction ends every subroutine. After execution, the program proceeds with
the instruction following an ACALL or LCALL.
Syntax: RET;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;
EXAMPLE:

PUSH direct - Pushes the direct byte onto the stack


Data: Arbitrary register with address 0-255 (0-FFh)
Description: Address currently pointed to by the Stack Pointer is first incremented by 1 and
afterwards the data from the register Rx is copied to it. As it is direct addressing, the direct byte
can be any SFRs or general-purpose register with address 0-7Fh. (0-127 dec.)
Syntax: PUSH direct;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: Address Value


SP==> 030h 20h
DPTR=0123h (DPH=01, DPL=23h)
After execution: Address Value
030h 20h
031h 23h
SP==> 032h 01h
RL A - Rotates the accumulator one bit left
A: accumulator
Description: Eight bits in the accumulator are rotated one bit left, so that the bit 7 is rotated into
the bit 0 position.
Syntax: RL A;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: A= C2h (11000010 Bin.)


After execution: A=85h (10000101 Bin.)

RETI - Return from interrupt


Description: This instruction ends every interrupt routine and informs processor about it. After
executing the instruction, the program proceeds from where it left off. The PSW is not
automatically returned its pre-interrupt status.
Syntax: RETI;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;
RR A - Rotates the accumulator one bit right
A: accumulator
Description: All eight bits in the accumulator are rotated one bit right so that the bit 0 is rotated
into the bit 7 position.
Syntax: RR A;
Byte: 1 (instruction code);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: A= C2h (11000010 Bin.)


After execution: A= 61h (01100001 Bin.)

RLC A - Rotates the accumulator one bit left through the carry flag
A: accumulator
Description: All eight bits in the accumulator and carry flag are rotated one bit left. After this
operation, the bit 7 is rotated into the carry flag position and the carry flag is rotated into the bit 0
position.
Syntax: RLC A;
Byte: 1 (instruction code);
STATUS register flags: C;
EXAMPLE:

Before execution: A= C2h (11000010 Bin.)


C=0
After execution: A= 85h (10000100 Bin.)
C=1

SETB C - Sets the carry flag


C: Carry flag
Description: Instruction sets the carry flag.
Syntax: SETB C;
Byte: 1 (instruction code);
STATUS register flags: C;
EXAMPLE:

After execution: C=1


RRC A - Rotates the accumulator one bit right through the carry flag
A: accumulator
Description: All eight bits in the accumulator and carry flag are rotated one bit right. After this
operation, the carry flag is rotated into the bit 7 position and the bit 0 is rotated into the carry flag
position.

Syntax: RRC A;
Byte: 1 (instruction code);
STATUS register flags: C;
EXAMPLE:

Before execution: A= C2h (11000010 Bin.)


C=0
After execution: A= 61h (01100001 Bin.)
C=0

SJMP rel - Short Jump (relative address)


addr: Jump Address
Description: Instruction enables jump to the new address which should be in the range of -128
to +127 locations relative to the first following instruction.
Syntax: SJMP [jump address];
Bytes: 2 (instruction code, jump value);
STATUS register flags: No flags are affected;

EXAMPLE:

Before execution: PC=323


After execution: PC=345
SETB bit - Sets the direct bit
Bit: any bit of RAM
Description: Instruction sets the specified bit. The register containing that bit must belong to the
group of the so called bit addressable registers.
Syntax: SETB [bit address];
Bytes: 2 (instruction code, bit address);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: P0.1 = 34h (00110100)


pin 1 is configured as an output

After execution: P0.1 = 35h (00110101)


pin 1 is configured as an input
SUBB A,direct - Subtracts the direct byte from the accumulator with a borrow
Direct: arbitrary register with address 0-255 (0-FFh)
A: accumulator
Description: Instruction subtracts the direct byte from the accumulator with a borrow. If the
higher bit is subtracted from the lower bit then the carry flag is set. As it is direct addressing, the
direct byte can be any SFRs or general-purpose register with address 0-7Fh. (0-127 dec.). The
result is stored in the accumulator.
Syntax: SUBB A,direct;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: C, OV, AC;
EXAMPLE:

Before execution: A=C9h, DIF=53h, C=0


After execution: A=76h, C=0
SUBB A,Rn - Subtracts the Rn register from the accumulator with a borrow
Rn: any R register (R0-R7)
A: accumulator
Description: Instruction subtracts the Rn register from the accumulator with a borrow. If the
higher bit is subtracted from the lower bit then the carry flag is set. The result is stored in the
accumulator.
Syntax: SUBB A,Rn;
Byte: 1 (instruction code);
STATUS register flags: C, OV, AC;
EXAMPLE:

Before execution: A=C9h, R4=54h, C=1


After execution: A=74h, C=0
Note:
The result is different (C9 - 54=75) because the carry flag is set (C=1) before the instruction
starts execution.
SUBB A,#data - Subtracts the immediate data from the accumulator with a borrow
A: accumulator
Data: constant in the range of 0-255 (0-FFh)
Description: Instruction subtracts the immediate data from the accumulator with a borrow. If the
higher bit is subtracted from the lower bit then the carry flag is set. The result is stored in the
accumulator.
Syntax: SUBB A,#data;
Bytes: 2 (instruction code, data);
STATUS register flags: C, OV, AC;
EXAMPLE:

Before execution: A=C9h, C=0


After execution: A=A7h, C=0
SUBB A,@Ri - Subtracts the indirect RAM from the accumulator with a borrow

Ri: register R0 or R1
A: accumulator
Description: Instruction subtracts the indirectly addressed register of RAM from the
accumulator with a borrow. If the higher bit is subtracted from the lower bit then the carry flag is
set. As it is indirect addressing, the register address is stored in the Ri register (R0 or R1). The
result is stored in the accumulator.
Syntax: SUBB A,@Ri;
Byte: 1 (instruction code);
STATUS register flags: C, OV, AC;
EXAMPLE:

Register address: MIN=F4


Before execution: A=C9h, R1=F4h, MIN=04, C=0
After execution: A=C5h, C=0
XCH A,Rn - Exchanges the Rn register with the accumulator
Rn: any R register (R0-R7)
A: accumulator
Description: Instruction causes the accumulator and Rn register to exchange data. The content
of the accumulator is moved to the Rn register and vice versa.
Syntax: XCH A,Rn;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: A=C6h, R3=29h


After execution: R3=C6h, A=29h
SWAP A - Swaps nibbles within the accumulator
A: accumulator
Description: A nibble refers to a group of 4 bits within one register (bit0-bit3 and bit4-bit7).
This instruction interchanges high and low nibbles of the accumulator.
Syntax: SWAP A;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: A=E1h (11100001)bin.


After execution: A=1Eh (00011110)bin.

XCH A,@Ri - Exchanges the indirect RAM with the accumulator


Ri: register R0 or R1
A: accumulator
Description: Instruction moves the contents of accumulator to the indirectly addressed register
of RAM and vice versa. As it is indirect addressing, the register address is stored in the register
Ri (R0 or R1).
Syntax: XCH A,@Ri;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Register address: SUM=E3


Before execution: R0=E3, SUM=29h, A=98h
After execution: A=29h, SUM=98h
XCH A,direct - Exchanges the direct byte with the accumulator
Direct: arbitrary register with address 0-255 (0-FFh)
A: accumulator
Description: Instruction moves the contents of the accumulator into the direct byte and vice
versa. As it is direct addressing, the direct byte can be any SFRs or general-purpose register with
address 0-7Fh (0-127 dec.).

Syntax: XCH A,direct;


Bytes: 2 (instruction code, direct byte address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: A=FFh, SUM=29h


After execution: SUM=FFh A=29h
XRL A,Rn - Exclusive OR register to accumulator
Rn: any R register (R0-R7)
A: accumulator
Description: Instruction performs exclusive OR operation between the accumulator and the Rn
register. The result is stored in the accumulator.
Syntax: XRL A,Rn;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: A= C3h (11000011 Bin.)


R3= 55h (01010101 Bin.)
After execution: A= 96h (10010110 Bin.)

XCHD A,@Ri - Exchanges the low-order nibble indirect RAM with the accumulator
Ri: register R0 or R1
A: accumulator
Description: This instruction interchanges the low-order nibbles (bits 0-3) of the accumulator
with the low-order nibbles of the indirectly addressed register of RAM. High-order nibbles of the
accumulator and register are not affected. This instruction is mainly used when operating with
BCD values. As it is indirect addressing, the register address is stored in the register Ri (R0 or
R1).
Syntax: XCHD A,@Ri;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Register address: SUM=E3


Before execution: R0=E3 SUM=29h A=A8h,
After execution: A=A9h, SUM=28h

XRL A,@Ri - Exclusive OR indirect RAM to the accumulator

Ri: Register R0 or R1
A: accumulator
Description: Instruction performs exclusive OR operation between the accumulator and the
indirectly addressed register. As it is indirect addressing, the register address is stored in the Ri
register (R0 or R1). The result is stored in the accumulator.
Syntax: XRL A,@Ri;
Byte: 1 (instruction code);
STATUS register flags: No flags are affected;
EXAMPLE:

Register address: TEMP=FAh, R1=FAh


Before execution: TEMP= C2h (11000010 Bin.)
A= 54h (01010100 Bin.)
After execution: A= 96h (10010110 Bin.)
XRL A,direct - Exclusive OR direct byte to the accumulator
Direct: Arbitrary register with address 0-255 (0-FFh)
A: accumulator
Description: Instruction performs exclusive OR operation between the accumulator and the
direct byte. As it is direct addressing, the register can be any SFRs or general-purpose register
with address 0-7Fh (0-127 dec.). The result is stored in the accumulator.
Syntax: XRL A,direct;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: A= C2h (11000010 Bin.)


LOG= 54h (01010100 Bin.)
After execution: A= 96h (10010110 Bin.)
XRL direct,A - Exclusive OR accumulator to the direct byte
Direct: arbitrary register with address 0-255 (0-FFh)
A: accumulator
Description: Instruction performs exclusive OR operation between the direct byte and the
accumulator. As it is direct addressing, the register can be any SFRs or general-purpose register
with address 0-7Fh (0-127 dec.). The result is stored in the register.
Syntax: XRL direct,A;
Bytes: 2 (instruction code, direct byte address);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: TEMP= C2h (11000010 Bin.)


A= 54h (01010100 Bin.)
After execution: A= 96h (10010110 Bin.)
XRL A,#data - Exclusive OR immediate data to the accumulator
Data: constant in the range of 0-255 (0-FFh)
A: accumulator

Description: Instruction performs exclusive OR operation between the accumulator and the
immediate data. The result is stored in the accumulator.
Syntax: XRL A,#data;
Bytes: 2 (instruction code, data);
STATUS register flags: No flags are affected;
EXAMPLE:

Before execution: A= C2h (11000010 Bin.)


X= 11h (00010001 Bin.)
After execution: A= D3h (11010011 Bin.)
XRL direct,#data - Exclusive OR immediate data to direct byte
Direct: arbitrary register with address 0-255 (0-FFh)
Data: constant in the range of 0-255 (0-FFh)
Description: Instruction performs exclusive OR operation between the immediate data and the
direct byte. As it is direct addressing, the register can be any SFRs or general-purpose register
with address 0-7Fh (0-127 dec.). The result is stored in the register.
Syntax: XRL direct,#data;
Bytes: 3 (instruction code, direct byte address, data);
STATUS register flags: No flags affected;
EXAMPLE:

Before execution: TEMP= C2h (11000010 Bin.)


X=12h (00010010 Bin.)
After execution: A= D0h (11010000 Bin.)

CHAPTER-FIVE
Introduction
It was time that hardware-oriented to the core made compromise if they wanted to stay in the
game. Namely, unlike other circuits which only need to be connected to other components and
powered in order to be of any use, microcontrollers require to be programmed as well.
Fortunately, they still didn't progress so far in their evolution, so that all microcontroller families
understand only one language - machine language. That's a good thing. The bad one is that,
even primitive, this language of zeros and ones can only be understood by microcontrollers and
some of the experts working on its development. In order to bridge this gap between machine
and humans, the first high-level programming language called Assembly language was created.
The main problem of remembering codes recognized as instructions by electronics was solved
therefore, but another one, equally complicated to both us and them(microcontrollers) arose.
This problem was also easily solved by means of the program for a PC called assembler and a
simple device called programmer.
This program enables the PC to receive commands in the form of abbreviations and convert them
unerringly into so called executable file. The moment of compiling a program into machine
language is crucial as this file, called HEX file, represents a series of binary numbers
understandable to microcontrollers only. The program written in assembly language cannot be
executed practically unless this file is loaded into the microcontroller memory. This is the
moment when the last link in the chain - the programmer - appears on the scene. It is a small
device connected to a PC via some of the ports and has a socket for placing chip in.

5.1 Elements of Assembly Language


Assembly language is basically like any other language, which means that it has its words, rules
and syntax. The basic elements of assembly language are:

Labels;
Orders;

Directives; and

Comments.

Syntax of Assembly language


When writing a program in assembly language it is necessary to observe specific rules in order to
enable the process of compiling into executable HEX-code to run without errors. These
compulsory rules are called syntax and there are only several of them:

Every program line may consist of a maximum of 255 characters;


Every program line to be compiled, must start with a symbol, label, mnemonics or
directive;

Text following the mark ; in a program line represents a comment ignored (not
compiled) by the assembler; and

All the elements of one program line (labels, instructions etc.) must be separated by at
least one space character. For the sake of better clearness, a push button TAB on a
keyboard is commonly used instead of it, so that it is easy to delimit columns with labels,
directives etc. in a program.

Numbers
If octal number system, otherwise considered as obsolite, is disregarded, assembly laguage
allows numbers to be used in one out of three number systems:
Decimal Numbers
If not stated otherwise, the assembly language considers all the numbers as decimal. All ten
digits are used (0,1,2,3,4,5,6,7,8,9). Since at most 2 bytes are used for saving them in the
microcontroller, the largest decimal number that can be written in assembly language is 65535. If
it is necessary to specify that some of the numbers is in decimal format, then it has to be
followed by the letter D. For example 1234D.
Hexadecimal Numbers
Hexadecimal numbers are commonly used in programming. There are 16 digits in hexadecimal
number system (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F). The largest hexadecimal number that
can be written in assembly language is FFFF. It corresponds to decimal number 65535. In order
to distinguish hexadecimal numbers from decimal, they are followed by the letter h(either in
upper- or lowercase). For example 54h.
Binary Numbers
Binary numbers are often used when the value of each individual bit of some of the registers is
important, since each binary digit represents one bit. There are only two digits in use (0 and 1).
The largest binary number written in assembly language is 1111111111111111. In order to
distinguish binary numbers from other numbers, they are followed by the letter b (either in
upper- or lowercase). For example 01100101B.
Operators
Some of the assembly-used commands use logical and mathematical expessions instead of
symbols having specific values. For example:
IF (VERSION>1)
LCALL Table_2
USING VERSION+1
ENDIF
...

As seen, the assembly language is capable of computing some values and including them in a
program code, thus using the following mathematical and logical operations:

Name
+
*
/
MOD
SHR
SHL
NOT
AND
OR
XOR
LOW
HIGH
EQ, =
NE,<>
GT, >
GE, >=
LT, <
LE,<=

Operation
Example
Addition
10+5
Subtraction
25-17
Multiplication
7*4
Division (with no remainder)
7/4
Remainder of division
7 MOD 4
Shift register bits to the right
1000B SHR 2
Shift register bits to the left
1010B SHL 2
Negation (first complement of number) NOT 1
Logical AND
1101B AND 0101B
Logical OR
1101B OR 0101B
Exclusive OR
1101B XOR 0101B
8 low significant bits
LOW(0AADDH)
8 high significant bits
HIGH(0AADDH)
Equal
7 EQ 4 or 7=4
Not equal
7 NE 4 or 7<>4
Greater than
7 GT 4 or 7>4
Greater or equal
7 GE 4 or 7>=4
Less than
7 LT 4 or 7<4
Less or equal
7 LE 4 or 7<=4

Result
15
8
28
1
3
0010B
101000B
1111111111111110B
0101B
1101B
1000B
0DDH
0AAH
0 (false)
0FFFFH (true)
0FFFFH (true)
0FFFFH (true)
0 (false)
0 (false)

Symbols
Every register, constant, address or subroutine can be assigned a specific symbol in assembly
language, which considerably facilitates the process of writing a program. For example, if the
P0.3 input pin is connected to a push button used to stop some process manually (push button
STOP), the process of writing a program will be much simpler if the P0.3 bit is assigned the
same name as the push button, i.e. pushbutton_STOP. Of course, like in any other language,
there are specific rules to be observed as well:

For the purpose of writing symbols in assembly language, all letters from alphabet (A-Z,
a-z), decimal numbers (0-9) and two special characters ("?" and "_") can be used.
Assembly language is not case sensitive.

For example, the following symbols will be considered identical:


Serial_Port_Buffer
SERIAL_PORT_BUFFER
In order to distinguish

symbols from constants (numbers), every symbol starts with a


letter or one of two special characters (? or _).
The symbol may consist of maximum of 255 characters, but only first 32 are taken into
account. In the following example, the first two symbols will be considered duplicate
(error), while the third and forth symbols will be considered different:

START_ADDRESS_OF_TABLE_AND_CONSTANTS_1

START_ADDRESS_OF_TABLE_AND_CONSTANTS_2
TABLE_OF_CONSTANTS_1_START_ADDRESS
TABLE_OF_CONSTANTC_2_START_ADDRESS
Some of the symbols cannot be used when

writing a program in assembly language


because they are already part of instructions or assembly directives. Thus, for example, a
register or subroutine cannot be assigned name A or DPTR because there are
registers having the same name.

Here is a list of symbols not allowed to be used during programming in assembly language:
A
ADDC
AR0
AR4
BIT
CJNE
CSEG
DBIT
DPTR
END
GT
ISEG
JMP
JZ
LOW
MOVC
NOP
ORL
R0
R4
RET
RR
SHL
SWAP
XDATA

AB
ACALL ADD
AJMP AND ANL
AR1
AR2
AR3
AR5
AR6
AR7
BSEG C
CALL
CLR
CODE CPL
DA
DATA DB
DEC DIV
DJNZ
DS
DSEG DW
EQ
EQU
GE
HIGH IDATA INC
JB
JBC
JC
JNB
JNC
JNZ
LCALL LE
LJMP
LT
MOD MOV
MOVX MUL NE
NOT OR
ORG
PC
POP
PUSH
R1
R2
R3
R5
R6
R7
RETI RL
RLC
RRC SET
SETB
SHR
SJMP SUBB
USING XCH XCHD
XOR XRL
XSEG

Labels
A label is a special type of symbols used to represent a textual version of an address in ROM or
RAM memory. They are always placed at the beginning of a program line. It is very complicated
to call a subroutine or execute some of the jump or branch instructions without them. They are
easily used:

A symbol (label) with some easily recognizable name should be written at the beginning
of a program line from which a subroutine starts or where jump should be executed.
It is sufficient to enter the name of label instead of address in the form of 16-bit number
in instructions calling a subroutine or jump.

During the process of compiling, the assembler automatically replaces such symbols with
appropriate addresses.
Directives
Unlike instructions being compiled and written to chip program memory, directives are
commands of assembly language itself and have no influence on the operation of the
microcontroller. Some of them are obligatory part of every program while some are used only to
facilitate or speed up the operation.
Directives are written in the column reserved for instructions. There is a rule allowing only one
directive per program line.
EQU directive
The EQU directive is used to replace a number by a symbol. For example:
MAXIMUM EQU 99

After using this directive, every appearance of the label MAXIMUM in the program will be
interpreted by the assembler as the number 99 (MAXIMUM = 99). Symbols may be defined this
way only once in the program. The EQU directive is mostly used at the beginning of the program
therefore.
SET directive
The SET directive is also used to replace a number by a symbol. The significant difference
compared to the EQU directive is that the SET directive can be used an unlimited number of
times:
SPEED SET 45
SPEED SET 46
SPEED SET 57

BIT directive
The BIT directive is used to replace a bit address by a symbol. The bit address must be in the
range of 0 to 255. For example:
TRANSMIT BIT PSW.7 ;Transmit bit (the seventh bit in PSW register)
;is assigned the name "TRANSMIT"
OUTPUT BIT 6 ;Bit at address 06 is assigned the name "OUTPUT"
RELAY BIT 81 ;Bit at address 81 (Port 0)is assigned the name ;"RELAY"

CODE directive
The CODE directive is used to assign a symbol to a program memory address. Since the
maximum capacity of program memory is 64K, the address must be in the range of 0 to 65535.
For example:
RESET CODE 0 ;Memory location 00h called "RESET"
TABLE CODE 1024 ;Memory location 1024h called "TABLE"

DATA directive
The DATA directive is used to assign a symbol to an address within internal RAM. The address
must be in the range of 0 to 255. It is possible to change or assign a new name to any register.
For example:
TEMP12 DATA 32 ;Register at address 32 is named ;as "TEMP12"
STATUS_R DATA D0h ;PSW register is assigned the name ;"STATUS_R"

IDATA directive
The IDATA directive is used to change or assign a new name to an indirectly addressed register.
For example:
TEMP22 IDATA 32 ;Register whose address is in register ;at address 32 is named
as "TEMP22"
TEMP33 IDATA T_ADR ;Register whose address is in ;register T_ADR is named as
"TEMP33"

XDATA directive
The XDATA directive is used to assign a name to registers within external (additional) RAM
memory. The addresses of these registers cannot be larger than 65535. For example:
TABLE_1 XDATA 2048 ;Register stored in external
;memory at address 2048 is named
;as "TABLE_1"

ORG directive
The ORG directive is used to specify a location in program memory where the program
following directive is to be placed. For example:
BEGINNING ORG 100
...
...
ORG 1000h
TABLE
...
...

This program starts at location 100. The table containing data is to be stored at location 1024
(1000h).
USING directive
The USING directive is used to define which register bank (registers R0-R7) is to be used in the
program.
USING
USING
USING
USING

0
1
2
3

;Bank
;Bank
,Bank
;Bank

0
1
2
3

is
is
is
is

used
used
used
used

(registers
(registers
(registers
(registers

R0-R7
R0-R7
R0-R7
R0-R7

at
at
at
at

RAM-addresses
RAM-addresses
RAM-addresses
RAM-addresses

0-7)
8-15)
16-23)
24-31)

END directive
The END directive is used at the end of every program. The assembler will stop compiling once
the program encounters this directive. For example:
...
END ;End of program

Directives used for selecting memory segments


There are 5 directives used for selecting one out of five memory segments in the microcontroller:
CSEG ;Indicates that the next segment refers to program memory;
BSEG ;Selects bit-addressable part of RAM;
DSEG ;Indicates that the next segment refers to the part of internal RAM
accessed by
;direct addressing;
ISEG ;Indicates that the next segment refers to the part of internal RAM
accessed by
;indirect addressing using registers R0 and R1); and
XSEG ;Selects external RAM memory.

The CSEG segment is activated by default after enabling the assembler and remains active until
a new directive is specified. Each of these memory segments has its internal address counter
which is cleared every time the assembler is activated. Its value can be changed by specifying
value after the mark AT. It can be a number, an arithmetical operation or a symbol. For example:
DSEG
;Next segment refers to directly accessed registers; and
BSEG AT 32 ;Selects bit-addressable part of memory with address counter
;moved by 32 bit locations relative to the beginning of that
;memory segment.

A dollar symbol "$" denotes current value of address counter in the currently active segment.
The following two examples illustrate how this value can be used practically:
Example 1:
JNB FLEG,$ ;Program will constantly execute this
;instruction (jump instruction),until
;the flag is cleared.

Example 2:
MESSAGE DB ALARM turn off engine
LENGTH EQU $-MESSAGE-1

These two program lines can be used for computing exact number of characters in the message
ALARM turn off engine which is defined at the address assigned the name MESSAGE.
DS directive
The DS directive is used to reserve memory space expressed in bytes. It is used if some of the
following segments ISEG, DSEG or XSEG is currently active. For example:
Example 1:
DSEG
;Select directly addressed part of RAM
DS 32
;Current value of address counter is incremented by 32
SP_BUFF DS 16 ;Reserve space for serial port buffer
;(16 bytes)
IO_BUFF DS 8 ;Reserve space for I/O buffer in size of 8 bytes

Example 2:
ORG 100
;Start at address 100
DS 8
;8 bytes are reserved
LAB ......... ;Program proceeds with execution (address of this location is
108)

DBIT directive
The DBIT directive is used to reserve space within bit-addressable part of RAM. The memory
size is expressed in bits. It can be used only if the BSEG segment is active. For example:
BSEG ;Bit-addressable part of RAM is selected
IO_MAP DBIT 32 ;First 32 bits occupy space intended for I/O buffer

DB directive
The DB directive is used for writing specified value into program memory. If several values are
specified, then they are separated by a comma. If ASCII array is specified, it should be enclosed

within single quotation marks. This directive can be used only if the CSEG segment is active.
For example:
CSEG
DB 22,33,Alarm,44

If this directive is preceeded by a lable, then the label will point to the first element of the array.
It is the number 22 in this example.
DW directive
The DW directive is similar to the DB directive. It is used for writing a two-byte value into
program memory. The higher byte is written first, then the lower one.
IF, ENDIF and ELSE directives
These directives are used to create so called conditional blocks in the program. Each of these
blocks starts with directive IF and ends with directive ENDIF or ELSE. The statement or symbol
(in parentheses) following the IF directive represents a condition which specifies the part of the
program to be compiled:

If the statement is correct or if the symbol is equal to one, the program will include all
instructions up to directive ELSE or ENDIF.
If the statement is not correct or if the symbol value is equal to zero, all instructions are
ignored, i.e. not compiled, and the program continues with instructions following
directives ELSE or ENDIF.

Example 1:
IF (VERSION>3)
LCALL Table_2
LCALL Addition
ENDIF
...

If the program is of later date than version 3 (statement is correct), subroutines Table 2 and
Addition will be executed. If the statement in parentheses is not correct (VERSION<3), two
instructions calling subroutines will not be compiled.
Example 2:
If the value of the symbol called Model is equal to one, the first two instructions following
directive IF will be compiled and the program continues with instructions following directive
ENDIF (all instructions between ELSE and ENDIF are ignored). Otherwise, if Model=0,
instructions between IF and ELSE are ignored and the assembler compiles only instructions
following directive ELSE.
IF (Model)

MOV R0,#BUFFER
MOV A,@R0
ELSE
MOV R0,#EXT_BUFFER
MOVX A,@R0
ENDIF
...

Control directives
Control directives start with a dollar symbol $. They are used to determine which files are to be
used by the assembler during compilation, where the executable file is to be stored as well as the
final layout of the compiled program called Listing. There are many control directives, but only
few of them is of importance:
\$INCLUDE directive
This directive enables the assembler to use data stored in other files during compilation. For
example:
\$INCLUDE(TABLE.ASM)

\$MOD8253 directive
This $MOD8253 directive is a file containing names and addresses of all SFRs of 8253
microcontrollers. By means of this file and directive having the same name, the assembler can
compile the program on the basis of register names. If they are not used, it is necessary to specify
name and address of every SFRs to be used at the beginning of the program.

CHAPTER-SIX

Introduction
The purpose of this chapter is to provide basic information about microcontrollers that one needs
to know in order to be able to use them successfully in practice. This is why this chapter doesn't
contain any super interesting program or device schematic with amazing solutions. Instead, the
following examples are better proof that program writing is neither a privilege nor a talent issue,
but the ability of simply putting puzzle pieces together using directives. Rest assured that design
and development of devices mainly consists of the following method test-correct-repeat. Of
course, the more you are in it, the more complicated it becomes since the puzzle pieces are put
together by both children and first-class architects...

6.1 Basic connecting

As seen in the figure above, in order to enable the microcontroller to operate properly it is
necessary to provide:

Power supply:
Reset signal: and

Clock signal.

Clearly, it is about very simple circuits, but it does not have to be always like that. If the target
device is used for controlling expensive machines or maintaining vital functions, everything gets
increasingly complicated. However, this solution is sufficient for the time being...
Power supply
Even though this microcontroller can operate at different power supply voltages, why to test
Murphys low?! A 5V DC is most commonly used. The circuit, shown in the figure, uses a
cheap integrated three-terminal positive regulator LM7805, and provides high-quality voltage
stability and quite enough current to enable the microcontroller and peripheral electronics to
operate normally (enough current in this case means 1Amp).

Reset signal
In order that the mucrocontroller can operate properly, a logic 0 (0V) must be applied to the reset
pin RS. The push button connecting the reset pin RS to power supply VCC is not necessary.
However, it is almost always provided because it enables the microcontroller safe return to
normal operating conditions if something goes wrong. 5V is brought to this pin, the
microcontroller is reset and program starts execution from the beginning.
Clock signal
Even though the microcontroller has a built-in oscillator, it cannot operate without two external
capacitors and quartz crystal which stabilize its operation and determines its frequency
(operating speed of the microcontroller).

Of course, it is not always possible to apply this solution so that there are always alternative
ones. One of them is to provide clock signal from a special source through invertor. See the
figure on the left.

6.2 Additional components


Regardless of the fact that the microcontroller is a product of modern technology, it is of no use
without being connected to additional components. Simply put, the appearance of voltage on its
pins means nothing if not used for performing certain operations (turn something on/off, shift,
display etc.).
Switches and Push buttons
There are no simpler devices than switches and push-buttons. This is the simplest way of
detecting appearance of a voltage on the microcontroller input pin.

Nevertheless, it is not so simple in practice... It is about contact bounce- a common problem with
m e c h a n i c a l switches. When the contacts strike together, their momentum and elasticity act
together to cause bounce. The result is a rapidly pulsed electrical current instead of a clean
transition from zero to full current. It mostly occurs due to vibrations, slight rough spots and dirt
between contacts. This effect is usually unnoticeable when using these components in everyday
life because the bounce happens too quickly. In other words, the whole this process does not last
long (a few micro- or miliseconds), but it is long enough to be registered by the microcontroller.
When using only a push-button as a pulse counter, errors occur in almost 100% of cases!

The simplest solution to this problem is to connect a simple RC circuit to suppress quick voltage
changes. Since the bounce period is not defined, the values of components are not precisely
determined. In most cases, it is recomended to use the values shown in figure below.
If complete stability is needed then radical measures should be taken. The output of the circuit,
shown in figure (RS flip-flop), will change its logic state only after detecting the first pulse
triggered by contact bounce. This solution is expensive (SPDT switch), but effecient, the
problem is definitely solved. Since the capacitor is not used, very short pulses can also be
registered in this way.

In addition to these hardware solutions, there is also a simple software solution. When a program
tests the state of an input pin and detects a change, the check should be done one more time after
a certain delay. If the change is confirmed, it means that a switch or push button has changed its
position. The advantages of such solution are obvious: it is free of charge, effects of noises are
eliminated and it can be applied to the poorer quality contacts as well. Disadvantage is the same
as when using RC filter, i.e. pulses shorter than program delay cannot be registered.
Optocoupler

An optocoupler is a device commonly used to galvanically separate microcontrollers electronics


from any potentially dangerous current or voltage in its surroundings. Optocouplers usually have
one, two or four light sources (LED diodes) on their input while on their output, opposite to
diodes, there is the same number of elements sensitive to light (phototransistors, photo-thyristors
or photo-triacs). The point is that an optocoupler uses a short optical transmission path to transfer
a signal between the elements of circuit, while keeping them electrically isolated. This isolation
makes sense only if diodes and photo-sensitive elements are separately powered. In this way, the
microcontroller and expensive additional electronics are completely protected from high voltage
and noises which are the most common cause of destroying, damaging or unstable operation of
electronic devices in practice. The most frequently used optocouplers are those with
phototransistors on their outputs. When using the optocoupler with internal base-to-pin 6
connection (there are also optocouplers without it), the base can be left unconnected. An optional
connection which lessens the effects of noises by eliminating very short pulses is presented by
the broken line in the figure.

Relay

A relays is an electrical switch that opens and closes under control of another electrical circuit. It
is therefore connected to ouput pins of the microcontroller and used to turn on/off high-power
devices such as motors, transformers, heaters, bulbs, antenna systems etc. These are almost
always placed away from the board sensitive components. There are various types of relays but
all of them operate in the same way. When a current flows through the coil, the relay is operated
by an electromagnet to open or close one or many sets of contacts. Similar to optocouplers, there
is no galvanic connection (electrical contact) between input and output circuits. Relays usually
demand both higher voltage and current to start operation, but there are also miniature ones
which can be activated by a low current directly obtained from a microcontroller pin.
The figure shows the solution specific to the 8051 microcontroller. A darlington transistor is used
here to activate relays because of its high current gain. This is not in accordance with rules, but
is necessary in the event that logic one activation is applied since the output current is then very
low (pin acts as an input).

In order to prevent the appearance of self-induction high voltage, caused by a sudden stop of
current flow through the coil, an inverted polarized diode is connected in parallel to the coil. The
purpose of this diode is to cut off the voltage peak.
Light-emitting diode (LED)
Light-emitting diodes are elements for light signalization in electronics. They are manufactured
in different shapes, colors and sizes. For their low price, low power consumption and simple use,
they have almost completely pushed aside other light sources, bulbs at first place. They perform
similar to common diodes with the difference that they emit light when current flows through
them.

It is important to limit their current, otherwise they will be permanently destroyed. For this
reason, a conductor must be connected in parallel to an LED. In order to determine value of this
conductor, it is necessary to know diodes voltage drop in forward direction, which depends on
what material a diode is made from and what colour it is. Typical values of the most frequently
used diodes are shown in table below. As seen, there are three main types of LEDs. Standard
ones get ful brightness at current of 20mA. Low Current diodes get ful brightness at ten times
lower current while Super Bright diodes produce more intensive light than Standard ones.
Color
Infrared
Red
Red
Red
Orange
Green
Yellow
Blue
White

Type

Typical current Id (mA) Maximal current If (mA) Voltage drop Ud (V)


30
50
1.4
Standard
20
30
1.7
Super Bright 20
30
1.85
Low Current 2
30
1.7
10
30
2.0
Low Current 2
20
2.1
20
30
2.1
20
30
4.5
25
35
4.4

Since the 8051 microcontroller can provide only low output current and since its pins are
configured as outputs when voltage provided on them is 0V, direct connecting to LEDs is
performed as shown in figure on the right (Low current LED, cathode is connected to the output
pin).
LED displays
Basically, an LED display is nothing more than several LEDs moulded in the same plastic case.
There are many types of displays composed of several dozens of built in diodes which can
display different symbols.

Most commonly used is a so called 7-segment display. It is composed of 8 LEDs, 7 segments are
arranged as a rectangle for symbol displaying and there is an additional segment for decimal
point displaying. In order to simplify connecting, anodes and catodes of all diodes are connected
to the common pin so that there are common anode displays and common catode displays,
respectively. Segments are marked with the latters from A to G, plus dp, as shown in the figure
on the left. On connecting, each diode is treated separtely, which means that each must have its
own current limiting resistor.
Displays connected to the microcontroller usually occupy a large number of valuable I/O pins,
which can be a big problem especially if it is needed to display multy digit numbers. The
problem is more than obvious if, for example, it is needed to display two 6-digit numbers (a
simple calculation shows that 96 output pins are needed in this case). The solution to this
problem is called MULTIPLEXING. This is how an optical illusion based on the same operating
principle as a film camera is made. Only one digit is active at a time, but they change their state
so quickly making impression that all digits of a number are simultaneously active.

Here is an explanation on the figure above. First a byte representing units is applied on a
microcontroller port and a transistor T1 is activated at the same time. After a while, the transistor
T1 is turned off, a byte representing tens is applied on a port and a transistor T2 is activated. This
process is being cyclically repeated at high speed for all digits and corresponding transistors.
The fact that the microcontroller is just a kind of miniature computer designed to understand
only the language of zeros and ones is fully expressed when displaying any digit. Namely, the
microcontroller doesn't know what units, tens or hundreds are, nor what ten digits we are used to
look like. Therefore, each number to be displayed must be prepared in the following way:
First of all, a multy digit number must be split into units, tens etc. in a particular subroutine.
Then each of these digits must be stored in special bytes. Digits get familiar format by
performing masking. In other words, a binary format of each digit is replaced by a different
combination of bits in a simple subroutine. For example, the digit 8 (0000 1000) is replaced by
the binary number 0111 111 in order to activate all LEDs displaying digit 8. The only diode
remaining inactive in this case is reserved for the decimal point. If a microcontroller port is

connected to the display in such a way that bit 0 activates segment a, bit 1 activates segment
b, bit 2 segment c etc., then the table below shows the mask for each digit.

Digits to display Display Segments


dp a b c d e f g
0
1 0 00 00 01
1
1 0 01 11 11
2
1 0 01 00 10
3
1 0 00 01 10
4
1 1 00 11 00
5
1 0 10 01 00
6
1 0 10 00 00
7
1 0 00 11 11
8
1 0 00 00 00

0 00 01 00

In addition to digits from 0 to 9, some letters of alphabet - A, C, E, J, F, U, H, L, b, c, d, o, r, t can also be displayed by performing appropriate masking.
If the event that common chatode displays are used all units in the table should be replaced by
zeros and vice versa. Additionally, NPN transistors should be used as drivers as well.
Liquid Crystal Displays (LCD)
An LCD display is specifically manufactured to be used with microcontrollers, which means that
it cannot be activated by standard IC circuits. It is used for displaying different messages on a
miniature liquid crysal display.

The model described here is for its low price and great capabilities most frequently used in
practice. It is based on the HD44780 microcontroller (Hitachi) and can display messages in two
lines with 16 characters each. It displays all the letters of alphabet, Greek letters, punctuation
marks, mathematical symbols etc. In addition, it is possible to display symbols made up by the
user. Other useful features include automatic message shift (left and right), cursor appearance,
LED backlight etc.
LCD Pins
There are pins along one side of a small printed board. These are used for connecting to the
microcontroller. There are in total of 14 pins marked with numbers (16 if it has backlight). Their
function is described in the table bellow:
Function
Ground
Power supply
Contrast
Control of operating

Pin Number Name Logic State


Description
1
Vss 0V
2
Vdd +5V
3
Vee 0 - Vdd
0
D0 D7 are interpreted as commands
4
RS
1
D0 D7 are interpreted as data
0
Write data (from controller to LCD)
5
R/W
1
Read data (from LCD to controller)
6
E
0
Access to LCD disabled

Data / commands

7
8
9
10
11
12
13
14

D0
D1
D2
D3
D4
D5
D6
D7

1
From 1 to 0
0/1
0/1
0/1
0/1
0/1
0/1
0/1
0/1

Normal operating
Data/commands are transferred to LCD
Bit 0 LSB
Bit 1
Bit 2
Bit 3
Bit 4
Bit 5
Bit 6
Bit 7 MSB

LCD screen

An LCD screen consists of two lines each containing 16 characters. Each character consists of
5x8 or 5x11 dot matrix. This book covers the most commonly used display, i.e. the 5x8 character
display.
Display contrast depends on the power supply voltage and whether messages are displayed in
one or two lines. For this reason, varying voltage 0-Vdd is applied on the pin marked as Vee.
Trimmer potentiometer is usually used for that purpose. Some LCD displays have built-in
backlight (blue or green LEDs). When used during operation, a current limiting resistor should
be serially connected to one of the pins for backlight power supply (similar to LEDs).

If there are no characters displayed or if all of them are dimmed when the display is on, the first
thing that should be done is to check the potentiometer for contrast regulation. Is it properly
adjusted? The same applies if the mode of operation has been changed (writing in one or two
lines).
LCD Memory
The LCD display contains three memory blocks:

DDRAM Display Data RAM;


CGRAM Character Generator RAM; and

CGROM Character Generator ROM.

DDRAM Memory
DDRAM memory is used for storing characters to be displayed. The size of this memory is
sufficient for storing 80 characters. Some memory locations are directly connected to the
characters on display.

It works quite simply: it is sufficient to configure the display so as to increment addresses


automatically (shift right) and set the starting address for the message that should be displayed
(for example 00 hex).
After that, all characters sent through lines D0-D7 will be displayed in the message format we
are used to- from left to right. In this case, displaying starts from the first field of the first line
since the address is 00 hex. If more than 16 characters are sent, then all of them will be
memorized, but only the first sixteen characters will be visible. In order to display the rest of
them, a shift command should be used. Virtually, everything looks as if the LCD display is a
window which moves left-right over memory locations containing different characters. This is
how the effect of message moving on the screen is made.
If the cursor is on, it appears at the location which is currently addressed. In other words, when a
character appears at the cursor position, it will automatically move to the next addressed
location.
Since this is a sort of RAM memory, data can be written to and read from it, but its contents is
irretrievably lost when the power goes off.
CGROM Memory
CGROM memory contains the default chracter map with all characters that can be displayed on
the screen. Each character is assigned to one memory location.

The addresses of CGROM memory locations match the characters of ASCII. If the program
being currently executed encounters a command send character P to port, then the binary value
0101 0000 appears on the port. This value is the ASCII equivalent to the character P. It is then
written to LCD, which results in displaying the symbol from 0101 0000 location of CGROM. In
other words, the character P is displayed. This applies to all letters of alphabet (capitals and
small), but not to numbers.
As seen on the previous map, addresses of all digits are pushed forward by 48 relative to their
values (digit 0 address is 48, digit 1 address is 49, digit 2 address is 50 etc.). Accordingly, in
order to display digits correctly, each of them needs to be added a decimal number 48 prior to be
sent to LCD.
From their inception till today, computers can recognize only numbers, but not letters. It means
that all data a computer swaps with a peripheral device has a binary format, even though the
same is recognized by the man as letters (keyboard is an excellent example). Every character
matches the unique combination of zeroes and ones. ASCII is character encoding based on the
English alphabet. ASCII code specifies correspondance between standard character symbols and
their numerical equivalents.
CGRAM memory
Apart from standard characters, the LCD display can also display symbols defined by the user
itself. It can be any symbol in the size of 5x8 pixels. RAM memory called CGRAM in the size of
64 bytes enables it.
Memory registers are 8 bits wide, but only 5 lower bits are used. Logic one (1) in every register
represents a dimmed dot, while 8 locations grouped together represent one character. It is best
illustrated in figure below:

Symbols are usually defined at the beginnig of the program by simply writing zeros and ones to
registers of CGRAM memory so that they form desired shapes. In order to display them it is
sufficient to specify their address. Pay attention to the first coloumn in the CGROM map of
characters. It doesn't contain RAM memory addresses, but symbols being discussed here. In this
example, display 0 means - display , display 1 means - display etc.
LCD Basic Commands
All data transferred to LCD through the outputs D0-D7 will be interpreted as a command or a
data, which depends on the pin RS logic state:
RS = 1 - Bits D0-D7 are addresses of the characters to be displayed. LCD processor addresses
one character from the character map and displays it. The DDRAM address specifies the location
on which the character is to be displayed. This address is defined before the character is
transferred or the address of previously transferred character is automatically incremented.
RS = 0 - Bits D0 - D7 are commands which determine the display mode. The commands
recognized by the LCD are given in the table below:
Command
Clear display
Cursor home
Entry mode set
Display on/off control
Cursor/Display Shift
Function set
Set CGRAM address
Set DDRAM address
Read BUSY flag (BF)
Write to CGRAM or DDRAM
Read from CGRAM or DDRAM

RS RW D7 D6 D5 D4 D3 D2 D1 D0 Execution Time
0 0 0 0 0 0 0 0 0 1 1.64mS
0 0 0 0 0 0 0 0 1 x 1.64mS
0 0 0 0 0 0 0 1 I/D S 40uS
0 0 0 0 0 0 1 D U B 40uS
0 0 0 0 0 1 D/C R/L x x 40uS
0 0 0 0 1 DL N F x x 40uS
0 0 0 1 CGRAM address
40uS
0 0 1 DDRAM address
40uS
0 1 BF DDRAM address
1 0 D7 D6 D5 D4 D3 D2 D1 D0 40uS
1 1 D7 D6 D5 D4 D3 D2 D1 D0 40uS

I/D 1 = Increment (by 1)


0 = Decrement (by 1)

R/L 1 = Shift right


0 = Shift left

S 1 = Display shift on
0 = Display shift off

DL 1 = 8-bit interface
0 = 4-bit interface

D 1 = Display on
0 = Display off

N 1 = Display in two lines


0 = Display in one line

U 1 = Cursor on
0 = Cursor off

F 1 = Character format 5x10 dots


0 = Character format 5x7 dots

B 1 = Cursor blink on
0 = Cursor blink off

D/C 1 = Display shift


0 = Cursor shift

What is the Busy flag?

Compared to the microcontroller, the LCD is an extremely slow component. Because of this, it
was necessary to provide a signal which will, upon command execution, indicate that the display
is ready to receive a new data. That signal, called the busy flag, can be read from line D7. When
the BF bit is cleared (BF=0), the display is ready to receive a new data.
LCD Connection
Depending on how many lines are used for connecting the LCD to the microcontroller, there are
8-bit and 4-bit LCD modes. The appropriate mode is selected at the beginning of the operation.
This process is called initialization. 8-bit LCD mode uses outputs D0-D7 to transfer data in the
way explained on the previous page. The main purpose of 4-bit LED mode is to save valuable
I/O pins of the microcontroller. Only 4 higher bits (D4-D7) are used for communication, while
other may be left unconnected. Each data is sent to the LCD in two steps: four higher bits are
sent first (normally through the lines D4-D7), then four lower bits. Initialization enables the LCD
to link and interpret received bits correctly. Data is rarely read from the LCD (it is mainly
transferred from the microcontroller to LCD) so that it is often possible to save an extra I/O pin
by simple connecting R/W pin to ground. Such saving has its price. Messages will be normally
displayed, but it will not be possible to read the busy flag since it is not possible to read the
display either.

Fortunately, there is a simple solution. After sending a character or a command it is important to


give the LCD enough time to do its job. Owing to the fact that execution of the slowest
command lasts for approximately 1.64mS, it will be sufficient to wait approximately 2mS for
LCD.
LCD Initialization
The LCD is automatically cleared when powered up. It lasts for approximately 15mS. After that,
the display is ready for operation. The mode of operation is set by default. It means that:
1. Display is cleared
2. Mode
o

DL = 1 Communication through 8-bit interface

N = 0 Messages are displayed in one line

F = 0 Character font 5 x 8 dots

3. Display/Cursor on/off
o

D = 0 Display off

U = 0 Cursor off

B = 0 Cursor blink off

4. Character entry
o

ID = 1 Displayed addresses are automatically incremented by 1

S = 0 Display shift off

Automatic reset is in most cases performed without any problems. In most cases, but not always!
If for any reason the power supply voltage does not reach ful value within 10mS, the display will
start to perform completely unpredictably. If the voltage supply unit is not able to meet this
condition or if it is needed to provide completely safe operation, the process of initialization is
applied. Initialization, among other things, causes a new reset enabling display to operate
normally.
Refer to the figure below for the procedure on 8-bit initialization:

It is not a mistake!
In this algorithm, the same value is transferred three times in a row.
In case of 4-bit initialization, the procedure is as follows:

6.3 Examples
The schematic below is used in the several following examples:

Apart from components necessary for the operation of the microcontroller such as oscillator with
capacitors and the simplest reset circuit, there are also several LEDs and one push button. These
are used to indicate the operation of the program.
All LEDs are polarized in such a way that they are activated by driving a microcontroller pin low
(logic 0).
LED Blinking

The purpose of this example is not to demonstrate the operation of LEDs, but the operating speed
of the microcontroller. Simply put, in order to enable LED blinking to be visible, it is necessary
to provide sufficient amount of time to pass between on/off states of LEDs. In this example time
delay is provided by executing a subroutine called Delay. It is a triple loop in which the program
remains for approximately 0.5 seconds and decrements values stored in registers R0, R1 or R2.
After returning from the subroutine, the pin state is inverted and the same procedure is repeated...
;************************************************************************
;* PROGRAM NAME : Delay.ASM
;* DESCRIPTION: Program turns on/off LED on the pin P1.0
;* Software delay is used (Delay).
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(DELAY.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG
STACK_START:

AT
DS

;RESET VECTORS
CSEG
JMP

AT
0
XRESET

ORG
XRESET: MOV
MOV
LOOP:

03FH
040H

;Reset vector

100H
SP,#STACK_START
P1,#0FFh

;Define Stack pointer


;All pins are configured as inputs

CPL
LCALL
SJMP

P1.0
Delay
LOOP

;Pin P1.0 state is inverted


;Time delay

MOV
MOV
MOV
DJNZ
DJNZ
DJNZ

R2,#20
R1,#50
R0,#230
R0,$
R1,F01
R2,F02

;500 ms time delay


;25 ms

Delay:
F02:
F01:

END

;End of program

Using Watch-dog Timer


This example describes how the watch-dog timer should not operate. The watch-dog timer is
properly adjusted (nominal time for counting is 1024mS), but instruction used to reset it is
intentionally left out so that this timer always "wins". As a result, the microcontroller is reset

(state in registers remains unchanged), program starts execution from the beginning and the
number in register R3 is incremented by 1 and then copied to port P1.
LEDs display this number in binary format...
;************************************************************************
;* PROGRAM NAME : WatchDog.ASM
;* DESCRIPTION : After watch-dog reset, program increments number in
;* register R3 and shows it on port P1 in binary format.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(WATCHDOG.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
WMCON
WDTEN
PERIOD
1024ms

DATA
EQU
EQU

96H
00000001B
11000000B

; Watch-dog timer is enabled


; Nominal Watch-dog period is set to be

;RESET

VECTOR
CSEG
JMP

AT
XRESET

; Reset vector

CSEG
ORG

100H

ORL
ORL

WMCON,#PERIOD
WMCON,#WDTEN

; Define Watch-dog period


; Watch-dog timer is enabled

MOV
MOV
INC

A,R3
P1,A
R3

; R3 is moved to port 1

SJMP

LAB

; Wait for watch-dog reset

XRESET:

LAB:

END

; Register R3 is incremented by 1

; End of program

Timer T0 in mode 1
This program spends most of its time in an endless loop waiting for timer T0 to count up a full
cycle. When it happens, an interrupt is generated, routine TIM0_ISR is executed and logic zero
(0) on port P1 is shifted right by one bit. This is another way of demonstrating the operating
speed of the microcontroller since each shift means that counter T0 has counted up 216 pulses!
;************************************************************************
;* PROGRAM NAME : Tim0Mod1.ASM
;* DESCRIPTION: Program rotates "0" on port 1. Timer T0 in mode 1 is
;* used
;************************************************************************

;BASIC DIRECTIVES
$MOD53
$TITLE(TIM0MOD1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;DECLARATION OF VARIABLES
;STACK
DSEG
STACK_START:

AT
DS

03FH
040H

;RESET VECTORS
CSEG
JMP

AT 0
XRESET

; Reset vector

ORG
JMP

00BH
TIM0_ISR

; Timer T0 reset vector

ORG

100H

XRESET: MOV
MOV
MOV
MOV
SETB
MOV
CLR

SP,#STACK_START
TMOD,#01H
A,#0FFH
P1,#0FFH
TR0
IE,#082H
C

; Define Stack pointer


; MOD1 is selected

LOOP1: SJMP

LOOP1

; Remain here

TIM0_ISR:

RRC
MOV

PORT1

RETI
END

A
P1,A

; Timer T0 is enabled
; Interrupt enabled

; Rotate accumulator A through Carry flag


; Contents of accumulator A is moved to
; Return from interrupt
; End of program

Timer T0 in Split mode


Similarly to the previous example, the program spends most of its time in a loop called LOOP1.
Since 16-bit Timer T0 is split into two 8-bit timers, there are also two interrupt sources.
The first interrupt is generated after timer T0 reset. Routine TIM0_ISR in which logic zero (0)
bit on port P1 rotates is executed. Outside looking, it seems that LEDs move.
Another interrupt is generated upon Timer T1 reset. Routine TIM1_ISR in which the bit state
DIRECTION inverts is executed. Since this bit determines direction of bit rotation then the
moving direction of LED is also changed.

If you press a push button T1 at some point, a logic zero (0) on the P3.2 output will disable
Timer T1.
;************************************************************************
;* PROGRAM NAME : Split.ASM
;* DESCRIPTION: Timer TL0 rotates bit on port P1, while TL1 determines
;* the rotation direction. Both timers operate in mode
;* 3. Logic zero (0) on output P3.2 disables rotation on port P1.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(SPLIT.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;DECLARATION OF VARIABLES
BSEG

AT

;DECLARATION OF BIT-VARIABLES
SEMAPHORE:
DIRECTION

DBIT
BIT

8
SEMAPHORE

;STACK
DSEG
STACK_START:

AT
DS

03FH
040H

;RESET VECTORS
CSEG
JMP
ORG

AT
0
XRESET
00BH

; Reset vector

JMP

TIM0_ISR

; Timer T0 reset vector

ORG
JMP

01BH
TIM1_ISR

; Timer T1 reset vector

ORG
XRESET: MOV
MOV
MOV
MOV
MOV
SETB
SETB
MOV
CLR
CLR

100H
SP,#STACK_START
TMOD,#00001011B
A,#0FFH
P1,#0FFH
R0,#30D
TR0
TR1
IE,#08AH
C
DIRECTION

LOOP1:

LOOP1

SJMP

; Define Stack pointer


; Define MOD3

; TL0 is turned on
; TL1 is turned on
; Interrupt enabled
; Rotate to the right
; Remain here

TIM0_ISR:
DJNZ
R0,LAB3
JB
DIRECTION,LAB1
RRC
A
the right through

; Slow down rotation by 256 times


; Rotate contents of Accumulator to
; Carry flag

SJMP
LAB2
LAB1:
RLC
A
the left through
LAB2:
MOV
to port P1
LAB3:
RETI
TIM1_ISR:
DJNZ
256 times
DJNZ
direction
CPL
MOV
LAB4:
RETI

P1,A

; Rotate contents of Accumulator to


; Carry flag
; Contents of Accumulator is moved
; Return from interrupt

R1,LAB4

; Slow down direction of rotation by

R2,LAB4

; When time expires, change rotation

SMER
R2,#30D

END

; End of program

Simultaneous use of timers T0 and T1


This program can be considered as continuation of the previous one. They share the same idea,
but in this case true timers T0 and T1 are used. In order to demonstrate the operation of both
timers on the same port at the same time, timer T0 reset is used to shift logic zero (0) on the port,
while Timer T1 reset is used to change rotation direction. This program spends most of its time
in the loop LOOP1 waiting for an interrupt to be caused by reset. By checking the DIRECTION
bit, information on rotation direction of both bits in accumulator as well as of moving port LED
is obtained.
;************************************************************************
;* PROGRAM NAME : Tim0Tim1.ASM
;* DESCRIPTION: Timer TO rotates bit on port P1 while Timer1
;* changes rotation direction. Both timers are configured to operate in mode
1.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(TIM0TIM1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;DECLARATION OF VARIABLES

BSEG

AT

;DECLARATION OF BIT-VARIABLES
SEMAPHORE:
DIRECTION
;STACK

DSEG
STACK_START:

DBIT
BIT
AT
DS

8
SEMAPHORE
03FH
040H

;RESET VECTORS
CSEG
AT
0
JMP
XRESET

; Reset vector

ORG
JMP

00BH
TIM0_ISR

; Timer 0 Reset vector

ORG
JMP

01BH
TIM1_ISR

; Timer 1 Reset vector

ORG

100H

XRESET: MOV
MOV
MOV
MOV
MOV
SETB
SETB
MOV
enabled
CLR
CLR

SP,#STACK_START
TMOD,#11H
A,#0FFH
P1,#0FFH
R0,#30D
TR0
TR1
IE,#08AH
C
DIRECTION

; Rotate to the right

LOOP1:

LOOP1

; Remain here

SJMP

TIM0_ISR:
JB
DIRECTION,LAB1
RRC A
the right through
SJMP
LAB2
LAB1:
RLC
A
the left through
LAB2:
MOV
to port P1
RETI
TIM1_ISR:
DJNZ
direction
CPL

P1,A

; Define Stack pointer


; Select MOD1 for both timers
;
;
;
;

R0 is initialized
TIMER0 is turned on
TIMER1 is turned on
Timer0 and Timer1 Interrupt

; Rotate contents of accumulator to


; Carry flag
; Rotate contents of Accumulator to
; Carry flag
; Contents of Accumulator is moved
; Return from interrupt

R0,LAB3
DIRECTION

; When time expires, change rotation

LAB3:

MOV
RETI
END

R0,#30D

; Initialize R0
; End of program

Using Timer T2
This example describes the use of Timer T2 configured to operate in Auto-Reload mode. In this
very case, LEDs are connected to port P3 while the push button used for forced timer reset
(T2EX) is connected to the P1.1 pin.
Program execution is similar to the previous examples. When timer ends counting, an interrupt is
enabled and subroutine TIM2_ISR is executed, thus rotating a logic zero (0) in accumulator and
moving the contents of accumulator to the P3 pin. At last, flags which caused an interrupt are
cleared and program returns to the loop LOOP1 where it remains until a new interrupt request
arrives...
If push button T2EX is pressed, timer is temporarily reset. This push button resets timer, while
push button RESET resets the microcontroller.

;************************************************************************
;* PROGRAM NAME : Timer2.ASM
;* DESCRIPTION: Program rotates log. "0" on port P3. Timer2 determines
;* the speed of rotation and operates in auto-reload mode

;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(TIMER2.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;DEFINITION OF VARIABLES
T2MOD

DATA

0C9H

DSEG
STACK_START:

AT
DS

03FH
040H

;RESET VECTORS
CSEG
JMP

AT
XRESET

;STACK

ORG
JMP

02BH
TIM2_ISR

ORG

100H

; Reset vector
; Timer T2 Reset vector

XRESET: MOV
MOV
MOV
MOV
MOV
CLR
SETB
SETB
MOV
CLR

SP,#STACK_START
A,#0FFH
P3,#0FFH
RCAP2L,#0FH
RCAP2L,#01H
CAP2
EXEN2
TR2
IE,#0A0H
C

; Define Stack pointer

LOOP1:

LOOP1

; Remain here

SJMP

TIM2_ISR:
RRC
the right through
to PORT3

; Prepare 16-bit auto-reload mode


;
;
;
;

Enable 16-bit auto-reload mod


Pin P1.1 reset is enabled
Enable Timer T2
Interrupt is enabled

; Rotate contents of Accumulator to

MOV

P3,A

; Carry flag
; Move the contents of Accumulator A

CLR
CLR
RETI

TF2
EXF2

END

Using External Interrupt

; Clear timer T2 flag TF2


; Clear timer T2 flag EXF2
; Return from interrupt
; End of program

Here is another example of interrupt execution. An external iterrupt is generated when a logic
zero (0) is present on pin P3.2 or P3.3. Depending on which input is active, one of two routines
will be executed:
A logic zero (0) on the P3.2 pin initiates execution of interrupt routine Isr_Int0, thus
incrementing number in register R0 and copying it to port P0. Logic zero on the P3.3 pin initiates
execution of subroutine Isr_Int1, number in register R1 is incremented by 1 and then copied to
port P1.
In short, each press on push buttons INT0 and INT1 will be counted and immediately shown in
binary format on appropriate port (LED which emitts light represents a logic zero (0)).

;************************************************************************
;* PROGRAM NAME : Int.ASM
;* DESCRIPTION : Program counts interrupts INT0 generated by appearance of
high-to-low
;* transition signal on pin P3.2 Result appears on port P0. Interrupts INT1
are also
;* counted up at the same time. They are generated byappearing high-to-low
transition
;* signal on pin P3. The result appears on port P1.

;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(INT.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;RESET VECTORS
CSEG
JMP

AT
0
XRESET

ORG
003H
JMP
Isr_Int0
ORG 013H
JMP
Isr_Int1
ORG
MOV
appearing

TCON,#00000101B

; Interrupt routine address for INT1

; Interrupt INT0 is generated by


; high-to-low transition signal on pin

P3.2

; Interrupt INT0 is generated by

appearing

LOOP:

; Interrupt routine address for INT0

100H

XRESET:

P3.3

; Reset vector

; high-to-low transition signal on pin

MOV
MOV
MOV
MOV
MOV

IE,#10000101B
R0,#00H
R1,#00H
P0,#00H
P1,#00H

; Interrupt enabled
; Counter starting value

SJMP

LOOP

; Remain here

Isr_Int0:
INC R0
counter
MOV P0,R0
RETI
Isr_Int1:
INC R1
counter
MOV P1,R1
RETI
END

Using LED display

; Reset port P0
; Reset port P1

; Increment value of interrupt INT0

; Increment value of interrupt INT1

; End of program

The following examples describe the use of LED displays. Common chatode displays are used
here, which means that all built-in LEDs are polarized in such a way that their anodes are
connected to the microcontroller pins. Since the common way of thinking is that logic one (1)
turns something on and logic zero (0) turns something of, Low Current displays (low power
consumption) and their diodes (segments) are connected serially to resistors of relatively high
resistance.
In order to save I/O pins, four LED displays are connected to operate in multiplex mode. It
means that all segments having the same name are connected to one output port each and only
one display is active at a time.
Tranzistors and segmenats on displays are quickly activated, thus making impression that all
digits are active simultaneously.

Writing digits on LED display


This program is a kind of warming up exerciese before real work starts. The purpose of this
example is to display something on any display. Multiplex mode is not used this time. Instead,
digit 3 is displayed on only one of them (first one on the right).
Since the microcontroller does not know how we write number 3, a small subroutine called
Disp is used (the microcontroller writes this number as 0000 0011). This subroutine enables all
decimal digits (0-9) to be displayed (masked). The principle of operation is simple. A number to
be displayed is added to the current address and program jump is executed. Different numbers
require different jump length. Precisely determined combination of zeroes and ones appears on

each of these new locations (digit 1 mask, digit 2 mask...digit 9 mask). When this combination is
transferred to the port, the display shows desired digit.
;************************************************************************
;* PROGRAM NAME : 7Seg1.ASM
;* DESCRIPTION: Program displays number "3" on 7-segment LED display
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK

DSEG
STACK_START:

AT
DS

;RESET VECTORS
CSEG
JMP

AT
0
XRESET

XRESET:

LOOP:
number

03FH
040H

; Reset vector

ORG

100H

MOV
MOV
MOV

SP,#STACK_START
P1,#0
P3,#20h

; Define Stack pointer


; Turn off all segments on displays
; Activate display D4

MOV
LCALL

A,#03
Disp

; Send number 3 to display


; Perform appropriate masking for the

MOV
SJMP

P1,A
LOOP

INC
MOVC
RET
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB
END

A
A,@A+PC

Disp:

; Subroutine for displaying digits

3FH
06H
5BH
4FH
66H
6DH
7DH
07H
7FH
6FH

Writing and changing digits on LED display

;
;
;
;
;
;
;
;
;
;
;

Digit 0 mask
Digit 1 mask
Digit 2 mask
Digit 3 mask
Digit 4 mask
Digit 5 mask
Digit 6 mask
Digit 7 mask
Digit 8 mask
Digit 9 mask
End of program

This program is only an extended verson of the previous one. There is only one digit active- the
first one on the right, and there is no use of multiplexing. Unlike the previous example, all
decimal numbers are displayed (0-9). In order to enable digits to change at reasonable pace, a
soubroutine L2 which causes a short time delay is executed prior to each change occurs.
Basically, the whole process is very simple and takes place in the main loop called LOOP which
looks as follows:
1. R3 is copied to Accumulator and subroutine for masking digits Disp is executed;
2. Accumulator is copied to the port and displayed;
3. The contents of the R3 register is incremented;
4. It is checked whether 10 cycles are counted or not. If it is, register R3 is reset in order to
enable counting to start from 0; and
5. Instruction labeled as L2 within subroutine is executed.
;************************************************************************
;* PROGRAM NAME: 7Seg2.ASM
;* DESCRIPTION: Program writes numbers 0-9 on 7-segment LED display
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG2.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK

DSEG
STACK_START:

AT
DS

03FH
040H

;RESET VECTORS
CSEG
JMP

AT
0
XRESET

; Reset vector

100H

MOV
MOV
MOV
MOV

SP,#STACK_START
R3,#0
P1,#0
P3,#20h

;
;
;
;

MOV
LCALL

A,R3
Disp

; Perform appropriate masking for

XRESET:

ORG

Define Stack pointer


Counter initial value
Turn off all display segments
Activate display D4

LOOP:
number in

; Accumulator
MOV
INC

P1,A
R3

; Increment number in register by 1

R3
L2:
F02:
F01:

Disp:

CJNE

R3,#10,L2

; Check whether the number 10 is in

MOV

R3,#0

; If it is, reset counter

MOV
MOV
MOV
DJNZ
DJNZ
DJNZ
SJMP

R2,#20
R1,#50
R0,#230
R0,$
R1,F01
R2,F02
LOOP

; 500 mS time delay


; 25 mS

INC
MOVC
RET
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB

A
A,@A+PC
3FH
06H
5BH
4FH
66H
6DH
7DH
07H
7FH
6FH

END

; Subroutine for writing digits

;
;
;
;
;
;
;
;
;
;

Digit
Digit
Digit
Digit
Digit
Digit
Digit
Digit
Digit
Digit

0
1
2
3
4
5
6
7
8
9

mask
mask
mask
mask
mask
mask
mask
mask
mask
mask

; End of program

Writing two-digit number on LED display


It is time for time multiplexing! This is the simplest example which displays the number 23 on
two displays in such a way that one of them displays units, while the other displays tens. The
most important thing in the program is time synchronization. Otherwise, everything is very
simple. Transistor T4 enables display D4 and at the same time a bit combination corresponding
to the digit 3 is set on the port. After that, transistor T4 is disabled and the whole process is
repeated using transistor T3 and display D3 in order to display digit 2. This procedure must be
continuosly repeated in order to make impression that both displays are active at the same time.
;************************************************************************
;* PROGRAM NAME: 7Seg3.ASM
;* DESCRIPTION: Program displays number "23" on 7-segment LED display
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG3.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK

DSEG
STACK_START:

AT
DS

03FH
040H

;RESET VECTORS
CSEG
JMP

AT
XRESET

XRESET:
LOOP:

digit

; Reset vector

ORG
MOV

100H
SP,#STACK_START

; Define Stack pointer

MOV
MOV
MOV
LCALL

P1,#0
P3,#20h
A,#03
Disp

;
;
;
;

Turn off all display segments


Activate display D4
Write digit 3 on display D4
Find appropriate mask for that

MOV
MOV
MOV
MOV
LCALL
MOV
SJMP

P1,A
P1,#0
P3,#10h
A,#02
Disp
P1,A
LOOP

;
;
;
;
;
;
;

Put the mask on the port


Turn off all dislay segments
Activate display D3
Write digit 2 on display D3
Find mask for that digit
Put the mask on the port
Return to the label LOOP

INC
MOVC
RET
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB

A
A,@A+PC

Disp:

; Subroutine for writing digits

3FH
06H
5BH
4FH
66H
6DH
7DH
07H
7FH
6FH

END

;
;
;
;
;
;
;
;
;
;

Digit
Digit
Digit
Digit
Digit
Digit
Digit
Digit
Digit
Digit

0
1
2
3
4
5
6
7
8
9

mask
mask
mask
mask
mask
mask
mask
mask
mask
mask

; End of program

Using four digit LED display


In this example all four displays, instead of two, are active so that it is possible to write numbers
from 0 to 9999. Here, the number 1 234 is displayed. After initialization, the program remains in
the loop LOOP where digital multiplexing is performed. The subroutine Disp is used to convert
binary numbers into corresponding combinations of bits for the purpose of activating display
lighting segments.
;************************************************************************
;* PROGRAM NAME : 7Seg5.ASM
;* DESCRIPTION : Program displays number"1234" on 7-segment LED display
;************************************************************************
;BASIC DIRECTIVES

$MOD53
$TITLE(7SEG5.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK
DSEG
STACK_START:

AT
DS

03FH
040H

;RESET VECTORS
CSEG
JMP

AT
0
XRESET

; Reset vector

ORG

100H

XRESET:

MOV

SP,#STACK_START

; Define Stack pointer

LOOP:

MOV
MOV
MOV
LCALL
MOV
MOV
MOV
MOV
LCALL
MOV
MOV
MOV
MOV
LCALL
MOV
MOV
MOV
MOV
LCALL
MOV
SJMP

P1,#0
P3,#20h
A,#04
Disp
P1,A
P1,#0
P3,#10h
A,#03
Disp
P1,A
P1,#0
P3,#08h
A,#02
Disp
P1,A
P1,#0
P3,#04h
A,#01
Disp
P1,A
LOOP

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

INC
MOVC
RET
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB

A
A,@A+PC

Disp:

Turn off all display segments


Activate display D4
Write digit 4 on display D4
Find mask for that digit
Put the mask on the port
Turn off all display segments
Activate display D3
Write digit 3 on display D3
Find mask for that digit
Put the mask on the port
Turn off all display segments
Activate display D2
Write digit 2 on display D2
Find mask for that digit
Put the mask on the port
Turn off all display segments
Activate display D1
Write digit 1 on display D1
Find mask for that digit
Put the mask on the port
Return to the lable LOOP

; Subroutine for writing digits

3FH
06H
5BH
4FH
66H
6DH
7DH
07H
7FH
6FH

END ; End of program

;
;
;
;
;
;
;
;
;
;

Digit
Digit
Digit
Digit
Digit
Digit
Digit
Digit
Digit
Digit

0
1
2
3
4
5
6
7
8
9

mask
mask
mask
mask
mask
mask
mask
mask
mask
mask

LED display as a two digit counter


Things are getting complicated... In addition to two digit multiplexing, the microcontroller also
performs other operations. In this example, contents of registers R2 and R3 are incremented in
order to display number counting (97, 98, 99, 00, 01, 02...).
This time, transistors which activate displays remain turned on for 25mS. The soubroutine Delay
is in charge of that. Even though digits shift much slower now, it is still not slow enough to make
impression of simultaneous operation. After both digits of a number blink for 20 times, the
number on displays is incremented by 1 and the whole procedure is repeated.
;************************************************************************
;* PROGRAM NAME : 7Seg4.ASM
;* DESCRIPTION: Program displays numbers 0-99 on 7-segment LED displays
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(7SEG4.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK

DSEG
STACK_START:

AT
DS

03FH
040H

;RESET VECTORS
CSEG
JMP

AT
XRESET

XRESET:

ORG

100H

MOV
MOV
MOV
MOV

SP,#STACK_START
R2,#0
R3,#0
R4,#0

LOOP:
INC
R4
"refreshed" for 100 times
CJNE
R4,#20d,LAB1
MOV
R4,#0
MOV
P1,#0
INC
R2
units by 1
CJNE
R2,#10d,LAB1
MOV
R2,#0
INC
R3
1
CJNE
R3,#10d,LAB1
MOV
R3,#0

; Reset vector

; Define Stack pointer


; Counter starting value

;Wait for display to be


;before incrementing the counter
; Turn off all display segments
; Increment Register containing
; Reset units
; Increment Register with tens by
;
; Reset tens

LAB1:
to A

Delay:
F01:

MOV
MOV

P3,#20h
A,R2

; Activate display D4
; Copy Register containing units

LCALL
MOV
LCALL
MOV
MOV
MOV

Disp
P1,A
Delay
P1,#0
P3,#10h
A,R3

;
;
;
;
;
;

LCALL
MOV
LCALL
SJMP

Disp
P1,A
Delay
LOOP

; Call mask for that digit


; Write tens on display D3
; 25ms delay

MOV
MOV
DJNZ
DJNZ
RET

R1,#50
R0,#250
R0,$
R1,F01

; 5 ms delay

INC
MOVC
RET
DB
DB
DB
DB
DB
DB
DB
DB
DB
DB

A
A,@A+PC

Disp:

Call mask for that digit


Write units on display D4
25ms delay
Turn off all display segments
Activate display D3
Copy Register contaning tens to

; Subroutine for displaying digits

END

3FH
06H
5BH
4FH
66H
6DH
7DH
07H
7FH
6FH

;
;
;
;
;
;
;
;
;
;

Digit
Digit
Digit
Digit
Digit
Digit
Digit
Digit
Digit
Digit

0
1
2
3
4
5
6
7
8
9

mask
mask
mask
mask
mask
mask
mask
mask
mask
mask

; End of program

Handling EEPROM
This program writes data to on-chip EEPROM memory. In this case, the data is a hexadecimal
number 23 which is to be written to the location with address 00.
To make sure that this number is correctly written, the same location of EEPROM is read 10mS
later in order to compare these two numbers. If they match, F will be displayed. Otherwise, E
will be displayed on the LED display (Error).
;************************************************************************
;* PROGRAM NAME: EEProm1.ASM
;* DESCRIPTION: Programming EEPROM at address 0000hex and displaying message
;* on LED display.
;************************************************************************

;BASIC DIRECTIVES
$MOD53
$TITLE(EEPROM1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
WMCON
EEMEN
enabled
EEMWE
TEMP

DATA
EQU

96H
00001000B

; Access to internal EEPROM is

EQU
DATA

00010000B
030H

; Write to EEPROM is enabled


; Define Auxiliary register

THE END
ERROR

EQU
EQU

071H
033H

; Display "F"
; Display "E"

;STACK
DSEG
STACK_START:

AT
DS

;RESET VECTORS
CSEG
JMP

AT
0
XRESET

XRESET:

to

to TEMP,
ERROR

LOOP1:
ERROR:
LOOP2:
DELAY:
LOOP3:

03FH
040H

; Reset vector

ORG

100H

MOV
MOV

IE,#00
SP,#STACK_START

; All interrupts are disabled

MOV
ORL
ORL
MOV

DPTR,#0000H
WMCON,#EEMEN
WMCON,#EEMWE
TEMP,#23H

;
;
;
;

Choose location address in EEPROM


Access to EEPROM is enabled
Write to EEPROM is enabled
Number written to EEPROM is moved

MOV
MOVX
CALL
MOVX

A,TEMP
@DPTR,A
DELAY
A,@DPTR

;
;
;
;

register TEMP and Accumulator


Write byte to EEPROM
10ms delay
Read the same location and compare

CJNE

A,TEMP,ERROR

; If they don't match, jump to label

MOV
MOV
XRL
XRL
SJMP

A,#KRAJ
P1,A
WMCON,#EEMWE
WMCON,#EEMEN
LOOP1

; Display F (correct)

MOV
MOV
SJMP

A,#ERROR
P1,A
LOOP2

; Display E (error)

MOV
MOV
NOP

A,#0AH
R3,A

; Delay

; Write to EEPROM is disabled


; Access to EEPROM is disabled
; Remain here

LOOP4:
LOOP5:

DJNZ
DJNZ
DJNZ
RET

B,LOOP4
B,LOOP5
R3,LOOP3

END

; End of program

Data reception via UART


In order to enable successful UART serial communication, it is necessary to meet specific rules
of the RS232 standard. It primarily refers to voltage levels required by this standard.
Accordingly, -10V stands for logic one (1) in the message, while +10V stands for logic zero (0).
The microcontroller converts accurately data into serial format, but its power supply voltage is
only 5V. Since it is not easy to convert 0V into 10V and 5V into -10V, this operation is on both
transmit and receive side left to a specialized IC circuit. Here, the MAX232 by MAXIM is used
because it is widespread, cheap and reliable.
This example shows how to receive message sent by a PC. Timer T1 generates boud rate. Since
the 11.0592 MHz quartz crystal is used here, it is easy to obtain standard baud rate which amouts
to 9600 bauds. Each received data is immediately transferred to port P1 pins.

;************************************************************************
;* PROGRAM NAME : UartR.ASM
;* DESCRIPTION: Each data received from PC via UART appears on the port
;* P1.
;*
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(UARTR.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK

DSEG
STACK_START:
;RESET VECTORS
CSEG
JMP
ORG
routine
JMP

AT
DS

03FH
040H

AT
0
XRESET
023H

; Reset vector
; Starting address of UART interrupt

IR_SER

ORG

100H

MOV
MOV
MOV
MOV

IE,#00
SP,#STACK_START
TMOD,#20H
TH1,#0FDH

MOV
MOV
CLR
CLR
SETB

SCON,#50H
IE,#10010000B
TI
RI
TR1

;
;
;
;
;
;
;
;
;
;

LOOP:

SJMP

LOOP

; Remain here

IR_SER:

JNB

RI,OUTPUT

OUTPUT

MOV
MOV
CLR
RETI

A,SBUF
P1,A
RI

; If any data is received,


; move it to the port
; P1

XRESET:

END

All interrupts are disabled


Initialization of Stack pointer
Timer1 in mode2
9600 baud rate at the frequency of
11.0592MHz
Receiving enabled, 8-bit UART
UART interrupt enabled
Clear transmit flag
Clear receive flag
Start Timer1

; Clear receive flag


; End of program

Data transmission via UART


This program describes how to use UART to transmit data. A sequence of numbers (0-255) is
transmitted to a PC at 9600 baud rate. The MAX 232 is used as a voltage regulator.

;************************************************************************
;* PROGRAM NAME : UartS.ASM
;* DESCRIPTION: Sends values 0-255 to PC.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(UARTS.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK

DSEG
STACK_START:

AT
DS

;RESET VECTORS
CSEG
JMP

AT
0
XRESET

XRESET:

START:
LOOP1:

03FH
040H

ORG

100H

MOV
MOV
MOV
MOV

IE,#00
SP,#STACK_START
TMOD,#20H
TH1,#0FDH

MOV
CLR
CLR
MOV
SETB

SCON,#40H
TI
RI
R3,#00H
TR1

MOV
JNB

SBUF,R3
TI,LOOP1

CLR
INC
CJNE

;
;
;
;
;
;
;
;
;
;

All interrupts are disabled


Initialization of Stack pointer
Timer1 in mode 2
9600 baud rate at the frequency of
11.0592MHz
8-bit UART
Clear transmit bit
Clear receive flag
Reset caunter
Start Timer 1

TI
R3

;
;
;
;
;

Move number from counter to a PC


Wait here until byte transmission is
complete
Clear transmit bit
Increment the counter value by 1

R3,#00H,START

; If 255 bytes are not sent return to

the
LOOP:

; Reset vector

; label START
SJMP

LOOP

END

; Remain here
; End of program

Writing message on LCD display


This example uses the most frequently used type of LCD which displays text in two lines with 16
characters each. In order to save I/O ports, only 4 pins are used for communication here. In this
way each byte is transmitted in two steps: first higher then lower nible.

LCD needs to be initialized at the beginning of the program. Besides, parts of the program which
repeat in the program create special subroutines. All this may seem extremely complicated, but
the whole program basically performs several simple operations and displays
Mikroelektronika Razvojni sistemi.

*************************************************************************
;* PROGRAM NAME : Lcd.ASM
;* DESCRIPRTION : Program for testing LCD display. 4-bit communication
;* is used. Program does not check BUSY flag but uses program delay
;* between 2 commands. PORT1 is used for connection
;* to the microcontroller.
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(LCD.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;Stack
DSEG
Stack_Start:

AT
DS

0E0h
020h

Start_address

EQU

0000h
;Reset vectors

Inic:

CSEG
ORG
JMP

AT
0
Start_address
Inic

ORG

Start_address+100h

MOV
MOV

IE,#00
SP,#Stack_Start

; All interrupts are disabled

CALL

LCD_inic

; Initialize LCD

;*************************************************
;* MAIN PROGRAM
;*************************************************
START:
MOV
the first
CALL
LCD display.
MOV
CALL
transmission.
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
the first

CALL
LCD display.

A,#80h

; Next character will appear on

LCD_status

; location in the first line of

A,#'M'
LCD_putc

; Display character M.
; Call subroutine for character

A,#'i'
LCD_putc
A,#'k'
LCD_putc
A,#'r'
LCD_putc
A,#'o'
LCD_putc
A,#'e'
LCD_putc
A,#'l'
LCD_putc
A,#'e'
LCD_putc
A,#'k'
LCD_putc
A,#'t'
LCD_putc
A,#'r'
LCD_putc
A,#'o'
LCD_putc
A,#'n'
LCD_putc
A,#'i'
LCD_putc
A,#'k'
LCD_putc
A,#'a'
LCD_putc

; Display character i.

A,#0c0h

; Next character will appear on

LCD_status

; location in the second line of

; Display character k.
; Display character r.
; Display character o.
; Display character e.
; Display character l.
; Display character e.
; Display character k.
; Display character t.
; Display character r.
; Display character o.
; Display character n.
; Display character i.
; Display character k.
; Display character a.

MOV
CALL
transmission.
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
CALL
MOV
MOV
CALL
MOV
CALL
JMP

A,#'R'
LCD_putc

; Display character R.
; Call subroutine for character

A,#'a'
LCD_putc
A,#'z'
LCD_putc
A,#'v'
LCD_putc
A,#'o'
LCD_putc
A,#'j'
LCD_putc
A,#'n'
LCD_putc
A,#'i'
LCD_putc
A,#' '
LCD_putc
A,#'s'
LCD_putc
A,#'i'
LCD_putc
A,#'s'
LCD_putc
A,#'t'
LCD_putc
A,#'e'
LCD_putc
A,#'m'
LCD_putc
A,#'i'
LCD_putc

; Display character a.

R0,#20d
Delay_10ms
DPTR,#LCD_DB
A,#6d
LCD_inic_status
R0,#10d
Delay_10ms
START

; Wait time (20x10ms)


;
; Clear display
;
;
; Wait time(10x10ms)

; Display character z.
; Display character v.
; Display character o.
; Display character j.
; Display character n.
; Display character i.
; Display character .
; Display character s.
; Display character i.
; Display character s.
; Display character t.
; Display character e.
; Display character m.
; Display character i.

;*********************************************
;* Subroutine for wait time (T= r0 x 10ms)
;*********************************************
Delay_10ms: MOV
approximately
MOV
MOV
DJNZ
instruction.
DJNZ
DJNZ
RET

R5,00h

; 1+(1+(1+2*r7+2)*r6+2)*r5

R6,#100d
R7,#100d
R7,$

; (if r7>10)
; 2*r5*r6*r7
; $ indicates current

R6,$-4
R5,$-6

;
******************************************************************************
********
;* SUBROUTINE: LCD_inic
;* DESCRIPTION: Subroutine for LCD initialization.
;*
;* (is used with 4-bit interface, under condition that pins DB4-7 on LCD
;* are connected to pins PX.4-7 on microcontrollers ports, i.e. four higher
;* bits on the port are used).
;*
;* NOTE: It is necessary to define port pins for controlling LCD operation:
;* LCD_enable, LCD_read_write, LCD_reg_select,similar to port for connection
to LCD.
;* It is also necessary to define addresses for the first character in each
;* line.
;
******************************************************************************
********
LCD_enable
LCD.
LCD_read_write
LCD.
LCD_reg_select
LCD.
LCD_port
Busy
appears.

BIT

P1.3

; Bit for activating pin E on

BIT

P1.1

; Bit for activating pin RW on

BIT

P1.2

; Bit for activating pin RS on

SET
BIT

P1
P1.7

; Port for connection to LCD.


; Port pin on which Busy flag

00h

; Address of the first message

LCD_Start_I_red
character

EQU

; in the first line of LCD

display.
LCD_Start_II_red EQU
character

40h

; Address of the first message


; in the second line of LCD

display.
LCD_DB:
format

DB

00111100b

; 0 -8b, 2/1 lines, 5x10/5x7

DB

00101100b

; 1 -4b, 2/1 lines, 5x10/5x7

DB

00011000b

; 2 -Display/cursor shift,

DB
cursor blink off
DB
shift off
DB
DB
DB
cursor blink off

00001100b

; 3 -Display ON, cursor OFF,

00000110b

; 4 -Increment mode, display

00000010b
00000001b
00001000b

; 5 -Display/cursor home
; 6 -Clear display
; 7 -Display OFF, cursor OFF,

format
right/left

LCD_inic:
;*****************************************
MOV

DPTR,#LCD_DB

beginning
supply is on

MOV
CALL

A,#00d
LCD_inic_status_8

; Triple initialization in 8-bit


; mode is performed at the

MOV
CALL

A,#00d
LCD_inic_status_8

; (in case of slow increment of


; power supply when the power

MOV
A,#00d
lcall LCD_inic_status_8
MOV
CALL
MOV
CALL

A,#1d
LCD_inic_status_8
A,#1d
LCD_inic_status

; Change from 8-bit into


; 4-bit mode

MOV

A,#3d

; As from this point the program

CALL
MOV
CALL
MOV
CALL

LCD_inic_status
A,#6d
LCD_inic_status
A,#4d
LCD_inic_status

executes in

;4-bit mode

RET
LCD_inic_status_8:
;******************************************
PUSH B

memorized

port

MOVC
CLR
CLR

A,@A+DPTR
LCD_reg_select
LCD_read_write

; RS=0 - Write command


; R/W=0 - Write data on LCD

MOV

B,LCD_port

; Lower 4 bits from LCD port are

ORL
ORL
ANL

B,#11110000b
A,#00001111b
A,B

MOV

LCD_port,A

; Data is moved from A to LCD

SETB

LCD_enable

; high-to-low transition signal


; is generated on the LCD's EN

CLR

LCD_enable

MOV

B,#255d

pin

reset

DJNZ B,$
DJNZ B,$
DJNZ B,$
POP B
RET

; Time delay in case of improper


; during initialization

LCD_inic_status:
;****************************************************************************
MOVC A,@A+DPTR
CALL LCD_status
RET
;****************************************************************************
;* SUBROUTINE: LCD_status
;* DESCRIPTION: Subroutine for defining LCD status.
;****************************************************************************
LCD_status:

PUSH
MOV
DJNZ
DJNZ
DJNZ
CLR
CALL

B
B,#255d
B,$
B,$
B,$
LCD_reg_select
LCD_port_out

SWAP

DJNZ
DJNZ
DJNZ
CLR
CALL

B,$
B,$
B,$
LCD_reg_select
LCD_port_out

POP
RET

; RS=O: Command is sent to LCD


; Nibles are swapped in

accumulator

; RS=0: Command is sent to LCD

;****************************************************************************
;* SUBROUTINE: LCD_putc
;* DESCRIPTION: Sending character to be displayed on LCD.
;****************************************************************************
LCD_putc:

accumulator

PUSH
MOV
DJNZ
SETB
CALL

B
B,#255d
B,$
LCD_reg_select
LCD_port_out

SWAP

; Nibles are swapped in

DJNZ
SETB

B,$
LCD_reg_select

; RS=1: Character is sent to LCD

CALL
POP
RET

LCD_port_out
B

; RS=1: Character is sent to LCD

;****************************************************************************
;* SUBROUTINE: LCD_port_out
;* DESCRIPTION: Sending commands or characters on LCD display
;****************************************************************************

LCD_port_out:
memorized

port

PUSH
PUSH
MOV

ACC
B
B,LCD_port

ORL
ORL
ANL

B,#11110000b
A,#00001111b
A,B

MOV

LCD_port,A

; Data is copied from A to LCD

SETB

LCD_enable

; high-to-low transition signal


; is generated on the LCD's EN

CLR

LCD_enable

POP
POP
RET

B
ACC

; Lower 4 bits of LCD port are

pin

END

; End of program

Binary to decimal number conversion


When using LED and LCD displays, it is often necessary to convert numbers from binary to
decimal. For example, if some register contains a number in binary format that should be
displayed on a three digit LED display it is first necessary to convert it to decimal format. In
other words, it is necessary to define what should be displayed on the most right display (units),
middle display (tens) and most left display (hundreds).
The subroutine below performs conversion of one byte. Binary number is stored in the
accumulator, while digits of that number in decimal format are stored in registers R3, R2 and
accumulator (units, tens and hundreds, respectively).
;************************************************************************
;* SUBROUTINE NAME : BinDec.ASM
;* DESCRIPTION : Content of accumulator is converted into three decimal digits
;************************************************************************
BINDEC:

MOV
DIV
MOV
MOV
DIV
MOV
MOV
DIV
MOV
RET

B,#10d
AB
R3,B
B,#10d
AB
R2,B
B,#10d
AB
A,B

.1 At the end - from the beginning...

;
;
;
;
;
;
;
;
;
;

Store decimal number 10 in B


A:B. Remainder remains in B
Move units to register R3
Store decimal number 10 in B
A:B. Remainder remains in B
Move tens to register R2
Store decimal number 10 in B
A:B. Remainder remains in B
Move hundreds to accumulator
Return to the main program

What is always the most difficult thing to do? You have bought the microcontroller, you have
learned everything about its circuits and registers, you have a great idea how to apply all your
knowledge in practice. But the most difficult thing to do is to start...
How to start working?
A microcontroller is a good-natured genie in the bottle and no extra knowledge is required to
use it.
In order to create a device controlled by the microcontroller, it is necessary to provide the
simplest PC, program for compiling and simple device to transfer the code from PC to the chip
itself.
Even though the whole process is quite logical, there are often some queries, not because it is
complicated, but for numerous variations. Lets take a look.
Writing program in assembly language
In order to write a program for the microcontroller, a specialized program in the Windows
environment may be used. It may, but it does not have to... When using such a software, there are
numerous tools which facilitate the operation (simulator tool comes first), which is an obvious
advantage. But there is also another ways to write a program. Basically, text is the only thing that
matters. Any program for text processing can be used for this purpose. The point is to write all
instructions in such an order they should be executed by the microcontroller, observe the rules of
assembly language and write instructions exactly as they are defined. In other words, you just
have to follow the program idea. Thats all!
;RESET

XRESET:

VECTOR
CSEG
JMP

AT
XRESET

CSEG
ORG

100H

ORL
ORL

WMCON,#PERIOD
WMCON,#WDTEN

0
; Reset vector

; Define Watch-dog period


; Watch-dog timer is enabled

To enable the compiler to operate successfully, it is necessary that a document containing this
program has the extension, .asm in its name, for example: Program asm.
When a specialized program (mplab) is used, this extension will be automatically added. If any
other program for text processing (Notepad) is used then the document should be saved and
renamed. For example: Program.txt -> Program.asm. This procedure is not necessarily
performed. The document may be saved in original format while its text may be copied to the
programmer for further use.
Compiling a program

The microcontroller does not undrestand assembly language as such. That is why it is
necessary to compile the program into machine language. It is more than simple when a
specialized program (mplab) is used because a compiler is a part of the software. Just one click
on the appropriate icon solves the problem and a new document with .hex extension appears. It is
actually the same program, only compiled into machine language which the microcontroller
perfectly understands. Such documentation is commonly named hex code and seemingly
represents a meaningless sequence of numbers in hexadecimal number system.
:03000000020100FA1001000075813F
7590FFB29012010D80F97A1479D40
90110003278589EAF3698E8EB25B
A585FEA2569AD96E6D8FED9FAD
AF6DD00000001FF255AFED589EA
F3698E8EB25BA585FEA2569AD96
DAC59700D00000278E6D8FED9FA
DAF6DD00000001FF255AFED8FED
9FADAF6DD000F7590FFB29013278
E6D8FED9FADAF6DD00000001FF2
55AFED589EAF3698E8EB25BA585
FEA2569AD96DAC59D9FADAF6D
D00000001FF255AFED8FED9FADA
F6DD000F7590FFB29013278E6D82
78E6D8FED9FA589EAF3698E8EB2
5BA585FEA2569AD96DAF6DD000
00001FF2DAF6DD00000001FF255A
ADAF6DD00000001FF255AFED8FE
D9FA

In the event that other software for program writing in assembly language is used, a special
software for compiling the program must be installed and used as follows - set up the compiler,
open the document with .asm extension and compile. The result is the same- a new document
with extension .hex. The only problem now is that it is stored in your PC.
Programming a microcontroller
In order to transfer a hex code to the microcontroller, it is necessary to provide a cable for
serial communication and a special device, called programmer, with software. There are several
ways to do it.
A large number of programs and electronic circuits having this purpose can be found on the
Internet. Do as follows: open hex code document, set a few parameters and click the icon for
compiling. After a while, a sequence of zeros and ones will be programmed into the
microcontroller through the serial connection cable and programmer hardware. What's left is to
place the programmed chip into the taget device. In the event that it is necessary to make some
changes in the program, the previous procedure may be repeated an unlimited number of times.

The end or...?


This section briefly describes the use of MPLAB and programmer software developed by
Mikroelektronika. Everything is very simple...

Start the program Mikroelektronika Asm51 Console. The window appears...


...Open a new document: File -> New. Write your program or copy text...
... Save and name your document: File -> Save As... (Document name is limited to 8 characters!)
Finally, to compile program into HEX code select: Project -> Build or click the 'play' icon.
If everything works properly, the computer will respond with a short report.

The program is written and successfully compiled. All that's left is to dump the program to the
microcontroller. For this purpose it is necessary to have a software that takes the written and
compiled program and passes it to the microcontroller.
Start the program 8051 Flash_setup.exe...

Program installation is performed as usually - just click Next, Accept, Next...


...and finally - Finish!

The program has been installed and ready for use. The settings are easily performed so that there
is no need for additional explanations (the type of the microcontroller, frequency and clock
oscillator etc.).

Connect the PC and programmer via a USB cable;


Load the HEX code using command: File -> Load HEX; and

Click the 'Write' push button and wait...

Thats all! The microcontroller is programmed and everything is ready for operation. If you are
not satisfied, make some changes in the program and repeat the procedure. Until when? Until
you feel satisfied...
Development systems

A device which in the testing program phase can simulate any environment is called a
development system. Apart from the programmer, the power supply unit and the
microcontrollers socket, the development system contains elements for input pin activation and
output pin monitoring. The simplest version has every pin connected to one push button and one
LED as well. A high quality version has LED displays, LCD displays, temperature sensors and
all other elements which can be supplied with the target device. These peripherals can be
connected to the MCU via miniature jumpers. In this way, the whole program may be tested in
practice during its development stage, because the microcontroller doesn't know or care whether
its input is activated by a push button or a sensor built in a real device.

7.2 Easy8051A Development System


The Easy8051A development system is a high-quality development system used for
programming 8051 compatible microcontrollers manufactured by Atmel. In addition to chip
programming, this system enables all the parts of the program to be tested as it contains most
components which are normally built in real devices.
The Easy8051A development system consists of:

Sockets for placing microcontrollers in (14, 16, 20 and 40- pin packages)
Connector for external power supply (DC 12V)

USB programmer

Power Supply Selector (external or via USB cable)

8 Mhz Quartz Crystal Oscillator

32 LEDs for output pin state indication

32 push buttons for input pin activation

Four 7-segment LED displays in multiplex mode

Graphic LCD display

Alphanumeric LCD display (4- or 8- bit mode)

Connector and driver for serial communication RS232

Digital thermometer DS1820

12- bit A/D converter (MCP3204)

12- bit D/A converter (MCP4921)

Reference voltage source 4.096V (MCP1541)

Multiple-pin connectors for direct access to I/O ports

The following text describes in short some circuits within this development system. It is rather
illustration of its features than complete manual. Besides, by learning about this device, one
understands that microcontrollers and its tools are intended to everybody, not only to the
privileged.
Sockets

All microcontrollers manufactured by Atmel appear in a few standard DIP packages. In order to
enable their programming using one device, corresponding pins (having the same name) on
sockets are connected in parallel. As a result, by being placed in the appropriate socket, each
microcontroller is automatically properly connected. Figure on the right shows a microcontroller
in 40-pin package and connection of one of its I/O pins (P1.5). As seen, the pin can be connected
to an external device (connector PORT1), LED (microswitch SW2), push button or resistor
through connectors. In the last two cases, polarity of voltage is selected using on-board jumpers.

Programmer

The purpose of the programmer is to transfer HEX code from PC to appropriate pins and provide
regular voltage levels during chip programming as well. For this development system, the
programmer is built in it and should be connected to PC via USB cable. When the process of
programming is completed, pins used for it are automatically available for other application.

Development system power supply

There is a connector on the development board enabling commection to external power supply
source (AC/DC, 8-16V). Besides, voltage necessary for device operation can also be obtained
from PC via USB cable. Jumper J5 is used for power supply selection.

8MHz Oscillator

The EASY8051A development system has built-in oscillator used as a clock signal generator.
The frequency of this oscillator is stabilized by 8Hz quartz crystal. Besides, it is also possible to
select internal RC oscillator during chip programming,.

LEDs for output pin state indication

Each I/O port pin is connected to one LED which enables visual indication of its logic state. In
the event that the presence of directly polarized LEDs and serial resistors is not acceptable in
some applications, DIP switch SW2 enables them to be disconnected from the port.

Push buttons for input pin activation

Similar to LEDs, each I/O port pin is connected to one push button on the development board. It
enables simple activation of input pins. Jumper J6 is used for selecting voltage polarity (+ or -)
brought to pins by pressing appropriate push button.

7-segment LED displays

Being often applied in the industry, four high-performance LED displays set in multiplex mode
belong to the development system. Display segments are connected to the port P0 via resistors.
Transistor drivers used for activating individual digits are connected to the first four port P1 pins.
It enables programs using 7-segment displays to be tested with minimum use of I/O ports.
Similar to LEDs, DIP switch SW2 enables transistor drivers to be disconnected from
microcontroller pins.

LCD displays

The EASY8051A development system provides connection to eather graphic or alphanumeric


LCD display. Both types of displays are connected by being placed into appropriate connector
and by switching position of the jumper J8. If displays are not in use, all pins used for their
operation are available for other applications. Apart from connectors, there is also a
potentiometer for contrast regulation on the board.

Serial communication via RS232

In order to enable programs using serial communication to be tested, the development system has
built in standard 9-pin SUB-D connector. The MAX232 is used as a voltage regulator.
Similar to other built-in circuits, electronics supporting serial communication can be enabled or
disabled by using jumpers J9 and J10.

DS1820 Digital thermometer

Temperature measurement is one of the most common tasks of devices which operate in the
industry. For this reason, there is a circuit DS1820 on the EASY8051A development system
which measures temperature in the range of -55 to +125oC with accuracy greater than 0.50.
Results of measurement are transferred via serial communication to the pins P3.3 or P2.7.
Jumper J7 is used for selecting pins for data reception. In the event that no jumper is installed,
port pins are available for other applications.

12-bit A/D converter MCP3204

A built-in 12-bit AD Converter MCP3204 has four input channels connected to on-board
connectors. Data are interchanged with the microcontroller via SPI serial communication system
using pins P1.5, P1.6, P1.7 and P3.5. If A/D converter is not in use, these pins can be used for
other applications (DIP switch SW1). In order to check operation, there is a potentiometer on the
development board used as a variable voltage source. It can be brought to the converters input
pins using one of four jumpers J12. As a special convenience, a reference voltage source
MCP1541 (4,096V) is built in. Jumper J11 is used to select whether converter will use this
voltage or 5V.

12-bit D/A converter MCP4921

Digital to analog conversion (D/A) is another operation ofen performed by the microcontroller in
practice. For this reason, there is a special on-board chip which interchanges data with the
microcontroller via SPI communication system. It can also generate analog voltage in 12-bit
resolution on its output pin. When it is not in use, all microcontroller pins are available for other
applications using DIP switch SW1. Similar to A/D converter, jumper J11 is used for selecting
reference voltage.

Connectors for direct access to I/O ports

In order to enable microcontroller ports to be directly connected to additional components, each


of them is connected to one on-board connector. Besides, two pins of each connector are
connected to power supply voltage while each pin can be connected to + or - polarity of voltage
via resistors (pull up or pull down resistors). Presence and connection of these resistors are
determined by jumpers. Jumper J3 which controls port P3 is shown in figure on the right.

You might also like