Chapter 6 : Examples

Introduction

The purpose of this chapter is to inform you about basic issues on microcontrollers that one should know in order to use them successfully in practice. That is why you will not find here some ultra interesting program or device schematic with amazing solutions. Instead of that, examples described in this chapter are more proof that program writing is neither privilege nor talent issue but ability of simple putting puzzle pieces together using directives. Device development mainly comes to the method “test-correct-repeat”. Of course, the more you are into it, the issues become more complicated as the puzzle pieces are put together by both children and first-class architects...

6.1 Basic connecting of the microcontroller

Basic connecting of the microcontroller - Power Supply

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

  • Power supply
  • Reset signal
  • Clock signal

Obviously, all this is about very simple circuits, but it does not have to be always like that. If device is used for handling expensive machines or for maintaining vital functions, everything becomes more and more complicated! This kind of solution is quite enough for the time being...

Power supply

Although this circuit can operate with different power supply voltage, why to test “Marphy’s low”?! Voltage of 5V is so common that it imposes itself. The circuit, shown on the figure, uses cheap voltage stabilisator LM7805 and provides high-quality voltage level and guite enough current to enable microcontroller and “peripheral electronics” to operate ( sufficient current in this case amounts to 1A)!

Reset signal

In order to operate properly, the microcontroller must “see” logic 0 (0V) on reset pin RS (It explains connection pin-resistor 10K-ground). Pushbutton which connects reset pin RS to power supply VCC is not necessary but it is almost always built in because it enables microcontroller safe return to normal operating conditions when the things go wrong. By activating this pin, 5V is brought to it, the microcontroller is reset and program starts execution from the beginning.

Clock signal

Although the microcontroller has built in oscillator, it cannot operate without two external condensators and quartz crystal which stabilize its frequency (microcontroller’s operating speed).

Clock signal

Naturally, there are some exceptions too:
if this solution cannot be applied for some reason, there are always alternative ones. One of them is to bring clock signal from special source through invertor. See the figure on the left.

6.2 Additional components

Regardless of the fact that microcontrollers are the product of modern technology, they are not so useful without being connected to additional components. Simply, the appearance of voltage on its pin means nothing if it does not perform certain operations (turn on/off, shift, display and similar).

Switches and Pushbuttons

There is nothing simpler than this! This is the simplest way of controlling appearance of some voltage on microcontroller’s input pin. There is also no need for additional explanation of how these components operate.

Switches and Pushbuttons

Nevertheless, it is not so simple in practice... This is about something commonly unnoticeable when using these components in everyday life. It is about contact bounce- a common problem with m e c h a n i c a l switches. If contact switching does not happen so quickly, several consecutive bounces can be noticed prior to maintain stable state. The reasons for this are: vibrations, slight rough spots and dirt. Anyway, whole this process does not last long (a few micro- or miliseconds), but long enough to be registered by the microcontroller. Concerning pulse counter, error occurs in almost 100% of cases!

RC Debounce

The simplest solution is to connect simple RC circuit which will “suppress” each quick voltage change. Since the bouncing time is not defined, the values of elements are not strictly determined. In the most cases, the values shown on figure are sufficient.

If complete safety is needed, radical measures should be taken! The circuit, shown on the figure (RS flip-flop), changes logic state on its output with the first pulse triggered by contact bounce. Even though this is more expensive solution (SPDT switch), the problem is definitely resolved! Besides, since the condensator is not used, very short pulses can be also registered in this way.

Filp Flop Debounce

In addition to these hardware solutions, a simple software solution is commonly applied too: when a program tests the state of some input pin and finds changes, the check should be done one more time after certain time delay. If the change is confirmed it means that switch (or pushbutton) has changed its position. The advantages of such solution are obvious: it is free of charge, effects of disturbances are eliminated too and it can be adjusted to the worst-quality contacts. Disadvantage is the same as in case of using RC filter-pulses shorter than program delay cannot be registered.

Optocouplers

Optocouplers

Optocoupler is a device commonly used to galvanically separate microcontroller’s electronics from potentionally dangerous currents and voltages in environment. Optocouplers usually have one, two or four light sources (LE diodes) on their input while on their output, opposite to diodes, there are the same number of elements sensitive to light (phototransistors, photo-thyristors or photo-triacs). The point is that there is no electrical contact between input and output, but the signal is transferred by light. For this isolation to make sense, electrical power supply of diodes and photo-sensitive elements must be independent. Being connected in this way, the microcontroller and expensive additional electronics are completely protected from high voltage and disturbances which in practice are the most common cause of destroying, damaging or unstable operating of electronic devices. Most frequently used optocouplers are those with phototransistors on their output. In case the model of optocouplers with internal base-to-pin 6 connection is on disposal (there are optocouplers without it), the base can be left unconnected. Optional connection, decreasing effects of disturbances by eliminating very short pulses, is on the figure marked with a broken line .

Relays

Relays

Relays are elements connected to ouput pins of the microcontroller and used to turn on/off all that being out of board which has sensitive components: motors, transformators, heaters, bulbs, high-voltage components, antenna systems etc. There are various types of relays but all have the same operating principle: when a current flows through the coil, it makes or brakes machanical connection between one or more pairs of contacts. As it is case with optocouplers, there is no galvanically connection (electrical contact) between input and output circuits. Relays usually demand both higher voltage and current to start operating but there are also miniature versions which can be activated with a low current directly obtained from the microcontroller’s pin.

Below figure presents one solution specific to the 8051 microcontrollers. In this very case, darlington transistor is used to activate relays because of its high current gain. This is not in accordance with “rules”, but it is necessary in case of logic one activation since the current is then very low (pin acts as input)!

Basic connecting of the microcontroller - Relays

In order to be prevented from appearance of high voltage of self-induction caused by a sudden stop of current flow through the coil, an inverted polarized diode is connected in parallel to the coil. The purpose of this diode is to “cut off” the voltage peak.

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

Light-emitting diode (LED)

It is important to know that each diode will be immediately destroyed unless its current is limited. This means that a conductor must be connected in parallel to a diode. In order to correctly determine value of this conductor, it is necessary to know diode’s voltage drop in forward direction, which depends on what material a diode is made of and what colour it is. Values typical for the most frequently used diodes are shown in table below: As seen, there are three main types of LEDs. Standard ones get ful brightness at current of 20mA. Low Current diodes get ful brightness at ten times lower current while Super Bright diodes produce more intensive light than Standard ones.

Color Type Typical current Id (mA) Maximal current If (mA) Voltage drop Ud (V)
Infrared - 30 50 1.4
Red Standard 20 30 1.7
Red Super Bright 20 30 1.85
Red Low Current 2 30 1.7
Orange - 10 30 2.0
Green Low Current 2 20 2.1
Yellow - 20 30 2.1
Blue - 20 30 4.5
White - 25 35 4.4
Low current LED

Since the 8051 microcontrollers can provide only low input current and since their pins are configured as outputs when voltage level on them is equal to 0, direct connectining to LEDs is carried out as it is shown on figure (Low current LED, cathode is connected to output pin).

LED displays

Basically, LED displays are nothing else but several LEDs moulded in the same plastic case. Diodes are arranged so that different marks-commonly digits: 0, 1, 2,...9 are displayed by activating them. There are many types of displays composed of several dozens of built in diodes which can display different symbols.

LED displays

The most commonly used are so called 7-segment displays. They are composed of 8 LEDs, 7 segments are arranged as a rectangle for symbol displaying and there is additional segment for decimal point displaying. In order to simplify connecting, anodes and catodes of all diodes are connected to the common pin so that there are common cathode displays and common anode displays. Segments are marked with the latters Ato G as shown on the figure on the left. When connecting, each diode is treated independently, which means that each must have its own conductor for current limitation.

When connecting displays to the microcontroller, the greatest problem is a great deal of valuable I/O pins which they “occupy”, especially if it is needed to display several-digit numbers. Problem is more than obvious if for example it is needed to display two 6-digit numbers (a simple calculation shows that 96 output pins are needed)!The solution on this problem is called MULTIPLEXING. This is how optical illusion based on the same operating principle as filmcamera occurs. The principle is that only one digit is active but by quick changing one gets impression that all digits of a number are active at the same time.

Basic connecting of the microcontroller - LED displays

Referring to the previous example it would mean that firstly one byte representing units is applied on a microcontroller’s port and only transistor T1 is activated at the same time. After a while, the transistor T1 is turned off, a byte representing tens is applied on a port and transistor T2 is activated. This process is being cyclicly repeated at high speed for all digits and corresponding transistors.

When displaying any digit, a defeating fact that microcontroller is nevertheless only a machine made to understand only language of units and zeros is fully expressed. Namely, it “does not know” what units, tens or hundreds are, nor it knows how ten digits we are used to look like. Therefore, each number intended to be shown on display must be prepared in the following way:

In special subroutine, a several digit number must be first separated in units, tens etc. Afterwards, each of these digits must be stored in specific byte. In order to make these digits familiar to us, “masking” is carried out. Basically, it is a simple subroutine by which binary format of each number is replaced by different combination of bits. For example, the digit 8 (0000 1000) is replaced by binary digit 0111 111 in order to activate all LEDs which represent digit 8 on display. The only diode, inactive in this case is reserved for decimal point. If a microcontroller’s port is connected to display in a way that bit 0 activates segment “a”, bit 1 activates segment “b”, bit 2 segment “c” etc., the table below shows “mask” for each digit.

Masking LED displays
Digits to display Display Segments
dp a b c d e f g
0 1 0 0 0 0 0 0 1
1 1 0 0 1 1 1 1 1
2 1 0 0 1 0 0 1 0
3 1 0 0 0 0 1 1 0
4 1 1 0 0 1 1 0 0
5 1 0 1 0 0 1 0 0
6 1 0 1 0 0 0 0 0
7 1 0 0 0 1 1 1 1
8 1 0 0 0 0 0 0 0
9 1 0 0 0 0 1 0 0

Beside digits 0 to 9, some latters of alphabet : A, C, E, J, F, U, H, L, b, c, d, o, r, t can be displayed by appropriate masking.
If common chatode displays are used all units in the table should be replaced by zeros and vice versa. In that case NPN transistors should be also used as drivers.

Liquid Crystal Displays (LCD)

These components are “specialized” for being used with the microcontrollers, which means that they cannot be activated by standard IC circuits. They are used for writing different messages on a miniature LCD.

Liquid Crystal Displays (LCD)

Amodel described here is for its low price and great possibilities most frequently used in practice. It is based on the HD44780 microcontroller (Hitachi) and can display messages in two lines with 16 characters each . It displays all letters of alphabet, greek letters, punctuation marks, mathematical symbols etc. In addition, it is possible to display symbols that user makes up on its own. Automatic shifting message on display (shift left and right), appearance of the pointer, backlight etc. are considered as useful characteristics.

Pins Functions

There are pins along one side of the small printed board used for connection to the microcontroller. There are total of 14 pins marked with numbers (16 in case the background light is built in). Their function is described in the table bellow:

Function Pin Number Name Logic State Description
Ground 1 Vss - 0V
Power supply 2 Vdd - +5V
Contrast 3 Vee - 0 - Vdd
Control of operating 4 RS 0
1
D0 – D7 are interpreted as commands
D0 – D7 are interpreted as data
5 R/W 0
1
Write data (from controller to LCD)
Read data (from LCD to controller)
6 E 0
1
From 1 to 0
Access to LCD disabled
Normal operating
Data/commands are transferred to LCD
Data / commands 7 D0 0/1 Bit 0 LSB
8 D1 0/1 Bit 1
9 D2 0/1 Bit 2
10 D3 0/1 Bit 3
11 D4 0/1 Bit 4
12 D5 0/1 Bit 5
13 D6 0/1 Bit 6
14 D7 0/1 Bit 7 MSB
LCD screen
LCD screen pixels

LCD screen consists of two lines with 16 characters each. Each character consists of 5x8 or 5x11 dot matrix. This book covers 5x8 character display because it is commonly used.

Contrast on display depends on the power supply voltage and whether messages are displayed in one or two lines. For that reason, variable voltage 0-Vdd is applied on pin marked as Vee. Trimmer potentiometer is usually used for that purpose. Some versions of displays have built in backlight (blue or green diodes). When used during operating, a resistor for current limitation should be used (like with any LE diode).

LCD backlight Note
If there are no characters on display or all of them are dimmed upon the display is on, the first thing that should be done is to check the potentiometer for contrast regulation. Is it properly adjusted? Same applies in case the operation mode is changed (writing in one or two lines).

LCD Memory

There are three memory blocks inside the display:
  • DDRAM Display Data RAM
  • CGRAM Character Generator RAM
  • CGROM Character Generator ROM
DDRAM Memory

DDRAM memory is used for storing characters that should be displayed. The size of this memory is sufficient for storing 80 characters. One part of these locations is directly connected to the characters on display.

DDRAM Memory

All functions quite simply: it is sufficient to configure display so that addresses are automatically incremented (shift right). Afterwards it sets starting value for the message that should be displayed (for example 00 hex).

After that, all characters sent through lines D0-D7 will be displayed as a message we are used to- from left to right. In this case, displaying starts from the first character in the first line on display since the address is 00 hex. If more than 16 characters are sent, they all will be also memorized but not visible. In order to display them, a shift command should be used. Virtually, everything looks as if LCD display is a “window” which moves left-right over memory locations with characters. In reality, that is how the affect of message “moving”on the screen is obtained (from left to right or vice versa).

If cursor is on, it will appear at location which is currently addressed. In other words, characters will appear at cursor’s position while the cursor is automatically moved to the next addressed location.
Since this is a sort of RAM memory, data can be written to and read from it. Disadvantage is that the contents will be lost forever upon the power is off.

CGROM Memory

A “map” with all characters that can be displayed are written by default. Each character has corresponding location.

CGROM Memory

Addresses of CGROM memory locations match standard ASCII values of characters. It means that if in a program being currently executed by the microcontroller is written “send letter P to port”, the binary value 0101 0000 will appear on the port. This value is ASCII equivalent to the letter P. When this binary number is sent to LCD, a symbol stored on 0101 0000 location in CGROM will be displayed. In other words, the letter “P” will be displayed . This applies to all alphabet letters (upper- and lowercase), but not to numbers!

If one carefully looks at the “map” with characters in this memory, it can be seen that addresses of all digits are “shifted” by 48 in comparison to the values of these digits (address of the digit 0 is 48, of digit 1 is 49, of digit 2 is 50 etc.). For that reason and in order to display digits correctly, each of them needs to be added a decimal number 48 prior to being sent to LCD.

Note
Since the time the first computer was made, it recognizes numbers but not letters. It means that on sending any character from keyboard to PC, from PC to printer or from microcontroller to other computer, through connection line are actually sent binary numbers instead of characters . A table that links all standard symbols and their number equivalents is called ASCII code.

CGRAM memory

Beside being able to display all standard characters, the LCD can display symbols that user defines on its own. It enables displaying cyrilic fonts as well as many other symbols which fit to the frame of 5x8 dots size. RAM memory (CGRAM) in size of 64 bytes enables the above.

The size of registers of this memory is a standard one (8 bits), but only 5 lower bits are in use. Logic one (1) in every register represents a dimmed dot, while 8 locations considered jointly represent one character. It is best illustrated on the figure below:

CGRAM memory

Symbols are usually defined at the beginnig of a program by simple writing zeros and units to registers of CGRAM memory so that they form desirable shapes. In order to display them it is sufficient to specify their address. Pay attention to the first coloumn in CGROM map of characters- these are not addresses of RAM memory but symbols which are discussed here.In this example, “display 0” means - display “č”, “display 1” means - display “ž” etc.

LCD Basic Commands

All data transferred to LCD through outputs D0-D7 will be interpreted as commands or as data, which depends on logic state on pin RS:

RS = 1 - Bits D0 - D7 are addresses of characters that should be displayed. Built in processor addresses built in “map of characters” and displays corresponding symbols. Displaying position is determined by DDRAM address. This address is either previously defined or the address of previously transferred character is automatically incremented.

RS = 0 - Bits D0 - D7 are commands which determine display mode. List of commands which LCD “recognizes”are given in the table below:

Command RS RW D7 D6 D5 D4 D3 D2 D1 D0 Execution Time
Clear display 0 0 0 0 0 0 0 0 0 1 1.64mS
Cursor home 0 0 0 0 0 0 0 0 1 x 1.64mS
Entry mode set 0 0 0 0 0 0 0 1 I/D S 40uS
Display on/off control 0 0 0 0 0 0 1 D U B 40uS
Cursor/Display Shift 0 0 0 0 0 1 D/C R/L x x 40uS
Function set 0 0 0 0 1 DL N F x x 40uS
Set CGRAM address 0 0 0 1 CGRAM address 40uS
Set DDRAM address 0 0 1 DDRAM address 40uS
Read “BUSY” flag (BF) 0 1 BF DDRAM address -
Write to CGRAM or DDRAM 1 0 D7 D6 D5 D4 D3 D2 D1 D0 40uS
Read from CGRAM or DDRAM 1 1 D7 D6 D5 D4 D3 D2 D1 D0 40uS
I/D 1 = Increment (by 1)         R/L 1 = Shift right
    0 = Decrement (by 1)             0 = Shift left
    
S 1 = Display shift on           DL 1 = 8-bit interface
  0 = Display shift off             0 = 4-bit interface
  
D 1 = Display on                 N 1 = Display in two lines
  0 = Display off                  0 = Display in one line
  
U 1 = Cursor on                  F 1 = Character format 5x10 dots
  0 = Cursor off                   0 = Character format 5x7 dots

B 1 = Cursor blink on            D/C 1 = Display shift
  0 = Cursor blink off               0 = Cursor shift
What is Busy flag ?

Comparing to the microcontroller, LCD is an extremly slow component. Because of that It was necessary to provide a signal which will indicate that display is ready to receive a new data or a command following the previous one has been executed. That signal is called busy flag and can be read from line D7. When the bit BF is cleared (BF=0), display is ready to receive.

LCD Connection

Depending on how many lines are used for connection to the microcontroller, there are 8-bit and 4-bit LCD modes. The appropriate mode is determined at the beginning of the process in a phase called “initialization”. In the first case, the data are transferred through outputs D0-D7 as it has been already explained. In case of 4-bit LED mode, for the sake of saving valuable I/O pins of the microcontroller, there are only 4 higher bits (D4-D7) used for communication, while other may be left unconnected. Consequently, each data is sent to LCD in two steps: four higher bits are sent first (that normally would be sent through lines D4-D7), four lower bits are sent afterwards. With the help of initialization, LCD will correctly connect and interprete each data received. Besides, with regards to the fact that data are rarely read from LCD (data mainly are transferred from microcontroller to LCD) one more I/O pin may be saved by simpleconnecting R/W pin to the Ground. Such saving has its price. Even though message displaying will be normally performed, it will not be possible to read from busy flag since it is not possible to read from display.

LCD Connection

Luckily, solution is simple. It is sufficient to give LCD enough time to perform its task upon sending every character or command. Since execution of the slowest command is approximately 1.64mS, it will be quite enough to wait for approximately 2mS.

LCD Initialization

Once the power supply is turned on, LCD is automatically cleared. This process lasts for approximately 15mS. After that, display is ready to operate. The mode of operating is set by default. This means that:

  1. Display is cleared
  2. Mode
    • 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
    • D = 0 Display off
    • U = 0 Cursor off
    • B = 0 Cursor blink off
  4. Character entry
    • ID = 1 Addresses on display are automatically incremented by 1
    • S = 0 Display shift off

Automatic reset is mainly performed without any problems. Mainly but not always! If for any reason power supply voltage does not reach ful value in the course of 10mS, display will start perform completely unpredictably. If voltage supply unit can not meet this condition or if it is needed to provide completely safe operating, the process of initialization by which a new reset enabling display to operate normally must be applied.

Algorithm according to the initialization is being performed depends on whether connection to the microcontroller is through 4- or 8-bit interface. All left over to be done after that is to give basic commands and of course- to display messages...

Refer to the Figure below for the procedure on 8-bit initialization:

8-bit initialization Note
It is not a mistake!
In algorithm on figure, the same value is being transmitted three times in a row.

In case of 4-bit initialization, the procedure is as follows:

4-bit initialization

6.3 Examples

The schematic below is used in the several following examples:

LED connection schematic

Nothing special... Beside elements necessary for operating (oscillator with condensators and the simplest reset circuit), there are also several LEDs and one pushbutton which actually do not have any practical application and are used only to indicate program operating.

All LEDs are polarized so that they are activated by logic zero (0) on the microcontroller’s pin.

LED Blinking

This program does not demonstrate LEDs’ operating but the speed of operation of the microcontroller! Simply, in order to enable LED blinking be visible, sufficient amount of time must pass between on/off states. In this example time delay is solved using a subroutine called Delay. It is a triple loop where the program remains for approximately 0.5 seconds and decrements values in registers R0, R1 or R2. Upon return from subroutine, the state on the pin is inverted and procedure is repeated...

;************************************************************************
;* PROGRAM NAME : Delay.ASM
;* DESCRIPTION: Program turns on/off LED on the pin P1.0
;* Software delay is used (Delay).
;************************************************************************
;BASIC DIRECTIVES
$MOD53
$TITLE(DELAY.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK
        DSEG    AT    03FH
STACK_START:    DS    040H

;RESET VECTORS
       CSEG     AT    0
       JMP      XRESET                  ;Reset vector
       
       ORG      100H
       
XRESET: MOV     SP,#STACK_START         ;Defining of Stack pointer
        MOV     P1,#0FFh                ;All pins are configured as inputs

LOOP:
        CPL     P1.0                    ; State on the pin P1.0 is inverted
        LCALL   Delay                   ; Time delay
        SJMP    LOOP

Delay:
        MOV     R2,#20                  ;500 ms time delay
F02:    MOV     R1,#50                  ;25 ms
F01:    MOV     R0,#230
        DJNZ    R0,$
        DJNZ    R1,F01
        DJNZ    R2,F02

END                                     ;End of program
Using Watch-dog Timer

This program describes how the watch-dog timer should not operate! As a matter of fact watch-dog timer is properly adjusted (nominal time for counting is 1024mS), but instruction for its reset is intentionally left out so that this timer always wins the “battle for time”. As a result, the microcontroller is reset (state in registers remains unchanged), program starts execution from the beginning, number in register R3 is incremented by 1 and copied to port P1 afterwards.

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     DATA    96H
WDTEN     EQU     00000001B        ; Watch-dog timer is enabled
PERIOD    EQU     11000000B        ; Nominal Watch-dog period in duration of 1024ms 
                                   ; is defined

;RESET    VECTOR
          CSEG    AT      0
          JMP     XRESET           ; Reset vector

          CSEG
          ORG     100H

XRESET:   ORL     WMCON,#PERIOD    ; Defining of Watch-dog period
          ORL     WMCON,#WDTEN     ; Watch-dog timer is enabled

          MOV     A,R3             ; R3 is moved to port 1
          MOV     P1,A
          INC     R3               ; Register R3 is incremented by 1

LAB:      SJMP    LAB              ; Wait for watch-dog reset

          END                      ; End of program
Timer T0 in mode 1

This program spends the most of its time in endless loop waiting for timer T0 to count up a full cycle. Once it happens, interrupt is generated, the routine TIM0_ISR is executed and logic zero (0) on port P1 is shifted right by one place. This is another way to demonstrate the speed of operation of the microcontroller since each shift means that counter T0 has counted off 216 pulses!

;************************************************************************
;* PROGRAM NAME : Tim0Mod1.ASM
;* DESCRIPTION: Program rotates "0" on port 1. Timer T0 in mode 1 is
;* used
;************************************************************************

;BASIC DIRECTIVES

$MOD53
$TITLE(TIM0MOD1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;DEFINING OF VARIABLES

;STACK

        DSEG     AT     03FH
STACK_START:     DS     040H

;RESET VECTORS
       CSEG      AT 0
       JMP       XRESET             ; Reset vector

       ORG       00BH
       JMP       TIM0_ISR           ; Timer T0 reset vector

       ORG       100H

XRESET: MOV      SP,#STACK_START    ; Defining of Stack pointer
       MOV       TMOD,#01H          ; MOD1 is selected
       MOV       A,#0FFH
       MOV       P1,#0FFH
       SETB      TR0                ; Timer T0 start
       MOV       IE,#082H           ; Interrupt enabled
       CLR       C

LOOP1: SJMP      LOOP1              ; Remain here

TIM0_ISR:        RRC     A          ; Rotate accumulator A through Carry bit
                 MOV     P1,A       ; Contents of accumulator A is moved to PORT1
                 RETI               ; Return from interrupt

       END                          ; End of program
Timer T0 in Split mode

Similar to the previous example, the program spends the most of its time in a loop called LOOP1. Since 16-bit Timer T0 is split into two 8-bit timers, there are also two interrupt sources, therefore.

First interrupt is generated after timer T0 reset. It executes the routine TIM0_ISR in which logic zero (0) bit on port P1 is rotated. Looking from outside, it seems that LED’s light shifts.

Another interrupt is generated upon Timer T1 reset. It executes the routine TIM1_ISR in which the bit state DIRECTION is inverted. Since this bit determines direction of bit rotation then the direction of LED shifting is also changed.
If at any moment a pushbutton T1 is pressed, logic zero (0) on output P3.2 will stop the Timer T1.

;************************************************************************
;* PROGRAM NAME : Split.ASM
;* DESCRIPTION: Timer TL0 rotates bit on port P1, while TL1 determines
;* the direction of rotation. Both timers operate in mode
;* 3. Logic 0 on output P3.2 stops rotation on port P1.
;************************************************************************

;BASIC DIRECTIVES

$MOD53
$TITLE(SPLIT.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;DEFINING OF VARIABLES

        BSEG    AT    0

;DEFINING OF BIT-VARIABLES

SEMAPHORE:      DBIT    8
DIRECTION       BIT     SEMAPHORE

;STACK
        DSEG    AT    03FH
STACK_START:    DS    040H

;RESET VECTORS

        CSEG    AT    0
        JMP     XRESET                    ; Reset vector
        ORG     00BH

        JMP     TIM0_ISR                  ; Timer T0 reset vector

        ORG     01BH
        JMP     TIM1_ISR                  ; Timer T1 reset vector

        ORG     100H
XRESET: MOV     SP,#STACK_START           ; Defining of Stack pointer
        MOV     TMOD,#00001011B           ; Defining of MOD3
        MOV     A,#0FFH
        MOV     P1,#0FFH
        MOV     R0,#30D
        SETB    TR0                       ; TL0 is turned on
        SETB    TR1                       ; TL1 is turned on
        MOV     IE,#08AH                  ; Interrupt enabled
        CLR     C
        CLR     DIRECTION                 ; First rotation is to right

LOOP1:  SJMP    LOOP1                     ; Remain here

TIM0_ISR:
        DJNZ    R0,LAB3                   ; Slow down rotation by 256 times
        JB      DIRECTION,LAB1
        RRC     A                         ; Rotate contents of Accumulator to the right through
                                          ; Carry bit

        SJMP    LAB2
LAB1:   RLC     A                         ; Rotate contents of Accumulator to the left through
                                          ; Carry bit
LAB2:   MOV     P1,A                      ; Contents of Accumulator is moved to port P1
LAB3:   RETI                              ; Return from interrupt

TIM1_ISR:
        DJNZ    R1,LAB4                   ; Slow down direction of rotation by 256 times
        DJNZ    R2,LAB4                   ; If time is ran out, change direction of
                                          ; rotation
        CPL     SMER
        MOV     R2,#30D
LAB4:   RETI

        END                               ; End of program
Simultaneous use of timers T0 and T1

One can take this program as extension of the previous one. The idea is the same but in this case true timers T0 and T1 are used. In order to demonstrate operation of both timers simultaneously, the Timer T0 reset is used to shift logic zero (0) on port while Timer1 reset is used to change direction of rotation. This program spends the most of its time in the loop LOOP1 waiting for interrupt caused by reset. By checking the bit DIRECTION, an information on direction of rotation of both bits in Accumulator and shifting LED on port is obtained.

;************************************************************************
;* PROGRAM NAME : Tim0Tim1.ASM
;* DESCRIPTION: Timer TO rotates bit on port P1 while Timer1
;* changes direction of rotation. Both timers oper
;* ates in mode 1.
;************************************************************************

;BASIC DIRECTIVES

$MOD53
$TITLE(TIM0TIM1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;DEFINING OF VARIABLES

       BSEG    AT    0

;DEFINING OF BIT-VARIABLES

SEMAPHORE:      DBIT    8
DIRECTION       BIT     SEMAPHORE

;STACK
       DSEG    AT    03FH
STACK_START:   DS    040H

;RESET VECTORS
       CSEG    AT    0
       JMP     XRESET                     ; Reset vector

       ORG     00BH                       ; Timer 0 Reset vector
       JMP     TIM0_ISR

       ORG     01BH                       ; Timer 1 Reset vector
       JMP     TIM1_ISR

       ORG     100H


XRESET: MOV    SP,#STACK_START            ; Defining of Stack pointer
        MOV    TMOD,#11H                  ; Selecting MOD1 for both timers
        MOV    A,#0FFH
        MOV    P1,#0FFH
        MOV    R0,#30D                    ; R0 is initialized
        SETB   TR0                        ; TIMER0 is turned on
        SETB   TR1                        ; TIMER1 is turned on
        MOV    IE,#08AH                   ; Timer0 and Timer1 Interrupt enabled
        CLR    C
        CLR    DIRECTION                  ; First rotation is to right

LOOP1:  SJMP   LOOP1                      ; Remain here


TIM0_ISR:
        JB     DIRECTION,LAB1
        RRC A                             ; Rotate contents of Accumulator to the right through
                                          ; Carry bit
        SJMP   LAB2
LAB1:   RLC    A                          ; Rotate contents of Accumulator to the left through
                                          ; Carry bit
LAB2:   MOV    P1,A                       ; Contents of Accumulator is moved to port P1
        RETI                              ; Return from interrupt

TIM1_ISR:
        DJNZ   R0,LAB3                    ; If time is ran out, change direction of rotation
        CPL    DIRECTION
        MOV    R0,#30D                    ; Initialize R0
LAB3:
        RETI
        END                               ; End of program
Using Timer T2

This example describes the use of Timer T2 configured to operate in Auto-Reload mode. In this very case, LEDs are connected to port P3 while the pushbutton used for forced timer reset (T2EX) is connected to pin P1.1.

Program execution is similar to the previous examples. When timer ends counting, interrupt is enabled and subroutine TIM2_ISR is executed. Within it, logic zero (0) in accumulator is rotated and afterwards content of accumulator is moved to pin P3. At the end, flags which caused interrupt are erased and program returns to the loop LOOP1 where it remains until a new interrupt request is encountered...

If pushbutton T2EX is pressed, timer is temporarily reset. Hence, this pushbutton resets timer while pushbutton RESET resets microcontroller.

Using Timer T2
;************************************************************************
;* 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
;STACK
        DSEG     AT       03FH
STACK_START:     DS       040H

;RESET VECTORS
        CSEG     AT       0
        JMP      XRESET                   ; Reset vector

        ORG      02BH                     ; Timer T2 Reset vector
        JMP      TIM2_ISR

        ORG      100H

XRESET: MOV      SP,#STACK_START          ; Defining of Stack pointer
        MOV      A,#0FFH
        MOV      P3,#0FFH
        MOV      RCAP2L,#0FH              ; 16-bit auto-reload mod is prepared
        MOV      RCAP2L,#01H
        CLR      CAP2                     ; 16-bit auto-reload mod is turned on
        SETB     EXEN2                    ; reset through pin P1.1 is enabled
        SETB     TR2                      ; Timer2 is turned on
        MOV      IE,#0A0H                 ; Interrupt is enabled
        CLR      C

LOOP1:  SJMP     LOOP1                    ; Remain here

TIM2_ISR:        RRC      A               ; Rotate contents of Accumulator to the right through
                                          ; Carry bit
                 MOV      P3,A            ; Move the content of Accumulator A to PORT3
                 CLR      TF2             ; Erase flag TF2 of timer T2
                 CLR      EXF2            ; Erase flag EXF2 of timer T2
                 RETI                     ; Return from interrupt

                 END                      ; End of program
Using External Interrupt

Here is another example of interrupt execution. This time, it is about external iterrupts generated when low logic level is present on pin P3.2 or P3.3. Depending on which input is active, one of two routines will be executed:

Logic zero (0) on pin P3.2 starts interrupt routine Isr_Int0. The routine increments number in register R0 and copies it to port P0. Low level on pin P3.3 starts subroutine Isr_Int1which increments number in register R1 by 1 and copies it to port P1 afterwards.

In short, each press on pushbuttons INT0 and INT1 will be counted and immediately shown in binary format on the appropriate port (LED which emitts light represents logic zero (0)).

Using External Interrupt
;************************************************************************
;* PROGRAM NAME : Int.ASM
;* DESCRIPTION : Program counts interrupts INT0 which are generated by
;* appearance of high-to-low transition signal on pin
;* P3.2 Result appears on port P0. Interrupts INT1 are
;* counted off at the same time. They are generated by
;* appearing high-to-low transition signal on pin P3.
;* This result appears on port P1.
;************************************************************************

;BASIC DIRECTIVES

$MOD53
$TITLE(INT.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;RESET VECTORS

        CSEG     AT     0
        JMP      XRESET               ; Reset vector

        ORG      003H                 ; Interrupt routine address for INT0
        JMP      Isr_Int0
        ORG 013H                      ; Interrupt routine address for INT1
        JMP      Isr_Int1

        ORG      100H
XRESET:
        MOV      TCON,#00000101B      ; Interrupt INT0 is generated by appearing
                                      ; high-to-low transition signal on pin P3.2
                                      ; Interrupt INT0 is generated by appearing
                                      ; high-to-low transition signal on pin P3.3
        MOV      IE,#10000101B        ; Interrupt enabled
        MOV      R0,#00H              ; Counter starting value
        MOV      R1,#00H
        MOV      P0,#00H              ; Reset port P0
        MOV      P1,#00H              ; Reset port P1

LOOP:   SJMP     LOOP                 ; Remain here

Isr_Int0:
        INC R0                        ; Increment value of interrupt INT0 counter
        MOV P0,R0
        RETI

Isr_Int1:
        INC R1                        ; Increment value of interrupt INT1 counter
        MOV P1,R1
        RETI
        END                           ; End of program
Using LED display

Following examples describe the use of LED display. Common chatode displays are used here, which means that all built in LEDs are polarized so that their anodes are connected to the microcontroller pins. It is not the way it should be but common way of thinking is that logic one (1) “turns on” something while logic zero (0) “turns off” something. That is why Low Current displays (low consumption) and their diodes (segments) are connected in series to resistors of relatively high resistance.

In order to save I/O pins, four LED displays are connected to operate in multiplex mode. That means that all segments having the same name are connected to one output port each and that there is always one display active.

By quick and synchronized activation of tranzistors and segmenats on displays, one gets impression that all digits emit lights simultaneously.

Using LED display
Write digits on LED display

This program is designed as “warming up” before real work starts. The single aim is to display something on any of displays. This time it is not multiplex mode, instead, digit 3 is displayed on only one of them (first one on the right).

Since the microcontroller “does not know” how man writes number 3, a small subroutine called Disp is used (microcontroller writes it as 0000 0011). This subroutine performs as a mask for all digits in decade system (0-9). The principle of the operation is simple. A number that should be displayed is added to the current address and program jump is executed. Different numbers match different jump length. Precisely determined combination of zeroes and units appears on each of these new locations (digit 1 mask, digit 2 mask...digit 9 mask). When this combination is transferred to the port, display diodes are activated as to show desired digit.

;************************************************************************
;* PROGRAM NAME : 7Seg1.ASM
;* DESCRIPTION: Program shows number "3" on 7-segment LED display
;************************************************************************

;BASIC DIRECTIVES

$MOD53
$TITLE(7SEG1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK
          DSEG     AT     03FH
STACK_START:       DS     040H

;RESET VECTORS
          CSEG     AT     0
          JMP      XRESET               ; Reset vector

          ORG      100H

XRESET:   MOV      SP,#STACK_START      ; Defining of Stack pointer
          MOV      P1,#0                ; Turn off all segments on displays
          MOV      P3,#20h              ; Activate display D4

LOOP:
          MOV      A,#03                ; Send number “3” on display
          LCALL    Disp                 ; Find appropriate mask for that number
          MOV      P1,A
          SJMP     LOOP

Disp:                                   ; Subroutine for writing digits
          INC      A
          MOVC     A,@A+PC
          RET
          DB       3FH                  ; Digit 0 mask
          DB       06H                  ; Digit 1 mask
          DB       5BH                  ; Digit 2 mask
          DB       4FH                  ; Digit 3 mask
          DB       66H                  ; Digit 4 mask
          DB       6DH                  ; Digit 5 mask
          DB       7DH                  ; Digit 6 mask
          DB       07H                  ; Digit 7 mask
          DB       7FH                  ; Digit 8 mask
          DB       6FH                  ; Digit 9 mask
          END                           ; End of program
Write and change digits on LED display

Program in this example is only an extended verson of the previous one. There is only one digit active- the first one on the right side, and there is no use of multiplexing. Unlike the previous case, all decade digits are displayed (0-9). In order to enable digits to shift at rational rate, a soubroutine L2 which causes a small time delay is executed before each shift. Basically, the whole process is very simple and takes place in the main loop LOOP as follows:

  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 counted, register R3 is reset in order to enable counting to start from 0.
  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     AT     03FH
STACK_START:      DS     040H

;RESET VECTORS
         CSEG     AT     0
         JMP      XRESET                   ; Reset vector

         ORG      100H

XRESET:  MOV      SP,#STACK_START          ; Defining of Stack pointer
         MOV      R3,#0                    ; Counter starting value
         MOV      P1,#0                    ; Turn off all segments on display
         MOV      P3,#20h                  ; Activate display D4

LOOP:
         MOV      A,R3
         LCALL    Disp                     ; Find appropriate mask for number in
                                           ; Accumulator
         MOV      P1,A
         INC      R3                       ; Increment number in register by 1
         CJNE     R3,#10,L2                ; Check whether the number 10 is in R3
         MOV      R3,#0                    ; If it is, reset counter
L2:
         MOV      R2,#20                   ; 500 mS wait time
F02:     MOV      R1,#50                   ; 25 mS
F01:     MOV      R0,#230
         DJNZ     R0,$
         DJNZ     R1,F01
         DJNZ     R2,F02
         SJMP     LOOP

Disp:                                      ; Subroutine for writing digits
         INC      A
         MOVC     A,@A+PC
         RET
         DB       3FH                      ; Digit 0 mask
         DB       06H                      ; Digit 1 mask
         DB       5BH                      ; Digit 2 mask
         DB       4FH                      ; Digit 3 mask
         DB       66H                      ; Digit 4 mask
         DB       6DH                      ; Digit 5 mask
         DB       7DH                      ; Digit 6 mask
         DB       07H                      ; Digit 7 mask
         DB       7FH                      ; Digit 8 mask
         DB       6FH                      ; Digit 9 mask

         END                               ; End of program
Write two-digit number on LED display

It is time for time multiplex! This is the simplest example where the number 23 is displayed on two displays which represent units and tens,. It means that digit 3 should be dispalyed on the far right display and digit 2 on the display beside. The most important thing in the program is regular time synchronization. Since this is the simplest case where only two digits are used and since the microcontroller does nothing else but diaplays a number everything is very simple. Transistor T4 “turns on” display D4 and at the same time a bits’ combination corresponding to the digit 3 is set on the port. After that, transistor T4 is “turned off” and the whole process is repeated using transistor 3 and display 3 in order to display digit 2. This procedure must be continuosly repeated in order to make impression that both displays are activ at the same time.

;************************************************************************
;* PROGRAM NAME: 7Seg3.ASM
;* DESCRIPTION: Program displays number "23" on 7-segment LED display
;************************************************************************

;BASIC DIRECTIVES

$MOD53
$TITLE(7SEG3.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK
         DSEG      AT      03FH
STACK_START:       DS      040H

;RESET VECTORS
         CSEG      AT      0
         JMP       XRESET                    ; Reset vector

         ORG       100H
XRESET:  MOV       SP,#STACK_START           ; Defining of Stack pointer

LOOP:    MOV       P1,#0                     ; Turn off all segments on display
         MOV       P3,#20h                   ; Activate display D4
         MOV       A,#03                     ; Write digit 3 on display D4
         LCALL     Disp                      ; Find mask for that digit
         MOV       P1,A                      ; Put the mask on the port
         MOV       P1,#0                     ; Turn off all segments on displays
         MOV       P3,#10h                   ; Activate display D3
         MOV       A,#02                     ; Write digit 2 on display D3
         LCALL     Disp                      ; Find mask for that digit
         MOV       P1,A                      ; Put the mask on the port
         SJMP      LOOP                      ; Get back to the label LOOP

Disp:                                        ; Subroutine for writing digits
         INC       A
         MOVC      A,@A+PC
         RET
         DB        3FH                       ; Digit 0 mask
         DB        06H                       ; Digit 1 mask
         DB        5BH                       ; Digit 2 mask
         DB        4FH                       ; Digit 3 mask
         DB        66H                       ; Digit 4 mask
         DB        6DH                       ; Digit 5 mask
         DB        7DH                       ; Digit 6 mask
         DB        07H                       ; Digit 7 mask
         DB        7FH                       ; Digit 8 mask
         DB        6FH                       ; Digit 9 mask

         END                                 ; End of program
Using 4-digit LED display

In this example all four displays, instead of two, are active so it is possible to write numbers 0 - 9999. In this very case, the number 1 234 is displayed. After introductory initialization, program remains in the loop LOOP where digital multiplexing is performed.The subroutine Disp has the purpose to convert binary numbers into corresponding bit combinations for lighting segments activation on display.

;************************************************************************
;* PROGRAM NAME : 7Seg5.ASM
;* DESCRIPTION : Program displays number"1234" on 7-segment LED display
;************************************************************************

;BASIC DIRECTIVES

$MOD53
$TITLE(7SEG5.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK
         DSEG     AT     03FH
STACK_START:      DS     040H

;RESET VECTORS
         CSEG     AT     0
         JMP      XRESET                  ; Reset vector

         ORG      100H

XRESET:  MOV      SP,#STACK_START         ; Defining of Stack pointer

LOOP:    MOV      P1,#0                   ; Turn off all segments on display
         MOV      P3,#20h                 ; Activate display D4
         MOV      A,#04                   ; Write digit 4 on display D4
         LCALL    Disp                    ; Find mask for that digit
         MOV      P1,A                    ; Put the mask on the port
         MOV      P1,#0                   ; Turn off all segments on displays
         MOV      P3,#10h                 ; Activate display D3
         MOV      A,#03                   ; Write digit 3 on display D3
         LCALL    Disp                    ; Find mask for that digit
         MOV      P1,A                    ; Put the mask on the port
         MOV      P1,#0                   ; Turn off all segments on displays
         MOV      P3,#08h                 ; Activate display D2
         MOV      A,#02                   ; Write digit 2 on display D2
         LCALL    Disp                    ; Find mask for that digit
         MOV      P1,A                    ; Put the mask on the port
         MOV      P1,#0                   ; Turn off all segments on displays
         MOV      P3,#04h                 ; Activate display D1
         MOV      A,#01                   ; Write digit 1 on display D1
         LCALL    Disp                    ; Find mask for that digit
         MOV      P1,A                    ; Put the mask on the port
         SJMP     LOOP                    ; Return to the lable LOOP

Disp:                                     ; Subroutine for writing digits
         INC      A
         MOVC     A,@A+PC
         RET
         DB       3FH                     ; Digit 0 mask
         DB       06H                     ; Digit 1 mask
         DB       5BH                     ; Digit 2 mask
         DB       4FH                     ; Digit 3 mask
         DB       66H                     ; Digit 4 mask
         DB       6DH                     ; Digit 5 mask
         DB       7DH                     ; Digit 6 mask
         DB       07H                     ; Digit 7 mask
         DB       7FH                     ; Digit 8 mask
         DB       6FH                     ; Digit 9 mask

         END ; End of program
LED display as two-digit counter

Things are getting complicated... Beside two digit multiplexing, the microcontroller performs other operations “in the background” too. In this case, contents of registers R2 and R3 are incremented in order to make counting 97, 98, 99, 00, 01, 02... visible on display.

This time, transistors which activate displays remains on for 25mS. The soubroutine Delay is in charge for that. Even though digits are shifted much slower it is still not slow enough to make impression of simultaneous operating. After 20 alternate turning on and off both digits, number on displays is incremented by 1 and the whole procedure is repeated.

;************************************************************************
;* PROGRAM NAME : 7Seg4.ASM
;* DESCRIPTION: Program displays numbers 0-99 on 7-segment LED displays
;************************************************************************

;BASIC DIRECTIVES

$MOD53
$TITLE(7SEG4.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK
         DSEG      AT      03FH
STACK_START:       DS      040H

;RESET VECTORS
         CSEG      AT      0
         JMP       XRESET                   ; Reset vector

         ORG       100H

XRESET:  MOV       SP,#STACK_START          ; Defining of Stack pointer
         MOV       R2,#0                    ; Counter starting value
         MOV       R3,#0
         MOV       R4,#0

LOOP:    INC       R4                       ;Hold before to increment the content of
         CJNE      R4,#20d,LAB1             ;counter until display is 100 times refreshed
         MOV       R4,#0
         MOV       P1,#0                    ; Turn off all segments on displays
         INC       R2                       ; Increment Register with units by 1
         CJNE      R2,#10d,LAB1
         MOV       R2,#0                    ; Reset units
         INC       R3                       ; Increment Register with tens by 1
         CJNE      R3,#10d,LAB1             ;
         MOV       R3,#0                    ; Reset tens

LAB1:
         MOV       P3,#20h                  ; Activate display D4
         MOV       A,R2                     ; Copy Register with units to A
         LCALL     Disp                     ; Find mask for that digit
         MOV       P1,A                     ; Write units on display D4
         LCALL     Delay                    ; 25ms wait time
         MOV       P1,#0                    ; Turn off all segments on displays
         MOV       P3,#10h                  ; Activate display D3
         MOV       A,R3                     ; Copy Register with tens to A
         LCALL     Disp                     ; Find mask for that digit
         MOV       P1,A                     ; Write tens on display D3
         LCALL     Delay                    ; 25ms wait time
         SJMP      LOOP

Delay:
         MOV       R1,#50                   ; 25 mS
F01:     MOV       R0,#250
         DJNZ      R0,$
         DJNZ      R1,F01
         RET

Disp:                                       ; Subroutine for writing digits
         INC       A
         MOVC      A,@A+PC
         RET
         DB        3FH                      ; Digit 0 mask
         DB        06H                      ; Digit 1 mask
         DB        5BH                      ; Digit 2 mask
         DB        4FH                      ; Digit 3 mask
         DB        66H                      ; Digit 4 mask
         DB        6DH                      ; Digit 5 mask
         DB        7DH                      ; Digit 6 mask
         DB        07H                      ; Digit 7 mask
         DB        7FH                      ; Digit 8 mask
         DB        6FH                      ; Digit 9 mask

         END                                ; End of program
Handling EEPROM

Program writes data to on-chip EEPROM memory. In this case, data is hexadecimal number 23 which written to location with address 00.

To ensure that number is correctly written, the same location in EEPROM is read 10mS later and compared with original value. In case the numbers are identical, F will be displayed on LED display. Otherwise, E will be displayed on LED display (Error).

;************************************************************************
;* PROGRAM NAME: EEProm1.ASM
;* DESCRIPTION: Programming EEPROM at address 0000hex and displaying message
;* on LED display.
;************************************************************************

;BASIC DIRECTIVES

$MOD53
$TITLE(EEPROM1.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

WMCON     DATA     96H
EEMEN     EQU      00001000B              ; Access to internal EEPROM is enabled
EEMWE     EQU      00010000B              ; Write to EEPROM is enabled
TEMP      DATA     030H                   ; Defining of Auxilary register

THE END   EQU      071H                   ; Write "F" on display
ERROR     EQU      033H                   ; Write "E" on display

;STACK
          DSEG     AT     03FH
STACK_START:       DS     040H

;RESET VECTORS
          CSEG     AT     0
          JMP      XRESET                 ; Reset vector

          ORG      100H

XRESET:   MOV      IE,#00                 ; All interrupts are disabled
          MOV      SP,#STACK_START

          MOV      DPTR,#0000H            ; Choose location address in EEPROM
          ORL      WMCON,#EEMEN           ; Access to EEPROM is enabled
          ORL      WMCON,#EEMWE           ; Write to EEPROM is enabled
          MOV      TEMP,#23H              ; Number written to EEPROM is copied to
          MOV      A,TEMP                 ; register TEMP and Accumulator
          MOVX     @DPTR,A                ; Write byte to EEPROM
          CALL     DELAY                  ; 10ms wait time
          MOVX     A,@DPTR                ; Read the same location and compare to TEMP,
          CJNE     A,TEMP,ERROR           ; If they are not identical,jump to label ERROR
          MOV      A,#KRAJ                ; Write letter F on display (correct)
          MOV      P1,A
          XRL      WMCON,#EEMWE           ; Write to EEPROM is disabled
          XRL      WMCON,#EEMEN           ; Access to EEPROM is disabled
LOOP1:    SJMP     LOOP1                  ; Remain here

ERROR:    MOV      A,#ERROR               ; Write letter E on display (error)
          MOV      P1,A
LOOP2:    SJMP     LOOP2

DELAY:    MOV      A,#0AH                 ; Wait time
          MOV      R3,A
LOOP3:    NOP
LOOP4:    DJNZ     B,LOOP4
LOOP5:    DJNZ     B,LOOP5
          DJNZ     R3,LOOP3
          RET

          END                             ; End of program
Receiving data via serial communication UART

In order to enable successful serial communication using UART system, beside having correctly written program it is also necessary to meet certain rules of RS232 connection. It is about voltage levels issued by this standard. In accordance to it logic one (1) is represented by -10V in message, while logic zero (0) is transferred like +10V. The microcontroller converts data serial format without error but its power supply voltage is only 5V. It is not easy to convert 0V into 10V and 5V into -10V. Because of that, this operation is on both transmit and receive side left over to specialized IC circuit. In this example, MAX232 circuit manufactured by MAXIM is used because it is widespread, cheap and reliable.

This example demonstrates message receiving which is sent from PC. Timer T1 generates boud rate. Since quartz crystal with frequency of 11.0592 MHz is in use it is not problem to obtain standard baud rate which amout to 9600 baud. Each received data is transferred to port P1 pins.

Receiving data via serial communication UART
;************************************************************************
;* PROGRAM NAME : UartR.ASM
;* DESCRIPTION: Each data received from PC via UART appears on the port
;* P1.
;*
;************************************************************************

;BASIC DIRECTIVES

$MOD53
$TITLE(UARTR.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK
         DSEG     AT     03FH
STACK_START:      DS     040H

;RESET VECTORS
         CSEG     AT     0
         JMP      XRESET                ; Reset vector
         ORG      023H                  ; Starting address for UART interrupt routine
         JMP      IR_SER

         ORG      100H

XRESET:  MOV      IE,#00                ; All interrupts are disabled
         MOV      SP,#STACK_START       ; Initialization of Stack pointer
         MOV      TMOD,#20H             ; Timer1 in mode2
         MOV      TH1,#0FDH             ; Baud rate is 9600 baud at frequency of
                                        ; 11.0592MHz
         MOV      SCON,#50H             ; Receiving enabled, 8-bit UART
         MOV      IE,#10010000B         ; UART interrupt enabled
         CLR      TI                    ; Clear transmit flag
         CLR      RI                    ; Clear receive flag
         SETB     TR1                   ; Start Timer1

LOOP:    SJMP     LOOP                  ; Remain here

IR_SER:  JNB      RI,OUT                ; If any data is received,
                                        ; copy it to the port
         MOV      A,SBUF                ; P1
         MOV      P1,A
         CLR      RI                    ; Clear receive flag
OUT      RETI

         END                            ; End of program
Data transmission via serial communication UART

Program below describes how to use UART modul for data transmission. In concrete example, a series of numbers (0-255) are transmitted to PC at baud rate of 9600 baud. The circuit MAX 232 is used for voltage level converting.

;************************************************************************
;* PROGRAM NAME : UartS.ASM
;* DESCRIPTION: Sends values 0-255 to PC.
;************************************************************************

;BASIC DIRECTIVES

$MOD53
$TITLE(UARTS.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;STACK
         DSEG    AT    03FH
STACK_START:     DS    040H

;RESET VECTORS
         CSEG    AT    0
         JMP     XRESET               ; Reset vector

         ORG     100H

XRESET:  MOV     IE,#00               ; All interrupts are disabled
         MOV     SP,#STACK_START      ; Initialization of Stack pointer
         MOV     TMOD,#20H            ; Timer1 in mode 2
         MOV     TH1,#0FDH            ; Baud rate is 9600 baud at frequency of
                                      ; 11.0592MHz
         MOV     SCON,#40H            ; 8-bit UART
         CLR     TI                   ; Clear transmit bit
         CLR     RI                   ; Clear receive flag
         MOV     R3,#00H              ; Reset caunter
         SETB    TR1                  ; Start Timer 1

START:   MOV     SBUF,R3              ; Move number from counter to PC
LOOP1:   JNB     TI,LOOP1             ; Wait here until byte transmission is
                                      ; complete
         CLR     TI                   ; Clear transmit bit
         INC     R3                   ; Increment value of counter by 1

         CJNE    R3,#00H,START        ; If 255 bytes are not sent return to the
                                      ; label START

LOOP:    SJMP    LOOP                 ; Remain here

         END                          ; End of program
Write message on LCD display

The most frequent LCD version which displays text in two lines with 16 characters each is used in this example. Since I/O ports are always valuable, a method in which only 4 lines are used for communication is applied here. In this way each byte is transmitted in two steps: first higher one, afterwards lower nible.

You will see that, LCD needs to be initialized at the beginning (to be prepared for operating). Besides, specific parts of the program which are repeated are separated in special totalities (subroutines). All this may seem endlessly complicated at first sight, but the whole program basically performs several simple operations and displays ”Mikroelektronika Razvojni sistemi”.

Write message on LCD display
*************************************************************************
;* PROGRAM NAME : Lcd.ASM
;* DESCRIPRTION : Program for testing LCD display.4-bit communication
;* is used.Program does not check BUSY flag but uses pro
;* gram delay between 2 commands. PORT1 is used for con
;* nection to the microcontroller.
;************************************************************************

;BASIC DIRECTIVES

$MOD53
$TITLE(LCD.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING

;Stack
          DSEG     AT     0E0h
Stack_Start:       DS     020h

Start_address      EQU    0000h

                                             ;Reset vectors
          CSEG     AT     0
          ORG      Start_address
          JMP      Inic

          ORG      Start_address+100h

          MOV      IE,#00                    ; All interrupts are disabled
          MOV      SP,#Stack_Start

Inic:     CALL     LCD_inic                  ; Initialize LCD

;*************************************************
;* MAIN PROGRAM
;*************************************************

START:    MOV      A,#80h                    ; First following character will appear on first
          CALL     LCD_status                ; location in first line on LCD display.
          MOV      A,#'M'                    ; Display character ‘M’.
          CALL     LCD_putc                  ; Call subroutine for character transmission.
          MOV      A,#'i'                    ; Display character ‘i’.
          CALL     LCD_putc
          MOV      A,#'k'                    ; Display character ‘k’.
          CALL     LCD_putc
          MOV      A,#'r'                    ; Display character ‘r’.
          CALL     LCD_putc
          MOV      A,#'o'                    ; Display character ‘o’.
          CALL     LCD_putc
          MOV      A,#'e'                    ; Display character ‘e’.
          CALL     LCD_putc
          MOV      A,#'l'                    ; Display character ‘l’.
          CALL     LCD_putc
          MOV      A,#'e'                    ; Display character ‘e’.
          CALL     LCD_putc
          MOV      A,#'k'                    ; Display character ‘k’.
          CALL     LCD_putc
          MOV      A,#'t'                    ; Display character ‘t’.
          CALL     LCD_putc
          MOV      A,#'r'                    ; Display character ‘r’.
          CALL     LCD_putc
          MOV      A,#'o'                    ; Display character ‘o’.
          CALL     LCD_putc
          MOV      A,#'n'                    ; Display character ‘n’.
          CALL     LCD_putc
          MOV      A,#'i'                    ; Display character ‘i’.
          CALL     LCD_putc
          MOV      A,#'k'                    ; Display character ‘k’.
          CALL     LCD_putc
          MOV      A,#'a'                    ; Display character ‘a’.
          CALL     LCD_putc

          MOV      A,#0c0h                   ; First following character will appear on first
          CALL     LCD_status                ; location in second line on LCD display.
          MOV      A,#'R'                    ; Display character ‘R’.
          CALL     LCD_putc                  ; Call subroutine for character transmission.
          MOV      A,#'a'                    ; Display character ‘a’.
          CALL     LCD_putc
          MOV      A,#'z'                    ; Display character ‘z’.
          CALL     LCD_putc
          MOV      A,#'v'                    ; Display character ‘v’.
          CALL     LCD_putc
          MOV      A,#'o'                    ; Display character ‘o’.
          CALL     LCD_putc
          MOV      A,#'j'                    ; Display character ‘j’.
          CALL     LCD_putc
          MOV      A,#'n'                    ; Display character ‘n’.
          CALL     LCD_putc
          MOV      A,#'i'                    ; Display character ‘i’.
          CALL     LCD_putc
          MOV      A,#' '                    ; Display character ‘ ’.
          CALL     LCD_putc
          MOV      A,#'s'                    ; Display character ‘s’.
          CALL     LCD_putc
          MOV      A,#'i'                    ; Display character ‘i’.
          CALL     LCD_putc
          MOV      A,#'s'                    ; Display character ‘s’.
          CALL     LCD_putc
          MOV      A,#'t'                    ; Display character ‘t’.
          CALL     LCD_putc
          MOV      A,#'e'                    ; Display character ‘e’.
          CALL     LCD_putc
          MOV      A,#'m'                    ; Display character ‘m’.
          CALL     LCD_putc
          MOV      A,#'i'                    ; Display character ‘i’.
          CALL     LCD_putc

          MOV      R0,#20d                   ; Wait time (20x10ms)
          CALL     Delay_10ms                ;
          MOV      DPTR,#LCD_DB              ; Clear display
          MOV      A,#6d                     ;
          CALL     LCD_inic_status           ;
          MOV      R0,#10d                   ; Wait time(10x10ms)
          CALL     Delay_10ms
          JMP      START

;*********************************************
;* Subroutine for wait time (T= r0 x 10ms)
;*********************************************

Delay_10ms:  MOV   R5,00h                    ; 1+(1+(1+2*r7+2)*r6+2)*r5 approximate
                                             ; ly.
             MOV   R6,#100d                  ; (if r7>10)
             MOV   R7,#100d                  ; 2*r5*r6*r7
             DJNZ  R7,$                      ; $ indicates actual instruction.
             DJNZ  R6,$-4
             DJNZ  R5,$-6
             RET

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

LCD_enable     BIT    P1.3                   ; Bit for activating pin E on LCD.
LCD_read_write BIT    P1.1                   ; Bit for activating pin RW on LCD.
LCD_reg_select BIT    P1.2                   ; Bit for activating pin RS on LCD.
LCD_port       SET    P1                     ; Port for connection to LCD.
Busy           BIT    P1.7                   ; Port pin where Busy flag appears.

LCD_Start_I_red  EQU   00h                   ; Address of the first message charac
                                             ; ter in the first line on LCD display.
LCD_Start_II_red EQU   40h                   ; Address of the first message charac
                                             ; ter in the second line on LCD display.

LCD_DB:        DB     00111100b              ; 0 -8b, 2/1 lines, 5x10/5x7 format
               DB     00101100b              ; 1 -4b, 2/1 lines, 5x10/5x7 format
               DB     00011000b              ; 2 -Display/cursor shift, right/left
               DB     00001100b              ; 3 -Display ON, cursor OFF, cursor blink off
               DB     00000110b              ; 4 -Increment mode, display shift off
               DB     00000010b              ; 5 -Display/cursor home
               DB     00000001b              ; 6 -Clear display
               DB     00001000b              ; 7 -Display OFF, cursor OFF, cursor blink off

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

               MOV    DPTR,#LCD_DB

               MOV    A,#00d                 ; Triple initialization in 8-bit
               CALL  LCD_inic_status_8       ; mode is performed at the beginning
               MOV   A,#00d                  ; (in case of slow increment of
               CALL  LCD_inic_status_8       ; power supply when power on
               MOV   A,#00d
               lcall LCD_inic_status_8

               MOV   A,#1d                   ; Change from 8-bit into
               CALL  LCD_inic_status_8       ; 4-bit mode
               MOV   A,#1d
               CALL  LCD_inic_status

               MOV   A,#3d                   ; From this point program executes in
                                             ;4-bit mode
               CALL  LCD_inic_status
               MOV   A,#6d
               CALL  LCD_inic_status
               MOV   A,#4d
               CALL  LCD_inic_status

               RET

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

               MOVC  A,@A+DPTR
               CLR   LCD_reg_select          ; RS=0 - Write command
               CLR   LCD_read_write          ; R/W=0 - Write data on LCD

               MOV   B,LCD_port              ; Lower 4 bits from LCD port are memo
                                             ; rized
               ORL   B,#11110000b
               ORL   A,#00001111b
               ANL   A,B

               MOV   LCD_port,A              ; Data is copied from A to LCD port
               SETB  LCD_enable              ; EN=1 - EN high-to-low transition sig
                                             ; nal is generated
               CLR   LCD_enable              ; EN=0 made on EN pin of LCD display

               MOV   B,#255d                 ; Time delay in case of improper reset
               DJNZ  B,$                     ; during initialization
               DJNZ B,$
               DJNZ B,$

               POP B
               RET

LCD_inic_status:
;****************************************************************************
               MOVC  A,@A+DPTR
               CALL  LCD_status
               RET

;****************************************************************************
;* SUBROUTINE: LCD_status
;* DESCRIPTION: Subroutine for defining LCD status.
;****************************************************************************

LCD_status:    PUSH  B
               MOV   B,#255d
               DJNZ  B,$
               DJNZ  B,$
               DJNZ  B,$
               CLR   LCD_reg_select          ; RS=O: Command is sent on LCD
               CALL  LCD_port_out

               SWAP  A                       ; Nibles are swapped in accumulator

               DJNZ  B,$
               DJNZ  B,$
               DJNZ  B,$
               CLR   LCD_reg_select          ; RS=0: Command is sent on LCD
               CALL  LCD_port_out

               POP   B
               RET

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

LCD_putc:      PUSH  B
               MOV   B,#255d
               DJNZ  B,$
               SETB  LCD_reg_select          ; RS=1: Character is sent on LCD
               CALL  LCD_port_out

               SWAP  A                       ; Nibles are swapped in accumulator

               DJNZ  B,$
               SETB  LCD_reg_select          ; RS=1: Character is sent on LCD

               CALL  LCD_port_out
               POP   B
               RET

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

LCD_port_out:  PUSH  ACC
               PUSH  B
               MOV   B,LCD_port              ; Lower 4 bits of LCD port are memo
                                             ; rized
               ORL   B,#11110000b
               ORL   A,#00001111b
               ANL   A,B

               MOV   LCD_port,A              ; Data is copied from A to LCD port

               SETB  LCD_enable              ; EN=1 - EN high-to-low transition sig
                                             ; nal is generated
               CLR   LCD_enable              ; EN=0 made on EN pin of LCD display

               POP   B
               POP   ACC
               RET

               END                           ; End of program
Binary-decimal Conversion of number

While operating with LED and LCD displays, it is often needed to convert numbers from binary to decimal numerical system. For example, if some register contains a number in binary format that should be displayed on three digit LED display it is necessary to convert it to decimal format. Simply, it has to be defined what should be displayed on the far right display (units), middle display (tens) and far left display (hundreds), respectively.

Subroutine below solves this problem in case of conversion of one byte. Binary number is stored in Accumulator while digits of that number in decimal format are stored in registers R3, R2 and accumulator (units, tens and hundreds).

;************************************************************************
;* SUBROUTINE NAME : BinDec.ASM
;* DESCRIPTION : Content of accumulator is converted into three decimal
;* digits
;************************************************************************

BINDEC:            MOV     B,#10d         ; Store decimal number 10 in B
                   DIV     AB             ; A:B. Remainder remains in B
                   MOV     R3,B           ; Copy units to register R3
                   MOV     B,#10d         ; Store decimal number 10 in B
                   DIV     AB             ; A:B. Remainder remains in B
                   MOV     R2,B           ; Copy tens to register R2
                   MOV     B,#10d         ; Store decimal number 10 in B
                   DIV     AB             ; A:B. Remainder remains in B
                   MOV     A,B            ; Copy hundreds to accumulator
                   RET                    ; Return to the main program