Vous êtes sur la page 1sur 384

PIC-MDS

PIC Microcontroller Development System Training Manual


Copyright © 1996, 1998 Sirius microSystems. All rights reserved.

Second Printing.

Parallax is a Trademark of Parallax, Inc.


PICmicro™ is a Registered Trademark of Microchip Technology Inc. in the U.S.A. and other countries.

No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any
means, mechanical, electronic, photocopying, or recording, or otherwise, without the prior written permission
of Sirius microSystems.

Sirius microSystems has taken care to trace ownership of copyright material contained in this text. However,
Sirius microSystems will gladly accept any information that enables them to rectify any reference or credit in
subsequent editions.

For conditions, permissions and other rights under this copyright, contact Sirius microSystems:

Sirius microSystems
172 Harvard Road
Waterloo, ON N2J 3V3
Canada
tel.: 519.886.4462
fax: 519.886.4253
http://www.siriusmicro.com

ISBN 0-9681220-0-0 (Training Manual)


ISBN 0-9681220-1-9 (Teacher’s Reference)

Disclaimer of Liability
This manual and the program subroutines included herein are written for the Sirius microSystems PICmicro™
Development System and are provided on an “as is” basis, without any warranty, either expressed or implied.
These materials are provided for educational use only, and Sirius microSystems does not assume any liability for
damages, either incidental or consequential, arising out of the application, use, or misuse of any of its software
or hardware products. Sirius microSystems reserves the right, without further notice, to make changes to any of
its training materials, software or hardware referred to in this manual in order to improve its function, design or
reliability.

Printed in Canada.
Table of Contents
10
1 What are Microcontrollers? ......................................9
Microcontroller Features .................................................................. 10
Input/Output Ports ........................................................................... 10
Input Devices ................................................................................... 11
Output Devices ................................................................................ 12
Memory ............................................................................................ 12
Clock Circuit ..................................................................................... 15
Processing Unit ................................................................................ 15
Watch-Dog Timer ............................................................................. 15
Chapter Summary ............................................................................ 16
Questions ......................................................................................... 17
Assignments .................................................................................... 17

2 How do Microcontrollers Work? ............................ 19


Processing Unit ................................................................................ 19
Memory ............................................................................................ 20
The Outside World Connection ....................................................... 20
How do Programs get into the Microcontroller? .............................. 20
Chapter Summary ............................................................................ 21
Questions ......................................................................................... 22

3 The Microchip PIC family of Microcontrollers ...... 23


The PICmicro™ Product Range ...................................................... 23
The 18-pin PIC16CXX Product Line ............................................... 24
The PIC16F84 ................................................................................. 25
Program EEPROM .......................................................................... 25
Data EEPROM ................................................................................. 25
RAM ................................................................................................. 26
Input/Output Ports ........................................................................... 26
TMR0 ............................................................................................... 26
Watchdog Timer (WDT) ................................................................... 27
Power-Up Reset Timer (PWRT) ...................................................... 27
Oscillator .......................................................................................... 27
RAM Register Files .......................................................................... 28
STATUS ........................................................................................... 28
PCL & PCLATH ............................................................................... 28
IND0 & FSR ..................................................................................... 28
INTCON ........................................................................................... 28
Option .............................................................................................. 28
EEDATA & EEADR .......................................................................... 28
EECON1 & EECON2 ....................................................................... 28
The PIC16C711 ............................................................................... 29
Program EPROM ............................................................................. 29
Analog-to-Digital Converter ............................................................. 29
Chapter Summary ............................................................................ 30
Questions ......................................................................................... 31
Assignment ...................................................................................... 31

©1998 Sirius microSystems 3


4 Features of the PIC-MDS Development System ... 33
Power Supply Circuit ....................................................................... 35
J1 ..................................................................................................... 35
VR1 .................................................................................................. 35
JU1 ................................................................................................... 35
JU2 ................................................................................................... 36
External I/O Connectors .................................................................. 36
CON1 ............................................................................................... 36
PICBUS ............................................................................................ 37
Microcontroller Related Circuits ....................................................... 37
Microcontroller Socket ..................................................................... 37
H2 .................................................................................................... 37
Reset Button .................................................................................... 38
Y1 ..................................................................................................... 38
JU3 ................................................................................................... 38
JU6 ................................................................................................... 39
VR3 & VR4 ...................................................................................... 39
Matrix Keypad .................................................................................. 39
LED Output Indicator Bar Graph ..................................................... 40
Intelligent LCD Display .................................................................... 40
VR2 .................................................................................................. 40
RS-232 Serial Port ........................................................................... 40
JU5 ................................................................................................... 40
H3 .................................................................................................... 41
Serial EEPROM ............................................................................... 41
JU4 ................................................................................................... 41
PIC-MDS Default Jumper Locations................................................ 41
Questions ......................................................................................... 42

5 Writing a Simple Program ...................................... 43


Examining Source Code—Microchip Code ..................................... 44
Source Code Conventions .............................................................. 45
Some Other Common Source Code Conventions .......................... 46
Examining the Program ................................................................... 47
The Maclib Directive ........................................................................ 47
The Device and ID Directives .......................................................... 47
The ORG Directive .......................................................................... 47
Program Code ................................................................................. 48
Ending the Editing Process ............................................................. 49
Chapter Summary ............................................................................ 49
Questions ......................................................................................... 50
Assignment ...................................................................................... 50

6 Assembling a Program ........................................... 51


Assembling the Program ................................................................. 51
Object Code ..................................................................................... 54
Chapter Summary ............................................................................ 54
Questions ......................................................................................... 55
Assignment ...................................................................................... 55

Table of Contents
4 ©1998 Sirius microSystems
7 Downloading a Program ......................................... 57
Which Microcontroller Should I Program? ....................................... 57
Programming ................................................................................... 57
Downloading the Object Code......................................................... 59
Running the Program ...................................................................... 60
Reprogramming PIC Microcontrollers.............................................. 60
Chapter Summary ............................................................................ 60
Questions ......................................................................................... 61
Assignment ...................................................................................... 61

8 Looping .................................................................... 63
Infinite loops ..................................................................................... 63
Finite Loops ..................................................................................... 65
Nested Loops................................................................................... 66
Calculating Execution Times ........................................................... 68
Chapter Summary ............................................................................ 70
Questions ......................................................................................... 71
Assignment ...................................................................................... 72

9 Switch Input Programming .................................... 73


Interfacing to Switches .................................................................... 73
Counting Switch Activations ............................................................ 76
Switch Debouncing .......................................................................... 78
Interfacing to Matrix Keypads .......................................................... 80
Chapter Summary ............................................................................ 84
Questions ......................................................................................... 85
Assignment ...................................................................................... 86

10 Calls and Includes................................................... 87


Include, CALL and RETURN ........................................................... 87
Reading ROM Data Tables using Calls ........................................... 91
Chapter Summary ............................................................................ 96
Questions ......................................................................................... 97
Assignment ...................................................................................... 98

11 Interrupts ................................................................. 99
Interrupt Registers and Flags ........................................................ 100
TMR0 Interrupt ............................................................................... 100
INT Interrupt ................................................................................... 101
Port B Change Interrupt................................................................. 101
EEPROM Interrupt ......................................................................... 101
A/D Converter Interrupt ................................................................. 102
Interrupt Service Routines ............................................................. 102
Using Interrupts to Wake-up on Key Press ................................... 103
Managing Multiple Tasks using the TMR0 Interrupt ...................... 106
Chapter Summary ........................................................................... 111
Questions ....................................................................................... 112
Assignment .................................................................................... 112

©1998 Sirius microSystems 5


12 Using the LCD Display .......................................... 113
The LCD Interface ......................................................................... 113
LCD Enable ................................................................................... 115
LCD Register Select ...................................................................... 115
LCD Read/Write ............................................................................ 115
LCD Commands ............................................................................ 115
LCD Initialization ............................................................................ 116
LCD Display Addressing ................................................................ 117
Absolute Addressing ...................................................................... 118
Relative Addressing ....................................................................... 118
Displaying LCD Characters ........................................................... 118
Creating Custom Characters ......................................................... 125
CGRAM .......................................................................................... 125
Chapter Summary .......................................................................... 129
Questions ....................................................................................... 130
Assignment .................................................................................... 130

13 Using the PIC16F84 Data EEPROM ..................... 131


Using the PIC16F84 Data EEPROM .. 131Reading From and Writing
To the Data EEPROM .................................................................... 132
Chapter Summary .......................................................................... 137
Questions ....................................................................................... 138
Assignment .................................................................................... 138

14 Troubleshooting .................................................... 139


Identifying and Isolating Faults ...................................................... 139
Validating Your Hardware .............................................................. 139
I/O Requirements ........................................................................... 139
Shared I/O Lines ............................................................................ 140
“Playing” the Computer .................................................................. 140
Displaying Intermediate Values ..................................................... 141
External Triggers............................................................................ 141
Commenting Out Code .................................................................. 141
Isolating Faults within Subroutines ................................................ 142
Taking Breaks and New Approaches ............................................ 142
Memory Page Boundaries ............................................................. 142
A/D Converter Troubleshooting ..................................................... 144
Simulators and Emulators ............................................................. 144
Programming for Easy Troubleshooting ........................................ 144
Plan, Plan, and Plan ...................................................................... 144
Code and Debug Individual Program Tasks .................................. 144
Modularize Your Code ................................................................... 145
Comments ...................................................................................... 145
Chapter Summary .......................................................................... 145
Questions ....................................................................................... 146
Assignment .................................................................................... 146

Table of Contents
6 ©1998 Sirius microSystems
15 RS-232 Serial Communication ............................. 147
RS-232 Basics ............................................................................... 147
Receiving RS-232 Data ................................................................. 149
Transmitting RS-232 Data ............................................................. 154
Chapter Summary .......................................................................... 158
Questions ....................................................................................... 159
Assignment .................................................................................... 159

16 A/D Conversion ..................................................... 161


The PIC16C711 A/D Converter ..................................................... 161
ADCON0 Register ......................................................................... 162
ADCON1 Register ......................................................................... 163
Measuring Voltage using the A/D Converter ................................. 163
Chapter Summary .......................................................................... 170
Questions ....................................................................................... 171
Assignment .................................................................................... 172

17 Interfacing to a Serial EEPROM ........................... 173


The 93LC56 Serial EEPROM ........................................................ 173
The Serial EEPROM Data Frame .................................................. 174
Serial EEPROM Instructions.......................................................... 174
Using the SEEPROM..................................................................... 175
Chapter Summary .......................................................................... 181
Questions ....................................................................................... 182
Assignment .................................................................................... 182

18 The Watch Dog Timer ............................................ 183


Handling Software Faults using the WDT ..................................... 184
Enabling the WDT ......................................................................... 186
Waking the PIC using the WDT .................................................... 186
Chapter Summary .......................................................................... 188
Questions ....................................................................................... 189
Assignment .................................................................................... 189

Apendix A - PIC-MDS Installation and Setup ............. A1


PIC-MDS Professional Package ...................................................... A3
PIC-MDS Professional ..................................................................... A3
PIC-MDS Hobbyist Package ............................................................ A3
PIC-MDS Hobbyist ........................................................................... A3
PIC-MDS Requirements .................................................................. A4
Windows 3.x and Windows 3.11 for Workgroups ........................... A4
Windows 95 ..................................................................................... A4
OS/2 Warp v.3 and OS/2 Warp Connect ........................................ A4
Installing the Software ..................................................................... A4
If you are using the PIC-MDS with the EPIC Programmer... ........... A4
If you are using the PIC-MDS with a third-party programmer... ...... A5
PIC-MDS Setup ............................................................................... A5
Connecting the EPIC Programmer .................................................. A5
Connecting the PIC-MDS ................................................................ A7
Assembling and Downloading Programs ........................................ A8

©1998 Sirius microSystems 7


Appendix B - Troubleshooting .................................... B1
Troubleshooting ............................................................................... B3
Software Installation ........................................................................ B3
If the installation program does not work correctly: ......................... B3
If the installed files are not in the volume or directory expected: .... B3
Assembling Programs with ASM ..................................................... B3
If you get a “Bad Command or File Name” message: ..................... B3
If you get a “Fatal : [302] Unable to Open File” message: .............. B4
“Error filename.SRC 1 : [202] Illegal Character” message: ............. B4
Starting the EPIC Programmer Software ........................................ B4
If you get a “Bad Command or File Name” message: ..................... B4
If you get a “Programmer Not Found” message: ............................ B4
If the object code of the file does not appear in the EPIC window: B5
Downloading Programs ................................................................... B5
If you get a “Verify Error at ” message: ........................................... B5
Assembling, Downloading and Running Programs ......................... B5
If the PIC-MDS Chapter examples don’t work: ................................ B5
Converting PIC-MDS Source Code ................................................. B6
for Third-Party Tools ........................................................................ B6
If you use a third-party assembler: .................................................. B6

Appendix C - PIC Macro Assembler Reference ......... C1

Appendix D - Parallax Instruction Set Reference ...... D1

Program Pull-out References

Data Sheets

Table of Contents
8 ©1998 Sirius microSystems
What are
1 Microcontrollers?

What are Microcontrollers?


A microcontroller is essentially an entirely self-con-
tained computer on a chip. Like personal computers,
microcontrollers have memory, processing units, and in-
put/output circuitry. Unlike personal computers, micro-
controllers don’t have keyboards, monitors, disk drives
or mice—and programs are not loaded into microcon-
trollers to change their function from playing games to
calculating finances. In fact, microcontrollers are pro-
grammed to perform only one very specific task. Mi-
crocontrollers are computers designed to control spe-
cific processes or products. Applications that use mi-
crocontrollers include household appliances, electronic It’s hard to believe, yet this
devices, automobile subsystems, electronic instrumen- single chip microcontroller
is a complete computer.
tation, and even certain parts or functions of personal
computers.

Microcontrollers are small and inexpensive allowing them to be built into, or Microcontrollers are
‘embedded’ into, other devices to make these products more intelligent and easier to computers designed to
use. One microcontroller can replace a number of separate parts, or even a complete control specific processes
circuit. Product manufacturers stand to gain the following benefits by incorporating or products.
a microcontroller in their design:
• increased reliability due to one microcontroller replacing many parts
• reduced inventory, simplified product assembly and smaller end products
• greater product flexibility and adaptability since features are programmed into
the microcontroller and not built into hardware
• rapid product changes by changing the program and not the hardware

Microprocessors such as the Intel Pentium™ get more main-stream attention,


but microcontroller manufacturers such as Microchip sell hundreds of microcontrol-
lers for every microprocessor sold.
Chapter 1
©1998 Sirius microSystems 9 Microcontrollers
Microcontroller Features
Electronic designers Outside World
have a great deal of choice
when deciding on a micro-
controller for their next
Micro-Controller Input Output
project. A large number of Block Diagram Circuitry Circuitry
microcontroller families
exist, with even greater
variations within each fam-
Permanent Temporary
ily. Manufacturers tailor Memory Memory
the features of each micro-
controller or microcontrol-
ler family to specific types
of applications. It becomes Clock
easy for a designer to Processing Unit
Circuit
choose just the features and
memory size that are re- Timer
quired for the application, Circuitry
keeping costs low by not block1

buying unneeded capabil-


ity. Microcontrollers contain all of these functions on a
simgle silicon chip.
In general, all microcontrollers share some basic features. As a computer-on-a-
chip, microcontrollers contain input circuitry to interface with their environment, a
processing unit that executes the control program, permanent memory to hold the
control program, temporary memory to hold operating variables, a clock circuit to
orchestrate operations, a timing circuit (usually called a watchdog timer) for reliabil-
ity, and output circuitry to interface to other devices or processes. Optional features
might include specialized timing and pulse circuits, communication capability, ana-
log input/output connections, or other inputs and outputs tailored to specific sensors
or transducers. In the paragraphs that follow, we will compare each of the basic
features of a microcontroller with those found in personal computers. We’ll do this
by looking at two typical control applications: a microwave oven, and an automotive
engine control computer.

Input/Output Ports
Most microcontrollers have built-in input/output (I/O) circuitry that makes it
easy for input and output devices to be added to them. Their input ports have special
UARTs—Universal Asyn- features such as counters, comparators, serial UARTs, or analog-to-digital convert-
chronous Receiver Trans- ers. Microcontroller output ports can often supply higher current to output devices
mitters—are used in serial than standard microprocessors and ordinary logic circuitry. By adapting the
communications. microcontroller’s I/O circuitry to special applications, the need for external circuitry
is reduced, allowing a single microcontroller to take the place of many other compo-
nents.

Personal computers normally use I/O cards to add the type of functionality that
comes built into microcontrollers. For example, most microprocessors found in per-
sonal computers have general purpose I/O circuitry and require a serial/parallel I/O
Microcontroller
Features PB ©1998 Sirius microSystems
card to connect to modems, mice, printers and scanners. A SCSI or IDE interface
card allows the microprocessor to connect to hard disks and CD-ROM drives. Ethernet
cards allow connections to networks. In a personal computer, the device or applica-
tion determines the type of interface card required to a attach a peripheral to the
general purpose microprocessor.

In the case of microcontrollers, the expected input and output devices and appli-
cation determine the processor itself, since the processor incorporates all of the I/O
circuitry. Often, microcontroller manufacturers produce different versions of the same
basic microcontroller model by changing the type of I/O ports it includes.

It’s easier to under-


stand this concept if we
use a simple analogy. If a
housing contractor is
ready to buy a new vehi-
cle for his (or her) busi-
ness, a pick-up truck
would be better able to
carry lumber and bricks
than a Ferrari. In micro-
controller families, just as
in real life, choose the de-
vice to fit the purpose. Duh Homes went out of business shortly after young Harry took over while
his father vacationed in the Carribean.

Input Devices
Personal computers have standardized input de-
Tachometer
vices—you wouldn’t buy one without a keyboard or a
mouse. You might add a joystick or scanner to your com-
puter. Since microcontrollers are embedded into so many Throttle
Position
products, their input devices reflect the function that the Sensor
product performs. An engine control computer requires
Exhaust
very little in the way of input from the user, but still has Temperature
Sensor
many input sensors. These would include throttle posi-
tion sensors, crankshaft position or speed sensors, oil
and coolant temperature sensors, exhaust gas sensors
and even wheel-speed sensors. The obvious input de-
vice on a microwave oven would be the keypad on the
front of the unit. The door switch of a microwave is an
Micro-Controller Input Output
equally important input device—just try (no, don’t try) Block Diagram Circuitry Circuitry

cooking something with the door open! Some microwave


ovens also include temperature probes or humidity sen- Permanent
Memory
Temporary
Memory
sors. It is the microcontroller’s job to know not only
how to cook your food, but also when it is safe to cook
Clock
it, and when the food is done cooking. Circuit
Processing Unit

Timer
Circuitry
input2

Chapter 1
©1998 Sirius microSystems 11 Microcontrollers
Output Devices
The output of a per-
Key Pad
Time C sonal computer is usually
L
Power R displayed on a monitor, or
30
sec
1
min
2
min
5
min 7 Segment Display
can come from a speaker
10% 30% 50% 100% as sound, or can be in the
The 7-segment display,
beeper and magnetron are 1 2 3 S form of a print-out. Micro-
T controllers also connect to
output devices specific to a Door 4 5 6 A
Switch R
microwave oven. 7 8 9 T
a variety of devices spe-
Magnetron cific to the application. For
0 Stop
example the front panel
display on a microwave in-
Beeper
dicates the cooking time
Micro-Controller Input Output and mode that was se-
Block Diagram Circuitry Circuitry lected, but the microcon-
troller also modulates the
power of the magnetron
Permanent Temporary
Memory Memory used to cook your food.
The engine control compu-
ter outputs ignition spark
timing, fuel injector duty
Clock
Circuit
Processing Unit cycle, and cooling fan op-
eration. A number of to-
Timer tally different output de-
Circuitry vices can be controlled by
input3
one microcontroller.

Memory
Outside World Personal computers come with two types of memory:
permanent memory and temporary memory. One type Hard
Micro-Controller Input Output
Block Diagram Circuitry Circuitry of permanent memory—the Basic Input/Output System, Disk
or BIOS—is a read-only memory (ROM) that contains
Permanent
Memory
Temporary
Memory
programs which tell the microprocessor how to interact
with its peripheral devices, such as the monitor or key-
board. Hard disks are another form of permanent stor-
Clock Processing Unit
Circuit age for application programs. The applications are cop-
ROM RAM
Timer ied from hard disk to temporary memory, or random- BIOS
Circuitry
block1 access memory (RAM). While the computer is turned
on, the RAM contains one or more active programs.
When the computer is turned off, the contents of RAM
Processing Unit
are erased, so all programs and data must be saved in mo1

permanent memory.
Personal computers load
Microcontrollers have both permanent and tempo- one or more application
rary memory on-chip. As in personal computers, ROM programs stored on hard
is the permanent memory that remembers its operating disk into RAM. The micro-
programs while the device is off. Since microcontrollers processor then executes the
have no hard disk storage, and usually only one operat- application programs from
the computer’s RAM.
I/O Devices and
Memory PB ©1998 Sirius microSystems
ing program, ROM is the only permanent memory they
need. RAM is used only as a ‘scratch pad’ to hold tem-
porary data and changing input or output variables. A Microcontrollers use ROM
microwave might use RAM to store the current cook- to store their operating
ing mode and the cooking time remaining. An engine Program program. A small amount
ROM of RAM is necessary to
controller would use RAM to hold a digital value rep-
resenting the temperature, speed, or position of all of hold variables and chang-
ing data.
the inputs. The ROM in both the microwave oven and RAM
the engine control computer holds the control program
that makes them work.

Even though both personal computers and micro- Processing Unit


M02
controllers use the same types of memory for similar
functions, the relative amounts of memory are far dif-
ferent. It is not uncommon for a personal computer to have from 500 Mb (million 1 kilobyte is actually 210 or
bytes) to over 1 Gb (billion bytes) of permanent storage on the hard disk. RAM 1 024 bytes. A megabyte is
20
ranges from 4 Mb to 128 Mb or more depending on the expected application pro- 2 or 1 048 576 bytes.
grams. Microcontrollers have far less memory, typically 512 bytes to 4 kb (thousand
bytes) of ROM, and 20 to 512 bytes of RAM. Each byte contains one instruction, or
one number or character. Why is there such a great difference in memory size be-
tween computers and microcontrollers?

The memory size difference between com-


puters and microcontrollers relates mainly to
the size and function of the devices. Microcon-
trollers must be self-contained. Therefore, all
of a microcontroller’s memory must fit onto a
small silicon chip in addition to the input/out-
put circuitry and the processing unit itself. There
just isn’t room on the chip for a large amount
of memory. Also, the microcontroller has only
one function and needs only one program which
occupies a small amount of ROM. Since there
is only one active program, a large amount of
RAM is not needed to hold a copy of the active
program, and the program can be executed di-
In a typical microcontroller die, rectly from ROM. A small amount of RAM is
memory takes up a comparatively necessary only to hold any changing informa-
large amount of space. tion during program execution.
Courtesy of Microchip Technology, Inc.

Personal computers, on the other hand, require a temporary memory large enough
to hold a control program (the operating system of the computer—for example,
Windows 95, or MacOS) as well as any application programs (such as a word proc-
essor) and temporary data (the file being edited). The operating system is called
upon to hold information about how to use all of the input/output devices attached to
the computer as well, also requiring memory. The hard disk, or permanent memory,
must hold all of the programs and all of the data while the computer is off. For this
reason, the hard disk is much larger than the RAM.

The difference in memory size between microcontrollers and computers can also
be partially attributed to differences in the sizes and types of processing units. The
‘bit-width’ determines how large a binary number the processing unit can handle.
Chapter 1
©1998 Sirius microSystems 13 Microcontrollers
Typical computer micro-
ROM RAM ROM RAM processors are 32-bit or
BIOS 8 bit BIOS 32 bit even 64-bit giving them a
rich instruction set and
many features—ideal for
running many types of pro-
grams. Computers typi-
cally also have wide
‘buses’ or groups of wires
8-Bit Processing Unit 32-Bit Processing Unit
bit
that connect to the memory
and peripherals. A 32-bit
Microcontrollers require less memory than microprocessors with wide buses. wide bus (8-bits to a byte,
so this is a 4 byte bus) is
used to transport instructions and data to the 32-bit processor. The computer memory
needs to be bit because it must feed four bytes at a time to the microprocessor.

Microcontrollers can be 32-bit, but since most control programs are fairly sim-
An embedded version of the ple and straightforward, 8-bit and 16-bit processors are very widely used. Loading
32-bit PowerPC microcon-
one byte at a time into an 8-bit processor requires four times less memory than
troller is being used as an
engine control computer in loading 4 bytes at a time into the microprocessor in the personal computer. The trade-
some current cars. off is that a one-byte number can encode fewer instructions than a 4 byte number,
resulting in reduced instruction flexibility in the microcontroller.

Microcontrollers can contain four types of ROM: mask ROM, OTP ROM,
EPROM, or EEPROM. Mask ROM is programmed with the designer’s application
program during the chip manufacturing stage. As such, mask ROM is very cost
effective for large quantities of a microcontroller with the same program. Since mask
ROM is permanent, a designer must be sure that no more changes are required to the
program before committing to mask ROM. OTP (one-time-programmable) ROM
allows the designer to program the microcontroller during assembly of the product.
Code changes can be made at any time during the assembly cycle, giving the designer
more flexibility and extra peace of mind for fixing the inevitable bugs. OTP ROM
microcontrollers are only slightly more expensive than mask ROM versions, making
them ideal for small to medium size production runs. EPROM (erasable-program-
mable ROM) microcontrollers are programmed during assembly like OTP micro-
controllers, but can also be erased with exposure to ultraviolet light. EPROM micro-
controllers are distinguishable by their ceramic chip packages with a clear window
The window of the PIC on the top. Since this elaborate packaging is more expensive than the typical plastic
16C711 allows ultraviolet chip package, EPROM microcontrollers are most often used during program devel-
light to enter and erase the opment or whenever changes are required to be made in the field. Engineers and
EPROM. designers can test and evaluate new programs and then just erase the programs to
continue development. Finally, EEPROM (electrically erasable-programmable ROM)
microcontrollers can be erased and re-programmed electrically, without ultraviolet
light and so benefit from cheaper packaging. EEPROM microcontrollers can be
embedded into complex assemblies and programmed or erased without removing
them from the circuit making them extremely flexible. Most EEPROM microcontrol-
lers have a finite number of program/erase cycles, so continuous re-programming is
not recommended.

Memory
PB ©1998 Sirius microSystems
Clock Circuit Outside World

The clock oscillator circuit is a required part of any processing unit, including Micro-Controller Input Output
Block Diagram Circuitry Circuitry
those found in microcontrollers. The clock circuit generates a high frequency square
wave that is used to synchronize all internal operations. It is essentially the ‘orchestra Permanent Temporary
Memory Memory
conductor’ or ‘traffic cop’, ensuring that all parts of the processing unit maintain
synchronization.
Clock Processing Unit
Circuit
Most microcontrollers include built-in clock circuits that can generate a range of
Timer
clock frequencies. A few external components are used to create the clock signal or Circuitry
block1

to select the clock frequency. Clock signal frequencies can range from a few hertz to
over 20 MHz. As with everything else in life, there are trade-offs involved in select-
ing the clock frequency. Running the microcontroller at a higher clock frequency
results in the microcontroller accomplishing a task more quickly than at a lower
clock frequency. Lower clock frequencies, however, reduce electrical current drain
as well as operating power (and the heat produced during operation) prolonging
battery life as well as potentially increasing the lifetime reliability of the microproc-
essor.

Processing Unit Outside World

The processing unit is the most important part of the microcontroller and defines Micro-Controller Input Output
Block Diagram Circuitry Circuitry
the features, functions and ease of programmability of the device or system to be
created. Electronic designers swear by their favourite microcontrollers with an al- Permanent Temporary
Memory Memory
most religious fanaticism, claiming theirs is the fastest, or the cheapest, or the most
easy to use. It’s often very difficult to convert a seasoned programmer to another
‘religion’. Clock
Circuit
Processing Unit

Timer
The function of the processing unit is to execute the control program. In any Circuitry
block1

microcontroller, the processing unit reads the instructions from the ROM (permanent
memory), decodes each instruction, and carries out one or more operations for each
instruction. The speed at which these operations occur is controlled by the clock
circuit.

Watch-Dog Timer Outside World

Watch-dog timers were developed because control programs or devices can fail. Micro-Controller Input
Circuitry
Output
Circuitry
Block Diagram
When your personal computer software fails it’s relatively easy to recover. At most,
you may lose a portion of a file and a few minutes of time while you restart your Permanent Temporary
Memory Memory
computer. When the microcontroller operating your pacemaker fails, waiting in line
to see your doctor for a CTRL-ALT-DEL reset isn’t a desirable option!
Clock Processing Unit
Circuit
Watch-dog timers are oscillator circuits independent of the main oscillator and Timer
are always running. Your program must be designed to reset the watch-dog timer Circuitry
block1

during its execution. If your program fails, the watch-dog timer will time out and
reset the microcontroller, restarting your program from a known state.

Chapter 1
©1998 Sirius microSystems 15 Microcontrollers
Chapter Summary
Microcontrollers are built in many varieties to perform very specific functions,
whereas personal computers are available with only a small variety of general pur-
pose microprocessors. Microcontrollers are more suited to specific control tasks where
size and cost is a concern. Because a microcontroller is a single chip computer, a
microcontroller can offer a single-chip solution to a design problem. While they are
single-chip computers, microcontrollers are nowhere near as powerful as microcom-
puters. Microcontrollers typically have less memory, lower operating speeds, and
most often run only a single program. Their advantages are that they are small,
inexpensive, complete computers with integrated I/O circuitry.

Personal Computer Microcontroller


Size Laptop to Desktop Pea size to VHS tape
Memory External - 10’s of Mb Internal - 100’s of bytes
Processor 32 - 64 bit 4 - 32 bit
Clock Speed 133 MHz - 575 MHz DC - 50 MHz
Price $100.00 - $1000.00 $2.00 - $20.00
Power Requirements 0.5 W - 10 W 10 µW - 1 W
Programming Numerous (Basic, C, Limited to Assembly, C,
Languages C++, Java, etc.) Basic, Forth
Complexity of design Very complex Simple
Application General purpose Dedicated to specific
purpose

Chapter Summary
PB ©1998 Sirius microSystems
Questions
1. What types of household appliances can benefit from microcontrollers?

2. What parts of personal computers would contain microcontrollers?

3. Why does a microcontroller require far less RAM than a personal computer?

4. Why are the cheapest microcontrollers OTP?

5. How do microcontroller and personal computer input/output devices differ?

6. Compare and contrast the uses of RAM and ROM in personal computers and
microcontrollers.

Assignments
1. Create a chart similar to that on the opposite page comparing a typical compu-
ter system to one of the PICmicro™ family microcontrollers. Use a databook
or distributor catalog to find some of the information.

2. Describe a project that you would like to build that uses a microcontroller.
State why the project is ideally suited to using a microcontroller.

3. Sketch a large block diagram of a micro-controller and include a short state-


ment describing the function of each block within each.

Office productivity improved greatly after the introduction of the PICranialTM Brain
interface network adapters.

Chapter 1
©1998 Sirius microSystems 17 Microcontrollers
Notes
PB ©1998 Sirius microSystems
How do Microcontrollers
2 Work?

Microcontrollers work the same way that any computer works. They read an
instruction from memory, determine its meaning, and perform the operation(s) speci-
fied by the instruction. This is known as a fetch-decode-execute cycle and this cycle
takes place thousands or even millions of times each second. All computer proces-
sors repeat this simple cycle when executing programs.

Processing Unit
As shown in the block diagram, the ROM Dual Memory Stack
contains the program instructions. The Pro- Harvard Architecture Harvard architecture is the
gram Counter tells the Instruction Fetch/De- term used to describe
ROM RAM
microcontrollers which
code unit which memory location to address. Contains Contains
Program Data have separate memory
The instruction in the memory location that
Instructions
stacks (memory address
the program counter points to is decoded and ranges) for permanent
sent to the ALU (arithmetic/logic unit). The memory, temporary
ALU executes the instruction by performing memory and I/O devices.
simple arithmetic or logic operations on bi- To the
nary numbers. The results of these operations outside
world
are stored in a working register (W) or to I/O Port
memory. Results are never stored to ROM be-
cause ROM is Read Only Memory. When the
cycle is complete, the Fetch/Decode unit gets
the next instruction from memory. Processing
Unit
Fetch/Decode Unit
The clock oscillator circuit advances the
program counter. Unless the program counter ALU
is modified by the previous instruction, the next
instruction in the program sequence is fetched, W

decoded and executed. After this, the next in- Program Counter
struction is fetched, decoded and executed, and
so on. The entire operation of any computer
boils down to just three words: fetch, decode
and execute! That’s it.
Chapter 2
©1998 Sirius microSystems 19 How do Micro-
controllers work
Memory
Memory is organized as a sequentially
Single Memory Stack numbered stack of storage locations. Each
Microprocessors with a RAM memory location has its own unique address.
single, continuous memory Contains Some microcontrollers have places for
stack (or memory address Data RAM, ROM and I/O circuitry assigned in
range) are said to have a a single memory stack, while others have
memory mapped architec-
separate RAM, ROM and I/O stacks. When
ture. ROM
Contains there is only one memory stack, the micro-
Instructions To the controller is said to have a memory mapped
outside architecture (see right diagram). When there
world
I/O Port are separate memory stacks for instructions
(ROM) and data (RAM) the microcontrol-
ler is said to have a Harvard architecture.
All PICmicro™ microcontrollers use
Processing Harvard architecture.
Unit
Fetch/Decode Unit
Note that when they are separated, the
ALU microcontroller must distinguish between
RAM and ROM memory locations. This is
W done by using specific memory or I/O in-
structions to address each type of memory.
Program Counter

The Outside World Connection


I/O ports connect a microcontroller to the outside world. All ports have a memory
location or address which can be accessed by the processing unit. I/O ports are unique
in that external signals or the processor can modify their contents. In contrast, only
the processor can modify the memory contents. When the processor modifies the I/O
port contents, they appear as a voltage on the external pins of the microcontroller.
Most microcontroller I/O ports can be programmed to be either inputs or outputs.

How do Programs get into the Microcontroller?


Microcontroller programs are most often written as assembly language mne-
monics called source code (see the Data Sheets for a list of all mnemonics). Mnemon-
ics are short (3-5 letter) command representations that help programmers to remem-
ber the function of instructions. An assembler program converts mnemonics into
machine code. Machine codes are binary numbers that the microcontroller interprets
as instructions. This binary number representation is called object code and is pro-
grammed into the microcontroller ROM using a programmer. Programmers are hard-
ware devices that connect to your PC and have a socket that accommodates the
microcontroller.

Memory
20 ©1998 Sirius microSystems
;VISINE.SRC V1.0 Simple addition and vision test :020000000528D1
program for Chapter 2. :10000A00502058208C010C0814200038031910289D
:10001A006C208C0A0828183068204520102882078E
;Demonstrates use of registers, small characters and :10002A0053346934723469347534733420344D343A
:10003A006934633472346F345334793473347434B6
Device PIC16C71,HS_OSC,WDT_OFF,PROTECT_OFF, PWR :10004A0065346D347334203426342034E434453432
ID ‘X+Y=’ :10005A006E34673469346E346534653472346934A5
:10006A006E34673420344C3461346234733400346F
ORG
GOTO
00h
05h
;Reset Vector
;Jump over interrupt ve
:10007A008E011A308F008E0B40288F0B4028080003
:10008A008E018F01043090008E0B49288F0B49286E
010100101000101100010001000
ORG 05h ;Actual program starts :10009A00900B492808008316F83085050001860070
:1000AA00831205110800383068203D203830682056
;Hardware Equates :1000BA003D20383068203D200C306820013068200F
:1000CA000630682008000510860071208128051076
X EQU 0Ch ;X is a label given to :1000DA00860071200514812885148316FF30860056
Y EQU 0Dh ;Y is the label for the :1000EA00831205150000861B782805118316000166
Result EQU 0Eh ;Register 0E is labelle :1000FA008600831285100800051500000511080006
:084000004C0043004400540091
;Software Equates :02400E001A0096

Source code is converted by an Object code which is downloaded Machine code, the form of
assembler program into... to a programmer which programs instructions the microcontroller
the microcontroller using... understands.

Some programmers use PC-based simulators to verify the operation of their pro-
grams. Simulators allow a programmer to examine internal registers and program
flow, helping them to find bugs. Since program execution is simulated and the micro-
controller does not run in the target system, real-world timing problems may not be
uncovered by a simulator.

Another popular PC-based debugging tool is an emulator. An emulator connects


to your microcontroller target circuit in place of your microcontroller. The emulator
has functions similar to a simulator with the added bonus of actually running the
program in your target system. As a general rule, emulators are more expensive than
simulators.

Microcontroller to
be programmed
The computer downloads
machine code to the
programmer which ‘burns’
the code into the micro-
controller.

Microcontroller
Progammer

Programming Socket

Chapter Summary
All microcontrollers execute programs by performing math or logic operations
in a fetch-decode-execute cycle. Instructions are fetched from ROM, and can modify
RAM or I/O ports. Likewise, the contents of RAM and I/O can affect program in-
structions. Programs are written in assembly mnemonics, converted to object code
by the assembler program, and programmed into the processor with a programmer.
Simulators are often used to examine the program flow during execution to check for
errors.
Chapter 2
©1998 Sirius microSystems 21 How do Micro-
controllers work
Questions

1. Why is the result of an operation never stored to ROM?

2. What relationship does clock speed have to program operation?

3. Explain the difference between assembler and downloader software.

4. How do ports differ from memory locations?

5. What are the advantages of using an emulator vs. a simulator?

While ‘burning’ microcontrollers for the PICranialTM brain interface, Dr. von
Netzkopf utilized the services of many beta testers.

Questions
22 ©1998 Sirius microSystems
The Microchip PIC family
3 of Microcontrollers

The Microchip PICmicro™ family of microcontrollers is well established and Harvard architecture allows
inexpensive. PICmicro™ microcontrollers have been used for many applications in- simultaneous access to both
cluding computer mice, remote controls, and caller-ID decoders. The reasons that the RAM and ROM. RISC
PICmicro™ family is so popular are due to low cost, high-speed devices and inex- stands for Reduced Instruc-
tion Set Computer.
pensive development tools. Its speed stems from its architecture—a modified Harvard
architecture—and its RISC-like instruction set. RISC computers are characterized
by having a small instruction set in which each instruction executes very quickly. In
this case, every instruction is a single word long and executes in a single clock cycle. Actually, instructions that
modify the program counter
require two instruction
cycles to complete.
The PICmicro™ Product Range
Microchip, the manufacturer of PIC microcontrollers, have three ranges of
PICmicro™ microcontrollers (mcu’s) to choose from. The PIC16C5X series of parts
make up the low-end, the more powerful PIC16CXX chips form the mid-range line
and the PIC17CXX family completes the high-end. The chart below outlines the
various PICmicro™ families.
PIC MCU Program Data I/O Clock Peripherals Price
Families Memory Memory Pins Speed Range
ROM RAM (MHz) (qty.1)
(Words) (Bytes)

PIC12C5XX 512 - 2k 24 - 73 6 - 20 4 - 20 1 8-bit timer, WDT $2.00 - The main factor that
PIC16C5X 12-bit core $15.00 distinguishes the three
PICmicro™ families is the
instruction size of the core:
PIC12C67X 512 - 8k 36 - 368 6 - 52 4 - 20 1 to 3 8-bit timers, $4.00 -
12-bit in the low-end, 14-
PIC16C55X 14-bit core WDT, 8-bit A/D, DAC, $25.00
PIC16C6X comparators, USART, bit in the mid-range, and
PIC16C7X SPI/I2C, EEPROM, 16-bit in the high-end.
PIC16C9X capture/compare/
PIC14000 PWM, LCD drivers
PIC17C4X 2k - 16k 232 - 902 33 33 4 8/16-bit timers, $13.00 -
PIC17C75X 16-bit core WDT, 12-bit A/D, $35.00
SPI/I2C, USART,
capture/compare/
PWM, expandable
Chapter 3 - The
©1998 Sirius microSystems 23 Microchip PIC family
of Microcontrollers
The 18-pin PIC16CXX Product Line

PICmicro Program Data Clock A/D Analog Brown EEPROM T imers


MCU ROM RAM Speed chan. Comp. Out (Bytes)
(Words) (Bytes) (MHz) Reset

PIC15C554 512 80 20 - - - - 1 + WDT

PIC16C556 1024 80 20 - - - - 1 + WDT

PIC16C558 2048 128 20 - - - - 1 + WDT

PIC16C61 1024 36 20 - - - - 1 + WDT

PIC16C620 512 80 20 - 2 Yes - 1 + WDT

PIC16C621 1024 80 20 - 2 Yes - 1 + WDT

PIC16C622 2048 128 20 - 2 Yes - 1 + WDT

PIC16C71 1024 36 20 4 - - - 1 + WDT

PIC16C710 512 36 20 4 - Yes - 1 + WDT

PIC16C711 1024 68 20 4 - Yes - 1 + WDT

PIC16C715 2048 128 20 4 - Yes - 1 + WDT

PIC16CR83 512 36 10 - - - 64 1 + WDT

PIC16C84 1024 36 10 - - - 64 1 + WDT

PIC16F83 512 36 10 - - - 64 1 + WDT

PIC16F84 1024 68 10 - - - 64 1 + WDT

This chart compares the features of all current 18-pin mid-range PICmicro™ mcu’s.
Any of these PICmicro™ mcu’s can be used in the PIC-MDS.

The PICmicro Development System (PIC-MDS) has been developed for the mid-
range, 18-pin PICmicro™ devices. The PIC-MDS Professional comes with both the
PIC16C711 and PIC16F84. The PIC-MDS Hobbyist system includes only the
PIC16F84. The PIC16F84 can be programmed and erased while in the PIC-MDS.
The PIC16C711 requires an ultraviolet light source for erasure. We’ll examine the
features of these two chips in more detail in a moment. Bear in mind that any 18-pin
PIC highlighted in the chart above will work in the PIC-MDS.

The charts shown list only a small sampling of the large variety of PICmicro™
microcontrollers available. Visit the Microchip Technology, Inc. website (http://
www.microchip.com), or contact your local Microchip Distributor for the latest lit-
erature.

The 18-pin PIC16CXX


Product Line 24 ©1998 Sirius microSystems
The PIC16F84

The PIC uses Harvard


architecture which means
separate RAM and ROM
stacks. In the PIC they are
different widths.

represents a connection to the outside world.

Program EEPROM
The PIC16F84 has 1 k (1024) locations of EEPROM or Flash ROM, and can be
programmed and erased while in the PIC-MDS. Remember that ROM stores instruc-
tions for the microcontroller. Since each instruction takes one memory location, your
program can have no more than 1024 instructions. Each instruction is 14 bits long,
therefore each ROM location is 14 bits wide. ROM locations are addressed in hexa-
decimal and range from 0000h to 03FFh (0 to 1023 in decimal). Interrupts are a technique
by which the current
Two ROM locations are special. Location 0000h is called the Reset Vector. This program is temporarily
is where the PIC16F84 begins executing instructions immediately after a reset. Lo- placed on hold while the
cation 0004h is called the Interrupt Vector. The PIC16F84 begins executing instruc- processor performs another
tions from here immediately after an interrupt. set of instructions in
response to an event. See
Chapter 11 - Interrupts for
more information.
Data EEPROM
The PIC16F84 also has 64 bytes of 8-bit data storage EEPROM. This memory Data EEPROM is ideal for
is suited to storing values that need to be restored on power-up. Both the program storing user definable
and data EEPROM areas are electrically erasable. While the data EEPROM can be passwords or configuration
changed by the program executing in the microcontroller, the program EEPROM data.
can only be written to by the programmer or downloader.
Chapter 3 - The
©1998 Sirius microSystems 25 Microchip PIC family
of Microcontrollers
RAM
The PIC16F84 has 68 general purpose RAM locations. Each is 8-bits wide.
General purpose RAM locations begin at address 0Ch and extend to 4Fh. Microchip
calls RAM locations File Registers.

There are 16 other RAM locations known as hardware registers. Some are used
internally, while others extend to the outside world as I/O ports. Notice that file
register locations 00h through 0Bh have memory addresses on both page 0 and page
1. The RP0 bit in the Status register (03h) determines the active page—0 equals page
0, 1 equals page 1. Some page 0 registers are repeated in page 1 for programming
convenience. Though not implemented in the PIC16F84, the microcontroller is capa-
ble of accessing two more memory pages via the RP1 bit.

Input/Output Ports
The PIC16F84 has two input/output (I/O) ports. Each port pin can be programmed
to be either an input or an output. Some port pins have more than one function. All
port pins can source up to 20 mA of current and are able to sink up to 25 mA. The
PIC can easily drive LEDs, speakers and small relays without adding external driver
transistors. Not all pins can handle high current simultaneously (see the PIC data
sheets for details on the I/O ports).

The assembler also recog- Port A is a five bit wide digital port labelled RA.0 to RA.4. Pin RA.4 can be used
nizes the labels PORTA.0 - as an input to the real time clock counter/timer (TMR0 or RTCC) or can be used as
PORTA.4 and PORTB.0 - a digital I/O pin. TMR0 can also generate an interrupt.
PORTB.7 in addition to
RA.X and RB.X. See the
Port B is an 8-bit digital I/O port. All port B pins have an internal pull-up resis-
EPIC .INC files for a list of
all pre-defined labels for
tor that can be enabled when port B pins are set to be inputs. The internal pull-up
each particular processor. resistors eliminate the need for external resistors, saving parts and circuit board space.
Pin RB.0 (INT) can double as an interrupt source. Pins RB.4 through RB.7 can be
set to generate an interrupt on a change in input state. This feature is useful for
The PIC instruction set has waking up the PIC from sleep when a key is pressed.
a SLEEP command which
stops processing until an I/O ports A and B are file registers 05h and 06h. Two other registers, TRISA
interrupt occurs. While (05h on page 1) and TRISB (06h on page 1), contain the direction bits which control
asleep, a PIC uses very the flow of data through the ports. A ‘1’ bit in the TRISX register denotes that pin as
little current. an input, a ‘0’ bit denotes an output.

TMR0

TMR0 was once known as RAM register location 01h on page 0 contains TMR0, the counter/timer. It can
RTCC—the Real Time be fed from either pin 3 (RA.4), or from the internal clock. An 8 bit prescaler—
Clock Counter. which divides the incoming signal by a pre-programmed amount—can be applied to
the TMR0 input. Incoming clock signals can be divided by: 2, 4, 8, 16, 32, 64, 128
or 256 depending on the prescale value. The prescaler value is set in the OPTION
register (01h on page 1). The prescaler is shared with the watchdog timer (WDT),
and if used for WDT is unavailable for use by TMR0.

RAM and I/O


26 ©1998 Sirius microSystems
With TMR0 set to count external signals, it can count external events such as
bottles moving down an assembly line, the rotations of a tire, or the number of times
your desk drawer has been opened. With TMR0 counting internal clocks, you could
use TMR0 to measure the width of a pulse if you turn on TMR0 when a signal on a
pin goes high and turn it off when the signal transitions back to low. This technique
can be applied to measure pulse widths as small as 100 µs and frequencies up to 50
MHz.

Watchdog Timer (WDT)


The Watchdog Timer (WDT) is an independent free running oscillator completely While WDT is self con-
self-contained on the chip. Being independent of the main clock means that if the tained and requires no
main oscillator is halted by the SLEEP command, the PIC can be ‘awakened’ by the external parts, the main
continually running watchdog timer. clock oscillator requires
external components (see
The Watchdog timer has a nominal period of 18 ms (which is equivalent to a Oscillator, below).
frequency of 55 Hz) but can vary from 9 ms to 40 ms depending on temperature and
applied voltage. A prescaler, shared with TMR0, can be applied to the Watchdog
timer to change its period.

The Watchdog can used to force a reset after either a software fault—the proces-
sor may be stuck in an endless loop, or static discharge may have corrupted register
memory—or to wake the processor from a SLEEP command.

If not needed, WDT may be turned off via the configuration fuses. Configuration
fuses are set by the programmer or downloader during programming.

Power-Up Reset Timer (PWRT)


The power-up reset timer is used to provide a nominal 72 ms delay after power is
first applied. This allows the power supply 72 ms to stabilize before the reset signal
is issued to the micro-controller. It is controlled via the configuration fuses.

Oscillator
The clock oscillator circuit in the PIC16F84 is very flexible. Four oscillator
options are available: quartz crystal, ceramic resonator, resistor-capacitor combina-
tion (RC), or external clock input. The oscillator socket on the PIC-MDS allows you
to plug in quartz crystals or ceramic resonators.

Quartz crystal and external clock inputs allow the highest speed and the most Capacitors have wide
accurate timing. Ceramic resonators are cheaper but slightly less accurate than quartz tolerances and both resistor
crystals. RC combinations are cheapest but suffer from timing inaccuracies depend- and capacitor values
ent on temperature and the power supply voltage. The chosen oscillator option is set change with temperature.
via configuration fuses blown during programming.

Chapter 3 - The
©1998 Sirius microSystems 27 Microchip PIC family
of Microcontrollers
RAM Register Files
As mentioned earlier, RAM is divided into the hardware register file and general-
purpose storage locations. We have already seen how some of the register files have
been used (PORTA, PORTB, TRISA, TRISB, TMR0, and OPTION ). We’ll look at
some of the other important registers.

STATUS
The STATUS register (03h) holds arithmetic flags, page select bits and the mi-
crocontroller’s reset status. More detail on STATUS can be found in the PIC16F84
Data sheets.

PCL & PCLATH


PCL (02h) stands for Program Counter Low. It holds the lower 8 bits of the
program counter. Remember that the PIC16F84 can have as many as 1024 instruc-
tions in ROM (program) memory. Addressing 1024 locations requires 10 bits. The
upper two bits are stored in PCLATH (0Ah bits 0 and 1).

IND0 & FSR


IND0 (00h) is the first (and only) INDirect addressing register. It is used in
conjunction with FSR (04h), the File Select Register, to indirectly access data.

A reference to IND0 retrieves the contents of the address location stored in FSR.
This allows a programmer to increment FSR and access subsequent locations by
using the IND0 address as the target of the instruction. For example, if FSR contains
20h, addressing IND0 will access RAM location 20h. Indirect addressing is particu-
larly useful for look-up tables.

INTCON
The INTerrupt CONtrol register (0Bh) enables or disables interrupts and con-
tains most of the interrupt flag bits.

OPTION
The OPTION register (01h on page 1) controls prescaler divisors, TMR0 trigger
levels and signal source, as well as the Port B pull-up resistors.

EEDATA & EEADR


The PIC16F84 has 64 bytes of EEPROM data memory which can be changed
by the program, unlike the program EEPROM which can only be changed by the
programmer. EEDATA (08h) holds the data to be written to or read from the location
specified by EEADR (09h).

EECON1 & EECON2


EECON1 (08h on page 1) is the EEPROM data memory control register. EECON2
(09h on page 1) is used during EEPROM data writes.

RAM Register Files


28 ©1998 Sirius microSystems
The PIC16C711

Many of the parts of the PIC16C711 are identical to the PIC16F84. The differ-
ences reflect the addition of a four-channel A/D converter and the use of EPROM
program memory rather than EEPROM. The PIC16C711 has no EEPROM data
memory.

Program EPROM
The PIC16C711 EPROM memory is identical in size to that of the PIC16F84
(1k words). Unlike the PIC16F84, the PIC16C711’s EPROM memory is erased by Erasing a PIC16C711 takes
exposure to ultraviolet light. Be sure to cover the window after programming so that 5-10 minutes of exposure
ambient light won’t affect the operation of the PIC. under ultraviolet light.

The Reset and Interrupt Vectors are in the same locations as the PIC16F84.

Analog-to-Digital Converter
The PIC 16C711 is one of the few members of the PICmicro™ family with a
built-in 8-bit analog-to-digital converter (A/D). In many cases it is cheaper to use a
PIC16C711 than to use a PIC with an external A/D. The A/D converter can translate
an analog voltage into a binary number.

Port A of the PIC16C711 can be configured to read two, three or four analog
inputs. Conversions require a minimum of 20 µs. The A/D clock can be fed by its
Chapter 3 - The
©1998 Sirius microSystems 29 Microchip PIC family
of Microcontrollers
own RC oscillator or from the master clock through an internal clock divider under
control of the ADCON0 (08h) file register. Using the RC oscillator allows conver-
sions to take place while the micro-controller is asleep, which provides the best con-
version accuracy.

The A/D is controlled


through two RAM regis-
ters, ADCON0 (08h) and
ADCON1 (08h on page 1),
and the result is placed in
the A/D result file register
ADRES (09h).

The A/D is particu-


larly useful when measur-
ing the voltage from a
strain gauge, liquid level
sensor, temperature sensor,
light sensor, or perhaps
even for measuring brain- While trying out the new PIC-Your-BrainTM brain wave
wave activity. analyser, Bob realizes that he should never have removed
the ground prong from his oscilloscope’s power cord.

Chapter Summary
The PIC16F84 and PIC16C711 are identical except:
• the memory on the PIC16F84 is electrically erased, the PIC16C711 requires
exposure to ultraviolet light
• the PIC16F84 has an additional 64 bytes of EEPROM data space
• the PIC16C711 has a 4-channel A/D converter
• the maximum clock speed of the PIC16F84 is 10 MHz, the PIC16C711 has a
20 MHz maximum clock speed

It’s easiest to develop programs on the PIC16F84 becasue the EEPROM memory
allows quick erasing and reprogramming. The PIC16F84 can also be programmed
in-circuit, without removing it from the PIC-MDS and plugging it into the program-
mer. All necessary programming signals are supplied to the PIC through the In-
Circuit programming cable.

If your program requires high speed operation, or A/D conversion, then the
PIC16C711 must be used.

A/D Converter
30 ©1998 Sirius microSystems
Questions
1. What is the maximum size of program you could place inside a PIC16F84 or
PIC16C711?

2. What is the location of the instruction that will be executed immediately after
a reset?

3. What is the maximum number of variables that could be stored in RAM?

4. What is the purpose of a watchdog timer? Why is the watchdog given its own
oscillator?

5. What is the advantage of EEPROM program memory?

6. Explain how an application might use EEPROM data memory.

7. Why is program memory wider than data memory?

8. Air bag sensors respond to rapid decelerations that occur within 30 ms. Can a
PIC16C711 measure at least 20 analog samples within a 30 ms window to
determine whether or not to inflate the bag?

Assignment
1. You’ve developed a touch-tone dialer program using the PIC-MDS and a
PIC16F84. The program is 487 bytes long. What other PICs could be used
instead of the PIC16F84? Check supplier catalogs to find the least expensive
PIC.

2. You have 6 relays to connect to PIC16F84. Each relay coil requires 20 mA to


activate. Examine the data sheets and determine how many relay coils can be
active simultaneously on Port B. How many of these relays could be connected
to Port A?

Chapter 3 - The
©1998 Sirius microSystems 31 Microchip PIC family
of Microcontrollers
Notes
32 ©1998 Sirius microSystems
Features of the PIC-MDS
4 Development System

The PIC-MDS contains everything you need to develop your own mid-range
PICmicro™ microcontroller applications. The advantage of the PIC-MDS is that
was designed with typical microcontroller input/output (I/O) circuitry already pre-
wired to the microcontroller, so that users can spend their time concentrating on code
development and not on hardware debugging. This chapter explains the operation of
each of the devices on the PIC-MDS board. Refer to the schematic on the next page
to examine the circuitry for each item.

2-Line 16-Character LCD Display


with 80 character memory and Buffered LED RS-232 Serial
programmable characters display shows driver/receiver
2.1mm Power Jack
power and port
12 VAC or 18 VDC
status
(500mA) input
RS-232 input/
output header
Screw terminal strip
allows access to all RS-232 transmit/
port signals and receive select jumper
power supplies.
LCD contrast adjust
potentiometer
Variable DC adjust
potentiometer
Serial EEPROM Crystal or ceramic
resonator socket
Fixed 5V regulator
PICBUS expansion
header

Processor ZIF socket

5VDC internal/ 16 key matrix EPIC in-circuit


external select keypad with programming
Hardware
jumper customizable header
reset button
key legends
Variable DC Two variable
internal/external Variable DC analog input
select jumper regulator potentiometers

Chapter 4 - Features
©1998 Sirius microSystems 33 of the PIC-MDS
Development System
34 ©1998 Sirius microSystems
Power Supply Circuit
The power supply of the PIC-MDS is capable of supplying both the microcon-
troller and external circuitry with a range of voltages. Two independent regulators
provide a fixed +5VDC output as well as a variable DC output. The variable DC
output can be connected to the 5V microcontroller power supply to run the microcon-
troller at a lower voltage than 5V using a user-supplied jumper. Each power supply
voltage is present at the PICBUS expansion connector (H1) for external circuitry.

Electrical current is supplied to the PIC-MDS through the 2.1mm co-axial power
jack (J1) or from pins 1 and 3 of the screw terminal strip (CON1-1 & CON1-3). Pin
3 of the screw terminal strip (CON1-3) is the ground connection. Pin 2 of the screw
terminal strip (CON1-2) in conjunction with the ground (CON1-3) allows an exter- If you add high current
external circuitry to the
nal power supply to provide the regulated +5VDC for the microcontroller.
PICBUS or CON1, power
the PIC-MDS from an
The PIC-MDS power supply accepts either AC or DC input. The on-board power external power supply
supply will produce the necessary DC voltages for the PIC-MDS. The PIC-MDS is attached to screw termi-
designed to work with either of the following AC adapters: nals 2 and 3 on CON1. The
PIC-MDS AC power supply
Input Voltage Output Voltage Output Current can supply only 300 mA to
the PIC-MDS and external
120 VAC 9-12 VAC 300 mA circuitry.
120 VAC 12-18 VDC 300 mA

Note that using AC adapters with higher output voltages will increase the power
dissipation of the regulators and will cause them to get quite hot during operation.

J1
J1 is a 2.1mm co-axial power jack This jack supplies current from an AC or DC
wall adapter to the bridge rectifier (D1) and the regulator circuitry (C1-6, U1, U2, The screw terminal strip
etc.). J1 also contains a normally closed switch connected to the 16-pin screw termi- pins are numbered from the
nal strip (CON1-1). When no wall adapter is plugged into J1, current from pin 1 of top of the PIC-MDS.
the screw terminal strip (CON1-1) flows through J1 to the rectifier. Therefore, pin 1 or CON1-1
is closest to J1, and pin 16
or CON1-16 is closest to
VR1
C5.
Potentiometer VR1 is used to adjust the variable DC power supply. The range of
the variable DC power supply is from 1.3V to approximately 3V less than the volt-
age into J1.

JU1
Default position: REG

3-pin shorting jumper, JU1, selects the voltage source for any circuits connected
to the variable DC power supply. In the REG position, the variable DC voltage is
derived from the variable DC regulator (U1). In the CON1 position, the variable DC
voltage is taken from pin 2 of the screw terminal strip (CON1-2).

Chapter 4 - Features
©1998 Sirius microSystems 35 of the PIC-MDS
Development System
JU2
Default position: REG

The 3-pin shorting jumper, JU2, selects the fixed +5VDC voltage source. In the
REG position, the fixed +5VDC voltage is derived from the 5V regulator (U2). In the
CON1 position, the fixed +5VDC voltage is taken from pin 2 of the screw terminal
Warning: Do not exceed strip (CON1-2).
+6VDC on CON1-2 when
JU2 is set to CON1 input When the fixed +5VDC voltage source is present, the LED at the top of the LED
or you will destroy your bar graph (LED1-PWR) lights.
PIC microcontroller.

External I/O Connectors


The PIC-MDS has two external I/O expansion connectors. The 16-pin screw
terminal strip (CON1) allows for quick and easy connections from external circuit
components to the PIC I/O ports. The PICBUS expansion header (H1) allows exter-
nal circuits to be connected more permanently to the PIC microcontroller. The PICBUS
includes both power supplies as well as the PIC reset line (MCLR) and is geared to
adding microcontroller peripherals to the PIC-MDS.

CON1
CON1 is the 16-pin screw terminal strip at the extreme left of the PIC-MDS.
Three power supply connections and 13 microcontroller I/O pins are brought out to
the screw terminals for ease of connection to external devices. The pinout of CON1
is shown below:

Note that the input to


CON1-2 is affected by both +9V to +18VDC input — CON1-1
the JU1 and JU2 settings. +5VDC or variable DC — CON1-2
CON1-2 can provide
Ground — CON1-3
either the external +5VDC
supply or the external RA0/AIN0 — CON1-4
variable DC supply—but RA1/AIN1 — CON1-5
not both at once! RA2/AIN2 — CON1-6
RA3/AIN3/VREF — CON1-7
RA4/RTCC — CON1-8
RB0/INT — CON1-9
RB1 — CON1-10
RB2 — CON1-11
RB3 — CON1-12
RB4 — CON1-13
RB5 — CON1-14
RB6 — CON1-15
RB7 — CON1-16

External I/O
Connectors 36 ©1998 Sirius microSystems
PICBUS
The PICBUS connector on the PIC-MDS is compatible with the PICBUS con-
nectors on the PIC-PROTO boards from microEngineering Labs. It is a 26-pin header
connector socket at the right side of the PIC-MDS. The pinout of H1 is shown below:

Note that the PIC-MDS


does not come with a
connector for the
PICBUS header. A
number of different
RA4/RTCC — H1-1 H1-2 — MCLR/VPP styles of header plugs
RA0/AIN0 — H1-3 H1-4 — +5VDC/VDD and sockets will fit into
RA1/AIN1 — H1-5 H1-6 — Variable DC the PICBUS connector.
RA2/AIN2 — H1-7 H1-8 — Ground
RA3/AIN3/VREF — H1-9 H1-10 — Ground
RB0/INT — H1-11 H1-12 — RC7
RB1 — H1-13 H1-14 — RC6
RB2 — H1-15 H1-16 — RC5
RB3 — H1-17 H1-18 — RC4 Connected to opposite
RB4 — H1-19 H1-20 — RC3 RBx pin on PIC-MDS
RB5 — H1-21 H1-22 — RC2
RB6 — H1-23 H1-24 — RC1
RB7 — H1-25 H1-26 — RC0

Microcontroller Related Circuits


The PIC microcontroller is essentially connected to all of the circuitry on the
PIC-MDS board. The following parts of the PIC-MDS relate most directly to the
PIC microcontroller.

Microcontroller Socket
The PIC microcontroller socket (U3) is either an
18-pin zero-insertion-force (ZIF) socket (in the case of Attention Hobbyist users:
the PIC-MDS Professional), or an 18-pin DIP socket you will find that a ZIF
(PIC-MDS Hobbyist). Pin 1 is the pin closest to the U3 socket for U3 reduces the
likelihood of broken IC
label on the PIC-MDS board.
leads when removing and
inserting PICs.
H2
The EPIC In-Circuit programming header (H2) al-
lows the EPIC programmer from microEngineering Labs
to plug directly into the PIC-MDS to speed the pro-
gram/test/erase process and to save wear and tear on
the microcontroller and socket (U3). By connecting the
Chapter 4 - Features
©1998 Sirius microSystems 37 of the PIC-MDS
Development System
The PIC16C711 can also EPIC programmer to the
be programmed through the PIC-MDS, a PIC16F84
In-Circuit programming can be programmed and
header, but requires UV erased without removing it
light for erasure.
from the microcontroller
socket on the PIC-MDS
board. Simply connect H2
to the programming header
on the EPIC programmer
(J3) with the supplied 10-
pin ribbon cable.

Pin 1 of H2 is at the
lower left of the header and
is denoted by a triangular
arrow on the outside of the
header shroud. Pin 1 of the
programming header (J3)
on the EPIC programmer
is also at the lower left (far- The PIC-MDS connected to the EPIC programmer
thest away from the 25-pin through the 10-pin programming cable. Be sure to
parallel connector). Be connect the cable in the proper orientation.
sure to connect the 10-pin
If you purchased the PIC-MDS with the EPIC program-
programming ribbon cable mer, refer to the Quick Start sheet for information on how
in the proper orientation. to get up and running fast!

It is sometimes necessary Reset Button


to press and hold the Reset
button while starting the The Reset button (S1) pulls the PIC MCLR line low when pressed, causing a
EPIC software. This is hardware reset. During a hardware reset, the PIC microcontroller stops executing the
because the EPIC pro- current program and changes all I/O ports to inputs. When the Reset button is re-
grammer programs the PIC leased, the microcontroller begins executing its program from the beginning of memory,
using RB.6 and RB.7. The effectively restarting the program.
EPIC software expects
these two pins to be inputs. Y1
If your program uses RB6
and RB7 as outputs, the Y1 is the crystal oscillator/ceramic resonator socket. Crystal oscillators and two-
EPIC software can’t pin ceramic resonators plug into the two outer socket pins (Y1-1 and Y1-3 on the
interrogate the PIC. By schematic). Y1-2 is a ground pin and is used for 3-pin ceramic resonators.
holding the Reset button,
these two pins float, The PIC-MDS is supplied with a 10 MHz crystal. The values of the external
essentially becoming
oscillator components C7, C8 and R5 have been chosen to operate the PIC-MDS
inputs.
properly at frequencies from 4 to 20 MHz. To operate the PIC-MDS at a clock
frequency other than 10 MHz, or to use a ceramic resonator instead of a crystal
oscillator, simply install the crystal or resonator in Y1.

JU3
Default position: RUN

Three-pin shorting jumper JU3 changes the source


of the +5VDC power supply for the microcontroller only.
In the RUN setting, the PIC-MDS fixed +5VDC supply
Microcontroller
Related Circuits 38 ©1998 Sirius microSystems
powers the PIC microcontroller (as well as all other circuitry on the PIC-MDS). In
the PROG setting, the microcontroller is powered by the EPIC programmer (all other
PIC-MDS circuitry is still powered by the fixed +5VDC supply).

This jumper allows you to take advantage of the ZIF socket on the PIC-MDS as
an add-on to the EPIC programmer. When set to PROG, the EPIC programmer
powers only the microcontroller, not the rest of the PIC-MDS. Since the EPIC pro-
grammer was not made to power external circuitry, setting JU3 to PROG prolongs
the battery life of the EPIC.

JU6
Select only one of RA2,
Default positions: RA0 - Open RA3 or RA4 at a time.
RA1 - Open Otherwise you will short
RA2 - Shorted two or more PIC outputs
RA3 - Open together, potentially
RA4 - Open damaging the PIC through
excessive output current.
The 10-pin jumper block JU6 has two purposes. The RA0 and RA1 positions
connect the analog input potentiometers (VR3 and VR4) to the PIC RA.0 and RA.1
inputs, respectively. When not using the analog input capability of the PIC16C711,
leave RA0 and RA1 open to eliminate interference from the analog voltage levels set
by VR3 and VR4.

The RA2, RA3 and RA4 positions of JU6 select which of the microcontroller
Port A lines is connected to the LED labelled JU6 on the LED bar (LED1). By
default, the JU6 LED monitors the LCD enable line on RA2. Moving the shorting RA2 is also the LCD
jumper from RA2 to RA3 or RA4 allows you to monitor those pins using the LED. enable line. Removing the
jumper from RA2 lets the
VR3 & VR4 enable line float and may
cause unreliable operation.
VR3 and VR4 are analog input potentiometers meant
to simulate analog sensors when using the PIC16C711’s
built-in A/D converter. Disable VR3 and VR4 when not
using the analog input capability of the PIC16C711, or
when using the PIC16F84. To disable VR3 and VR4
simply remove the jumpers from JU6-RA0 and JU6-
RA1.

Matrix Keypad
KB1 is a 4X4 matrix keypad connected to Port B of the PIC microcontroller. All
switches are normally open and will not interfere with the operation of any programs
that do not use the keypad. Resistors R6-R9 provide short-circuit protection in case
two Port B pins are set to output and become shorted by a pressed keypad switch.

The key caps can easily be removed by gently lifting the left or right side of the
clear plastic cover. This makes it easy for you to add your own custom key legends.

Chapter 4 - Features
©1998 Sirius microSystems 39 of the PIC-MDS
Development System
The LEDs will display the LED Output Indicator Bar Graph
state of the PIC I/O ports
regardless of whether they
are outputs or inputs. By
LED1, a 10-seg-
ment LED (Light Emit- — indicates +5VDC is present
connecting external
ting Display) bar graph, — displays state of RA2, 3 or 4
circuits to the PIC inputs
is used to indicate that — displays state of RB0
you can use the LEDs as
logic probes to monitor the fixed +5VDC power — displays state of RB1
your inputs. supply is operating as — displays state of RB2
well as to monitor the — displays state of RB3
status of the microcon- — displays state of RB4
— displays state of RB5
troller I/O lines. The
— displays state of RB6
LEDs are connected as
— displays state of RB7
shown.

Intelligent LCD Display

Disable the LCD by making The LCD display (LCD1) is a 2-line by 16-character intelligent display with an
RA2 (LCD Enable) an 80 character memory. A built-in microcontroller gives the LCD display intelligence
output and setting it low. At by allowing it to control the cursor, address specific character positions, shift the
power-up all PIC I/O ports display contents left or right and program custom characters.
are set as inputs. An
undefined input on RA2 The LCD display uses RA0, RA1 and RA2 as its Register Select, Read/Write
can activate the LCD and and Enable control signals, along with RB0-7 for character or command data. When
adversely affect your disabled, the LCD display will not interfere with other circuitry connected to Port B,
program.
RA0 or RA1.

VR2
Potentiometer VR2 is the LCD contrast control. Rotate this potentiometer until
the LCD displays the most readable image.

RS-232 Serial Port

Note that you cannot use U6 is an RS-232 serial line driver/receiver and translates the PIC microcontrol-
U6 to transmit and receive ler’s +5V logic to bipolar RS-232 levels. It connects to pin RA4 of the PIC to allow
serial data at the same time transmission or reception of standard RS-232 data. Note that many new computers
because only one PIC I/O will accept +5V (TTL) logic levels allowing you to use any PIC I/O pin for serial
line (RA4) is connected to data transmission (over limited distances). U6 guarantees the correct voltage and
it. drive capability as specified by the RS-232 standard.

JU5
Default position: open

Transmit/receive select jumper, JU5, is a 3-pin shorting jumper used to select


whether RA4 is connected as a serial input or output. Removing the shorting jumper
plug, or connecting it to only one pin of JU5, disables the serial port. Putting the
jumper in the Rx position couples incoming RS-232 data to RA4. Putting the jumper
in the Tx position allows RA4 to output RS-232 data.
LED, LCD Display,
Serial Port 40 ©1998 Sirius microSystems
H3
H3 is the RS-232 serial cable connection header. A user-supplied 3-pin plug can
connect this header to external RS-232 serial devices. Refer to the schematic dia-
gram at the beginning of this chapter for the pinout of H3.

Serial EEPROM Remember that the


PIC16F84 also has an on-
Applications that require long-term data or variable storage can store informa- board 64 byte EEPROM.
tion in the serial EEPROM. Its 256 bytes of memory are non-volatile, and can be
programmed by the PIC microcontroller. The serial EEPROM is controlled by the
Like the LCD, disable the
signals on RA0, RA1 and RA3. The serial EEPROM is similar to the LCD display in
EEPROM by making RA3
that it uses Port A wires for its control signals—the Chip Select, Clock, Data In and an output and setting it
Data Out lines. low.

JU4
Default position: X8

3-pin jumper JU4 sets the data memory organization of the serial EEPROM. In
the X8 setting, the serial EEPROM accesses memory in 8-bit bytes. When the jumper
is closest to the JU4 label, the serial EEPROM accesses memory in 16-bit words.

PIC-MDS Default Jumper Locations

The full-size parts layout drawing, above, shows the default locations of all jumpers for most of the program
examples. Each program lists the required jumper locations.

Chapter 4 - Features
©1998 Sirius microSystems 41 of the PIC-MDS
Development System
Questions

1. Which pins of the screw terminal strip would be used to connect a 15VDC lab
power supply?

2. What connections and jumper settings of JU1 and JU2 should be used for the
following:

a) a 9V battery powering the PIC-MDS board and a 12V battery providing


adjustable power to circuits on the PICBUS

b) a 12V car lighter adapter powering only the PIC-MDS board

c) a 5V regulated lab power supply powering the PIC-MDS and a variable lab
power supply powering PICBUS circuits

d) two D cells supplying power to a low-power PIC microcontroller

e) a 6V battery supplying 3V to a low-power PIC microcontroller through the


on-board variable DC power supply

3. Can you put shorting jumpers on both JU6-RA3 and JU6-RA4 at the same
time? Why or why not?

The default jumper settings


on the previous page work
for mostof the programs in
this text when using the
supplied AC adapter.

Hmm...Was that JU1 to JU3 for 5V operation, except with batteries and when bypassing
the regulator attached to CON1-3, or was it...?

Questions
42 ©1998 Sirius microSystems
Writing a Simple
5 Program

Recall from Chapter 2 that the first step in programming a microcontroller is If you have not yet in-
writing the program source code, after which the source code is converted to object stalled the PIC-MDS
code by an assembler program. The PM assembler supplied with the PIC-MDS pro- software do so now. See the
gramming packages supports two dialects of PIC instructions. Quick Start! sheet for
instructions.
One dialect is the official Microchip instruction set and syntax, the other is com-
patible with the Parallax’s 8051-like instruction set. Each has its advantages and Parallax, Inc. is a supplier
disadvantages. of PIC development tools.

If you are familiar with the Microchip instruction set, or have programmed
Motorola family microcontrollers, you may find it easier to use the Microchip com-
mand syntax and examples. If you have programmed Intel family microcontrollers or
microprocessors (or want to), you may find it easier to use the Parallax command
syntax and examples. If you are new to the PIC microcontrollers, we suggest that
you read both until you find one that you are more comfortable with.

Microchip Instruction Syntax Parallax 8051-like Syntax

similar to Motorola format similar to Intel format

few instructions to learn more instructions to choose from

many example programs not as widespread

instructions reflect one instruction may execute one


microcontroller actions or more Microchip instructions

The PIC-MDS system, including this manual and all example programs, pro- The Microchip Code
vides source code and descriptions in both instruction sets. Chapters using the Mi- sections are printed on
crochip instruction set and syntax are identified by the Microchip Code footer at the white paper, and the
bottom of the page. Likewise, chapters using the Parallax instruction set and syntax Parallax Code sections are
are identified by the Parallax Code footer at the bottom of the page. printed on blue paper.
Chapter 5
©1998 Sirius microSystems Microchip Code 43 Writing a Simple
Program
Here is the same pro-
Main BTFSC PORTA.4 ;Check Port A bit 4 for a low
gram routine written in GOTO Main ;If we’re here, bit 4 is high
both Microchip (top) and INCF PORTB ;If bit 4 is low, increment Port B
Parallax-compatible
Wait_for_High BTFSS PORTA.4 ;Check Port A bit 4 for a high
(bottom) source code.
GOTO Wait_for_High ;If we’re here, bit 4 is still low
Notice that the program GOTO Main ;Bit 4 went high, wait for next bounce
written in Microchip
code requires more Microchip assembly source code example.
instructions to be
entered in order to do
Main JB PORTA.4,Main ;Loop while Port A bit 4 is high
the same thing as the INC PortB ;If we’re here, bit 4 is low so
Parallax code. However, ;increment Port B to count the
both programs assemble ;transition and,
to six machine instruc-
Wait JNB PORTA.4,Wait ;Loop until Port A bit 4 goes high
tions, meaning that the JMP Main ;Bit 4 went high, wait for next bounce
Parallax code hides
some of the microcon- Parallax-compatible assembly source code example.
troller operations.

Examining Source Code—Microchip Code

EDIT is available from The example programs have been written using the DOS text editor EDIT. You
within an MS-DOS session can, of course, use any text editor, but our instructions describe EDIT. Let’s look at
in Windows-95. If you use the source code for a simple program that displays a binary number on the LEDs.
an editor or word processor
other than EDIT to write From the MS-DOS prompt, change to the EPIC directory using the command:
source code files, make
sure that you save them in cd \picmds [enter]
DOS Text or ASCII format.
Open the OUTPUT.ASM file for editing by typing:

edit output.asm [enter]

Your screen should look like this. Use the cursor keys or mouse to move the
cursor through the text as we examine the program.

If you have not used EDIT


before, you may want to
take a quick look at the
Help menu at the top-right
hand side of the screen.

Examining Source
Code 44 Microchip Code ©1998 Sirius microSystems
Source Code Conventions
Notice the way that text is organized in columns. Any text beginning in the very
first column is considered a Label, and is a part of the Label Field. The next three
columns contain the Instruction Field, Data Field and Comment Field. Comments
may also begin in the first column if they are prefixed with a semicolon (;).

Labels are names given to subroutines or sections of source code. By giving Initialize, Main and Done
parts of a program names, other program instructions can jump to or reference the are the three labels used in
named parts. Most assemblers place some sort of limit on the length of labels, as well OUTPUT.ASM.
as the characters that can be used to define labels. PM has a limit of 32 characters.

The PM assembler supplied with the PIC-MDS packages also allows the use of
local labels. Local labels are prefixed with a colon (:) and remain as a label specific Local labels are explained
in more detail in Chapter
to the previous non-local label. For example, you could have two different subrou-
10 - Calls and Includes.
tines labelled :Loop, one within a subroutine labelled Countdown and another within
a subroutine labelled Countup. The assembler knows that a call to :Loop from within
Countdown should reference only that :Loop, and not the :Loop in Countup.

;Description

; This program demonstrates port output. It initializes all port B pins


; to be outputs and then places a pattern on port B to illuminate LEDs.

;Jumper Settings

; JU2 5VDC internal/external select REG Assemblers usually only


; JU1 Variable DC internal/external select REG require a single space or
; JU3 Processor power select jumper RUN punctuation symbol to
; JU4 EEPROM X8/X16 organization select N/A separate columns. Using
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF nicely spaced columns
; RA2 ON makes it far easier for
; RA3 OFF you to read your source
; RA4 OFF code. Set Tab stops
; JU5 RS-232 receive/transmit select N/A
where you would like
;Requirements your columns to begin.

; This is a simple program that requires no prior setup.

Maclib ‘Pf8x.INC’ ;Library file for PIC16C84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘OUTP’

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector

ORG 05h ;One location past Interrupt vector

Initialize BSF RP0 ;Select memory register page 1


CLRF TRISB ;Make Port B output by clearing TRISB
BCF RP0 ;Go back to register page 0

Main MOVLW 01010101b ;Move 01010101b into W and


MOVWF PORTB ;output pattern to LEDs on Port

Done SLEEP ;Stop executing the program

Label Instruction Data Comment


Field Field Field Field
Chapter 5
©1998 Sirius microSystems Microchip Code 45 Writing a Simple
Program
The second column is the Instruction Field. Instructions can be either microcon-
troller instructions or instructions for the assembler, called assembler directives. The
Appendix D shows the instruction set of the PIC microcontroller is described in the PIC16F8x data sheets.
Parallax instruction set Remember that the PM assembler supports two instruction sets, Microchip and Par-
mnemonics. allax. The term directive is used for assembler commands so that they are not con-
fused with microcontroller instructions (See Appendix C for more details).

The column following the Instruction Field is the Data Field. Data fields contain
data used by the instructions. In the case of the PIC microcontrollers, data can be a
file register, a bit within a file register, a label, or a number—called a ‘Literal’ by
Microchip. Some instructions have no data. If an instruction needs multiple pieces of
data, they are separated by a comma.

Now may be a good time to The base unit of number is optionally specified by the suffixes b and h—binary
brush up on binary and and hexadecimal. A number with no suffix is considered to be a decimal number.
hexadecimal. Any good Therefore, the data 12, 00001100b and 0Ch are all the same. Note that if the first
digital textbook will digit of a hexadecimal number is not numeric, it must be prefixed with a 0, even if it
explain number systems. makes a three-digit number. For example, 0FDh is acceptable, but FDh generates an
error because it is interpreted as a label by the assembler.

The last field is the Comment Field. Comments always have a semicolon as their
first character and can be placed anywhere in the program. Comments are one of the
most important code conventions you should develop. Well written comments de-
scribe the operation of your code, or the operation and requirements of subroutines.
Without comments, it can be very difficult to decipher the source code that you cre-
ated just a few days ago.

Some Other Common Source Code Conventions


Some conventions are used to make a programmer’s life easier. You’ll adopt
your own favourite conventions as you become more proficient. In general, conven-
tions are any action that make it easier to review and understand any program, espe-
cially the one that you wrote a few months ago! Here are some of the conventions
used in this manual:

• file naming - *.ASM for source files, *.LST for list files, *.HEX for object files
• name, revision level and revision date as the first line of a program
• tabs - every 4 or 8 spaces
• instructions in upper case - the code is more visible
• comments explaining every line of code
• a comment paragraph explaining routines - comment fields are very small
• “_” as space character - max_int_power is easier to read than maxintpower

Remember, conventions are anything that you find makes the code easier to read.

Source Code
Conventions 46 Microchip Code ©1998 Sirius microSystems
Examining the Program
The Maclib Directive

Maclib ‘P84.INC’ ;Library file for PIC16C84 and PM assembler


;Comment this line out for other assemblers

After the disclaimer and description comments, the first part of the program is Maclib is unique to the PM
the Maclib directive. Maclib is short for Macro Library. A macro library contains assembler shipped with the
labels corresponding to the hardware locations of a particular microcontroller. In this EPIC programmer and
case, the Maclib directive includes references for the PIC16C84 and PIC16F84 allows easy upgrades to
new microcontrollers—just
microcontrollers. When you write a program for a different microcontroller, you will
reference a new .INC file.
need to include the proper file in the Maclib directive.
P84.INC works with the
PIC16C84 and PIC16F84,
The Device and ID Directives but the newer PF8X.INC
works with the PIC16F83
Device PIC16C84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
as well.
ID ‘OUTP’

The next line of the program is the Device Directive. The Device directive sets a
number of parameters for the microcontroller. The first item in the Device directive
tells the assembler to create a program for the PIC16C84 microcontroller. You could
change this to PIC16C711—the other type of microcontroller supplied with the PIC-
MDS—or to any other mid-range PIC microcontroller you wanted to program (see
Chapter 3).

The data following the microcontroller type sets the configuration fuses in the See Chapter 3 for other
microcontroller. In this case the directive sets high speed oscillator operation options set by the configu-
(HS_OSC), watch-dog timer off (WDT_OFF), code-protect off (PROTECT_OFF), ration fuses. Code-protect
and power-up reset timer on (PWRT_ON). prevents a standard
downloader/programmer
from reading your pro-
The ID directive sets the four identification bytes. These could be anything from
gram. This provides a
a name or serial number to the number of Sundays until Christmas. Note that the ID degree of protection from
bytes are not protected by code-protect. copying. There are people
who claim to be able to
A common use of the ID bytes is to hold the name or name and revision level of read any code-protected
a program. The ID bytes of a microcontroller can be read by a programmer, letting microcontroller.
you know at a glance what the chip is programmed to do.

The ORG Directive

ORG 00h ;Reset Vector location

The ORG directive tells the assembler where in ROM memory to begin placing The ORG directive can also
instructions. It is the ORiGin for all subsequent code. We place the origin at location specify the origin of the
00h because the mid-range PIC-micro™ family always executes the instruction at RAM register memory.
location 00h after a power-up or reset. Location 00h is called the Reset Vector.

Chapter 5
©1998 Sirius microSystems Microchip Code 47 Writing a Simple
Program
Location 04h is the Interrupt Vector. The microcontroller will execute the in-
Program ROM struction here if an interrupt is generated. It’s good practice to leave location 04h free
0000 GOTO 05 so that you can add interrupt capability to your programs at a later date. This pro-
0001 gram jumps past the Interrupt Vector and begins at location 05h.
0002
0003 ORG 00h ;Reset Vector location
0004 GOTO Initialize ;Start program after Interrupt vector
0005 BSF RP0
ORG 05h ;One location past Interrupt vector
0006 CLRF TRISB
0007 BCF RP0 Initialize BSF RP0 ;Select memory register page 1
0008 MOVLW 0101.. CLRF TRISB ;Make Port B output by clearing TRISB
BCF RP0 ;Go back to register page 0
0009 MOVWF PortB
000A SLEEP
000B The GOTO Initialize instruction has been stored in location 00h because it is the
000C next instruction following the ORG 00h directive. Therefore, the first instruction
executed by the microcontroller at power-up or after a reset is not ORG 00h, but
GOTO Initialize. Remember, ORG 00h is an assembler directive, not a microcon-
troller instruction.
03FE
03FF The assembler would normally place the next instruction after GOTO Initialize
in location 01h, the next available memory location. The microcontroller, however,
This memory map shows has jumped to a location pointed to by the label Initialize. Since ORG 05h precedes
where instructions would the Initialize label, the memory location 05h contains the BSF RP0 instruction, and
load into program ROM is the location of the next instruction to be executed.

Program Code

Initialize BSF RP0 ;Select memory register page 1

CLRF TRISB ;Make PortB output by clearing TRISB


BCF RP0 ;Go back to register page 0

The three instructions following the Initialize label set Port B of the microcon-
troller as output.

The P84.INC file knows First, BSF RP0 (Bit Set in File Register, Register Page Select Bit 0 in the Status
that RP0 is the fifth bit of Register) sets RAM register page 1 as the active page (refer to the PIC16F84 block
the Status register and diagram on page 17). Then, CLRF TRISB (Clear File Register, in what Microchip
automatically substitutes calls the Port B Tristate Register) clears the Port B data direction register, making
this location for any Port B an output port. A zero bit in a data direction register makes that port bit an
reference to RP0. P84.INC
output. Similarly, a one bit in a data direction register makes that port bit an input
also substitutes a file
register location for the (0=Output, 1=Input). Finally, BCF RP0 (Bit Clear in File Register, Register Page
data TRISB. Select Bit 0) sets the RAM register page 0 as the active page.

Main MOVLW 01010101b ;Move 01010101b into W and


MOVWF PORTB ;output pattern to LEDs on Port

Once again, the P84.INC


file knows the file register Main is a label that is commonly assigned to the first line of program code. The
location of Port B and lines following the Main label move a constant into Port B which light the LEDs in
substitutes this into the an alternating on-off pattern.
program during assembly.

Examining the
Program 48 Microchip Code ©1998 Sirius microSystems
MOVLW 01010101b (Move Literal into Working Register) moves the binary
number 01010101 into the Working Register. The PM assembler also accepts hexa-
decimal and decimal numbers. The equivalent commands would be MOVLW 55h
or MOVLW 85. Remember that a hex number beginning with A through F must
have a preceding zero in order not to be interpreted as a label by the assembler.

MOVWF PORTB (Move Working Register to File Register, Port B) copies the 01010101 W Port B
number in the Working Register to the Port B File Register. The Port B file register
is connected to the LEDs (refer to the schematic on page 26).

Done SLEEP ;Stop executing the program

Since our program is now finished, we tell the microcontroller to stop executing
instructions. Notice that the SLEEP instruction requires no data. The SLEEP com-
mand maintains all active outputs but stops program execution by stopping the
microcontroller clock. Power requirements during sleep mode are minimal.

Ending the Editing Process


To exit the EDIT program, select Exit from the File menu.

If you inadvertently made any changes to the program, EDIT will ask you if the
changes should be saved. Select No to keep the original program intact.

The next step in the programming process is assembling the source code file to
produce an object code file. After the object code file is created, it can be downloaded
to the microcontroller. Chapter 6 will lead you through program assembly, and
Chapter 7 shows you how to download your program to the microcontroller.

Chapter Summary
Source code is a text file that contains microcontroller instructions and assem-
bler directives. Recall from Chapter 2 that source code is the code from which the
list file and object code are derived.

Directives are assembler instructions which set device parameters and memory
locations. Directives are not stored in memory, but are used by the assembler and
programmer. Instructions and their data make up the program that will eventually
be stored in memory, and define what the microcontroller will do.

Labels can be used to differentiate program parts or subroutines, and comments


should be used to make the instructions and routines more understandable.

Chapter 5
©1998 Sirius microSystems Microchip Code 49 Writing a Simple
Program
Questions
1. What is the difference between a directive and an instruction?

2. What are the requirements for a label field?

3. Must comments be placed in the comment field?

4. Why can we not make the directive ORG 05h the first line of code?

5. What is the result of omitting the SLEEP instruction at the end of the pro-
gram?

Assignment
1. Follow the steps below to write a simple program which illuminates the first
four LEDs (RB0 to RB3). Save the program as TOPFOUR.ASM and set the
microcontroller ID locations to ‘TOP4’.

Step 1. Start the EDIT program.


Step 2. Enter the program comment and Device directives.
Step 3. Examine OUTPUT.ASM and the schematic diagram on page 26
to determine the commands needed to illuminate the top four LEDs.
Step 4. Save your program using the Save As option from the File menu.

As you continue to program


you will become more
comfortable with the
assembly instructions.
Really! Flip to the Data
Sheets to see all of the
other instructions you don’t
yet know.

BSF RP0 CLRF TRISB BCF RP0 MOVLW 01010101b MOVWF


PORTB SLEEP... the only thing I understand is SLEEP!

Questions
50 Microchip Code ©1998 Sirius microSystems
Assembling
6 a Program

The function of an Assembler is to convert text source code into numeric ma-
chine language instructions for the microcontroller. For example, the hexadecimal
digits 2805h represent the GOTO Initialize statement in the program, below. Al-
though we understand the meaning of the instruction GOTO Initialize, the
microcontroller understands only the numeric instructions contained in the object
code.

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector
All programs can be found
ORG 05h ;One location past Interrupt vector in the Pull-Out Program
References section.
Initialize BSF RP0 ;Select memory register page 1
CLRF TRISB ;Make Port B output by clearing TRISB

From OUTPUT.ASM in Chapter 5.

The assembler program converts your source code to object code in two passes.
During the first pass the assembler checks for correct instruction syntax, duplicate
label names, and assigns numeric values to symbols. In the example above, the label
Initialize is replaced with the numeric address 05h during assembly. During the sec-
ond pass, the assembler converts all instructions to their numeric machine codes.

Assembling the Program


Follow the steps, below, to assemble the OUTPUT.ASM source code from Chapter If you have not installed
5. From the MS-DOS prompt, change to the PICMDS directory by typing: the PIC-MDS software, do
so now. See the Quick
cd \picmds [enter] Start! sheet for details.

The assembler program is called PM.EXE. The batch file ASM.BAT calls
PM.EXE using default settings. Typing ASM filename will assemble the program.
Assemble OUTPUT.ASM by typing:

asm output [enter]

Chapter 6
©1998 Sirius microSystems Microchip Code 51 Assembling a
Program
Your screen should display the following:

C:\PICMDS>asm output

When ASM.BAT calls PM, C:\PICMDS>pm -l output


PICmicro Macro Assembler 3.01, (C) 1995, 1998 microEngineering Labs, Inc
the -l option creates a List
11 words used
file. See Appendix C for
more assembler options. C:\PICMDS>

The assembler has created two new files from your source code: the assembly
listing, OUTPUT.LST, and the object code, OUTPUT.HEX. Let’s examine the list
file first. Type the following to start the MS-DOS editor:

C:\PICMDS>edit output.lst [enter]

Notice that the List file contains a copy of your source code file along with three
extra columns of text. The assembler PM.EXE numbers every line of source code,
and identifies each memory address and its contents. If there were any errors during
assembly, PM would report the line number at which the error occurred.

34 ;Requirements
35
36 ; This is a simple program that requires no prior setup.
37
38
39 Maclib ‘PF8x.INC’ ;Library file for PIC16C84 and PM assemble
40 ;Comment this line out for other assembler
41
Line number 42 Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
43 =554F ID ‘OUTP’
44
45 ORG 00h ;Reset Vector location
Address 46 0000- 2805 GOTO Initialize ;Start program after Interrupt vec
47
48 ORG 05h ;One location past Interrupt vecto
49
50 0005- 1683 Initialize BSF RP0 ;Select memory register page 1
Address Contents 51 0006- 0186 CLRF TRISB ;Make Port B output by clearing TR
52 0007- 1283 BCF RP0 ;Go back to register page 0
53
54 0008- 3055 Main MOVLW 01010101b ;Move 01010101b into W and
55 0009- 0086 MOVWF PORTB ;output pattern to LEDs on Port
56
57 000A- 0063 Done SLEEP ;Stop executing the program

Assembling the
Program 52 Microchip Code ©1998 Sirius microSystems
The first item in the address column (=554F) is not an address at all. It is pro-
grammer information representing the microcontroller type. Addresses are not pre- Program ROM
ceded by an equal sign. 0000 2805
0001
Notice that the address and address content areas of comments and directives
0002
(such as Device or ORG 00h) are blank. Directives and comments do not generate
instructions or associated data for the program ROM. Remember, directives are in- 0003
structions for the assembler, not instructions for the microcontroller. 0004
0005 1683
The first generated address is on line 46 of the list file and contains 2805h. 2805h 0006 0186
is the machine code equivalent of GOTO Initialize. By examining the List file, you 0007 1283
can see each machine code instruction and its exact location. The memory map at 0008 3055
right graphically shows the ROM addresses and contents. 0009 0086
000A 0063
The list file demonstrates the result of the ORG directives. For example, the 000B
ORG 05h directive on line 48 generates no instruction for the program ROM. Rather,
000C
it tells the assembler that the next instruction (BSF RP0, or 1683h) should be placed
in location 0005h.

BSF RP0 also has the label Initialize associated with it. The assembler will
assign location 0005h to this label on the first assembly pass. During the second 03FE
pass, any instructions which reference Initialize will be replaced with 0005h. For 03FF
example, GOTO Initialize in line 46 converts to GOTO (28) Initialize (05).
The OUTPUT.ASM pro-
Some patterns in the list file are obvious. 28xx is the machine code for GOTO, gram loads into the PICs
and xx86 alters RP0. The job of the assembler is to convert all of the mnemonics to memory as shown above.
numeric machine code. These numbers represent our program. In fact, numbers are
the only thing the microcontroller understands. Before assemblers, programmers would
painstakingly convert each mnemonic to a machine code number by hand. This brings
a whole new meaning to the phrase ‘some assembly required’!

Inc.
hard
Micro bly by M
AssemumbersT bler.
the N ss assem
cordle

A typical day in the life of a programmer at MicroHard Inc., where their corporate
motto is: “If it’s hard to understand, it’s ‘cause we programmed it by hand!”
Chapter 6
©1998 Sirius microSystems Microchip Code 53 Assembling a
Program
Object Code
The object code is the other file created by the assembler. Object code is the
numeric form of your program saved in ASCII format. The EPIC programmer uses
this object code to program the microcontroller.

If you were to examine the object code file, you would see the numeric instruc-
tion equivalents that make up your program.

Type ‘edit output.hex’ from


the MS-DOS prompt to
examine the object code
file. Since object code is
only used by programmer/
downloaders, we won’t
spend too much time
looking at it.

If you examine the numbers carefully, you’ll find the 2805 (GOTO Initialize)
and the 1683 (BSF RP0), etc. The object code is stored in an Intel Merged Hex
format with the low byte followed by the high byte (so 2805 becomes 0528). Pro-
grammer information and checksums are interspersed throughout.

PM can also generate binary output, map and symbol files. If you need to know
more about these options, see Appendix C for the details.

Chapter Summary
The function of an assembler is to convert text source code mnemonics into
numeric machine codes. The machine codes generated by the assembler are found in
both the listing and object code files.

Listing files can be used to verify the location of instructions and their addresses.

Object code is used by the programmer to download your program into the mi-
crocontroller.

Object Code
54 Microchip Code ©1998 Sirius microSystems
Questions
1. What is the function of an assembler?

2. How does the assembler generated list file differ from the source code file?

3. Why is the ‘GOTO Initialize’ in line 46 of OUTPUT.ASM a better way of


coding than ‘GOTO 05h’?

4. Why does the assembler read your source code two times?

5. What address does the assembler assign to the label ‘Main’ on line 54?

Assignment
1. Following the steps described earlier, assemble TOPFOUR.ASM. Examine
the list file. How many instructions were produced?

Chapter 6
©1998 Sirius microSystems Microchip Code 55 Assembling a
Program
Notes
56 Microchip Code ©1998 Sirius microSystems
Downloading
7 a Program

The next—and long awaited step after writing the program source code and
assembling it to product object code—is to download our object code into the micro-
controller. Once this is done, we can see the program at work.

Which Microcontroller Should I Program?


The PIC-MDS Professional system comes with both the PIC16C711 and
PIC16F84 microcontrollers, but is capable of programming any of the 18-pin mid-
range (16Cxx series) PICmicro™ microcontrollers. The PIC-MDS Hobbyist sys-
tems include only the PIC16F84 microcontroller. Since you will be writing and test- The older PIC16C84 and
ing a number of programs in the next few chapters, you will need at least one eraseable the PIC16F84 are electri-
PIC. The PIC16F84 is EEPROM-based (Electrically Eraseable Read Only Memory) cally compatible and can
and can be quickly and easily erased while in-circuit. be used interchangeably.

If you need analog input capability, you may want to use the EPROM-based When using an EPROM
PIC16C711 or one of the other PIC16Cxx family. These microcontrollers are avail- microcontroller with a
able in OTP (one time programmable) and windowed versions. Make sure that you window, always cover the
use one in a ceramic package with a window as specified by the -JW suffix in the part window after programming.
number. Otherwise, you will know exactly what Microchip means by one time pro- Because silicon is photo-
sensitive, light striking the
grammable! To erase EPROM microcontrollers, you will need an uv (ultraviolet
chip die through the
light) EPROM eraser. UV erasers are available from most electronic distributors. window can affect the
microcontroller’s opera-
tion. Black electrical tape
Programming is an opaque and easily
removable window cover-
We will program a PIC16F84 with the OUTPUT program we just assembled. ing.
At this time, connect the EPIC programmer to your personal computer’s parallel port
with a 25-pin male to female DB-25 cable, and attach the 12 VAC wall adapter.
Make sure that the EPIC programming socket is empty until the programming soft-
ware is executed. Also be sure that the EPIC Programmer is placed on an insulated
surface to prevent the circuit traces and pins on the bottom of it from shorting to each
other.
Chapter 7
©1998 Sirius microSystems Microchip Code 57 Downloading
a Program
The EPIC programmer can be operated from batteries instead of using the 12
VAC wall adapter. If you choose to power the EPIC Programmer with two 9 volt
batteries, plug each battery onto the battery snaps. Connect the 2 pin shorting jumper
to the 2 pin “Batt ON” jumper. It is a good idea to check the battery voltage from
time to time, especailly if you are having difficulty programming parts.

WARNING: Do not connect a battery across the centre snaps. Doing so


shorts out the battery and may cause it to explode.

The EPIC programmer can program 18-pin mid-range PICs either in its own
programming socket, or through the microcontroller socket of the PIC-MDS. Pro-
gramming PICs in the PIC-MDS requires that you plug in the wall adapter and that
you connect the 10-pin programming ribbon cable to the EPIC programmer. The
cable attaches to the PIC-MDS in only one way. However, make sure that the cable
connects to the EPIC programmer properly, as shown in the photograph below:

JU3, the RUN/PROGram


jumper near the program-
ming header on the PIC-
MDS should remain in the
RUN setting during
programming. This isolates
the power supplies of the
PIC-MDS and EPIC and
prevents the EPIC from
having to power the PIC-
MDS.

On both the PIC-MDS and EPIC, pin 1 of the programming ribbon cable header is at
the lower left when the writing on the boards is upright. Make sure that you connect the
EPIC end of the ribbon cable properly, with pin 1 of the cable closest to the word
programmer.

The programmer should now be powered up and ready to program your PIC.
Note that the EPIC LED may be lit at this point. This is no cause for alarm. The LED
should go out as soon as the EPIC programming software is started. Do not insert or
remove a microcontroller from the EPIC or PIC-MDS when the LED is on.

Programming
58 Microchip Code ©1998 Sirius microSystems
Downloading the Object Code
From the MS-DOS prompt, start the EPIC program by typing:

epic output.hex [enter]

Your computer screen should look like the one shown below:

If you see a message


stating ‘Programmer not
Found’, press and hold the
RESET button on the PIC-
MDS while selecting Retry.
On start-up, EPIC checks
for the presence of a PIC.
If the PIC is blank, all I/O
pins are inputs and the
check completes properly.
If the PIC has previously
been programmed and
PORTB.6 and PORTB.7
were set as outputs, the
check will fail. Holding
RESET forces all I/O pins
to input and lets EPIC find
the programmer.

Your program object code will be visible in the blue portion of the screen, along
with the address locations of the fist instruction of each line of object codes. Along
the right, in the turquoise section of the screen are the configuration fuses settings
selected by the Device directive in your program. These settings are the defaults for
the OUTPUT program, but can be changed by clicking on them with a mouse. Chap-
ter 3 and the PIC data sheets explain all of the configuration fuse meanings.

We’re now ready to program a PIC16F84. Place the PIC16F84 into the pro-
gramming socket of the PIC-MDS with pin 1 at the top-left. Before starting to pro-
gram the PIC, make sure that the EPIC Device section matches the one in the dia-
gram, above.

Select the Program button now. The EPIC software reads all of the PICs memory Any of the grey buttons on
locations to verify that it really is blank, and then programs it. If the PIC in the the EPIC screen can be
programming socket contains a previous program, EPIC warns you of this and asks selected with the mouse or
if the PIC should be programmed anyway. Select ‘OK’ to continue programming. by pressing and holding the
Alt key along with the
highlighted letter of the
A few second later, you will see the message ‘Programming Complete’ at the button.
bottom of the blue section of the screen.

As the microcontroller gets programmed, EPIC verifies the contents of each


memory location by reading the the memory location and comparing its contents to
the original object code. If the instruction from the memory location and does not
match the object code, a problem has occurred and EPIC produces a verify error.
You may also use the Verify command to compare the memory of a PIC with an
object code program at any time.

Chapter 7
©1998 Sirius microSystems Microchip Code 59 Downloading
a Program
Running the Program
If you programmed the PIC while in the PIC-MDS, the PIC will execute the
program as soon as programming has stopped. If you programmed the PIC in the
EPIC programmer, gently pry the PIC from the programming socket, insert it into the
PIC-MDS and apply power by connecting the plug from the wall adapter.
If you don’t see the proper
display, try pressing the
You should immediately see the binary number 10101010 displayed on the eight
RESET button. While LEDs. Congratulations on writing, assembling and programming your first PIC
RESET is pressed all LEDs microcontroller program!
should be on. If this doesn’t
happen, or the output
pattern is not displayed Reprogramming PIC Microcontrollers
upon releasing RESET, see
Appendix B, Troubleshoot-
ing.
As you progress through this text, you will need to reprogram your PIC. If you
leave the PIC16F84 in the microcontroller socket of the PIC-MDS you can effort-
lessly program it with new programs. The only exception, of course, is programs
requiring analog input. The PIC16C711 can be programmed while in the PIC-MDS
but must be removed for erasure under ultraviolet light.

Chapter Summary
Programming a microcontroller requires that the object code program be
downloaded to the microcontroller. Downloading is most easily accomplished by
connecting the EPIC programmer to the PIC-MDS through the programming ribbon
cable. Remember to press and hold the RESET button if you get a ‘Programmer not
Found’ error when starting EPIC. After programming, the PIC immediately executes
the program.

Running the Program


60 Microchip Code ©1998 Sirius microSystems
Questions
1. What precautions must be taken before placing a PIC into the EPIC program-
mer?

2. When is erasing necessary?

3. How is the PIC16C711 erased?

Assignment
1. Erase and program your microcontroller with both the TOPFOUR program
that you wrote and assembled previously. Verify its operation by running the
program in the PIC-MDS board.

Remember to put your PIC into the programming socket the


right way around, or you’ll find out why programming is also
nicknamed “burning”!

Chapter 7
©1998 Sirius microSystems Microchip Code 61 Downloading
a Program
Notes
62 Microchip Code ©1998 Sirius microSystems
Looping
8

One of the most fundamental programming concepts is looping. If you’ve pro-


grammed in BASIC or another high level language you’re probably familiar with the
concept. Basically, looping allows a programmer to repeat code again and again.
Loops can go on forever (infinite) or they can repeat a finite number of times. We’ll
first examine infinite loops.

Infinite loops
Infinite loops do not end and have the following structure:

This is an example of
Start code, Pseudo-code. Pseudo-code
more code, is code programmers write
and still more code to identify the flow and
Go to Start
structure of programs.

Microcontroller programs almost always have this basic structure. Remember


that microcontrollers run a program designed for a specific purpose. Most microcon-
troller applications involve monitoring and controlling a continuous process. In order
to keep the program running continuously a GOTO instruction is often used to tell
the microcontroller to repeat code from the beginning of the program.

For example, the microcontroller in a computer mouse will check the button and
roller positions and send this information to a personal computer. The simplified
pseudo-code for the mouse might look like:

Start Send button 1 state


Send button 2 state
Send X roller motion
Send Y roller motion
Go to Start

Chapter 8
©1998 Sirius microSystems Microchip Code 63 Looping
Let’s look at a simple program which demonstrates an infinite loop. The pro-
gram COUNT.ASM sequentially displays the binary numbers from 0 to 255 on the
LED bar graph display. The count will repeat as the Port B register ‘rolls-over’ from
255 to 0, very much like a car odometer. The pseudo-code for COUNT.ASM is:

Initialize Set Port B for output


Clear Port B

Loop Increment Port B


Go to Loop

You may wish to pull out the program COUNT.ASM from the Pull-Out Pro-
gram References Section as we describe it.

Maclib ‘P84.INC’ ;Library file for PIC16C84 and PM assembler


;Comment this line out for other assemblers

Device PIC16C84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘CNT ‘

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector

ORG 05h ;One location past Interrupt vector

The program begins with the familiar Maclib, Device and ID directives. These
are followed by the ORG 00h and GOTO Initialize instructions that form the Reset
code of many example programs (refer to Chapter 5 for more detail).

Initialize BSF RP0 ;Select memory register page 1


CLRF TRISB ;Make Port B output by clearing TRISB
BCF RP0 ;Go back to register page 0
CLRF PORTB ;Turn off LEDs by clearing Port B

The Initialize routine prepares Port B for output and clears the LEDs.

Loop INCF PORTB ;Add 1 to Port B register


GOTO Loop ;and do it again, and again...

Done SLEEP ;Stop executing the program

INCF PORTB (Increment the File Register, Port B) adds one to the contents of
the Port B register. Since Port B is connected to the LED bar graph, the value in Port
B immediately appears on the LEDs. GOTO Loop forms the infinite loop structure.

Assemble and download this program as you did with OUTPUT.ASM in Chap-
To see the current count, ter 6 and Chapter 7. When the PIC microcontroller executes this program, all of the
just remove the crystal LEDs will appear to be lit. Because there is no delay after the increment instruction,
from its socket. This stops each count appears on the LED only for as long as it takes to execute the GOTO
the clock and displays the Loop and the next INCF PORTB—about one-millionth of a second at a 10 MHz
count. When you reinsert
clock speed!
the crystal, the program
continues!

Infinite Loops
64 Microchip Code ©1998 Sirius microSystems
Finite Loops
Finite loops execute a set number of times and can have two structures. The first
checks for a condition, and either repeats or exits the loop based on the result of the
conditional check. In pseudo-code:

Label code,
more code,
and still more code
If condition, go to Label
Otherwise,
code,
code,
and more code

An example of this first structure might be a burglar alarm. The microcontroller


might check a number of sensors, and if one or more are tripped sound an alarm. The
pseudo-code follows:

Check If sensor 1 open, go to Alarm


If sensor 2 open, go to Alarm
If sensor 3 open, go to Alarm
Go to Check

Alarm Activate Siren


If correct code entered, go to Alarm_Off
Go to Alarm

Alarm_Off Deactivate Siren


Go to Check

The second structure requires a variable which is modified during loop execu- Of the 35 PIC mnemonics,
tion. The modification of this variable should make a condition true or false. The 13 are commonly used to
check for the condition should occur immediately after the modification because modify variables before
subsequent instructions can affect this condition. Again, the microcontroller repeats making a decision based on
or exits the loop based on the condition. The pseudo-code looks like: conditions. They are:
ADDWF, ADNWF, COMF,
DECF, DECFSZ, INCF,
INCFSZ, IORWF, MOVF,
Initialize variable
RLF, RRF, SUBWF, and
Label code, XORWF. See the PIC data
more code, sheets for more instruction
and still more code. details.
Modify variable
If condition, go to Label
Otherwise,
code,
code,
and more code

An example of this structure can be found in a digital clock. The Hours variable
might be set to ‘12’ and the Minutes variable to ‘00’. Every 60 seconds, the Minutes
variable is incremented. When the Minutes variable becomes ‘60’, it is reset to ‘00’
and the Hours variable is incremented. When the Hours variable becomes ‘13’ it is
reset to ‘01’. The pseudo-code follows on the next page:
Chapter 8
©1998 Sirius microSystems Microchip Code 65 Looping
Hours = 12
Minutes = 00

Main Wait 60 seconds


Increment Minutes
If Minutes = 60, go to Inc_Hours
Go to Main

Inc_Hours Minutes = 00
Increment Hours
If Hours = 13, go to Reset_Hours
Go to Main

Reset_Hours Hours = 01
Go to Main

The number of times that this second type of finite loop structure executes can be
accurately determined. For this reason, it is found in timing and counting applica-
tions. Contrast this with the first type of finite loop structure, which exits when a
condition is true, rather than when a set number of loops has occurred.

Nested Loops

The total number of loops


The program DELAY.ASM modifies COUNT.ASM to include a finite loop de-
in a nested loop = inner lay routine. The finite delay includes a nested loop. A nested loop is a loop within a
loops X outer loops. loop. The total number of loops executed in a nested loop is the product of the inner
loop and the outer loop. This gives programmers the ability to easily execute more
Nested loops are also than 256 loops. The inner loop executes 256 times (as does Port B in the COUNT.ASM
useful for array or matrix program) and the outer loop executes once for each time the inner loop cycles through
applications. For example, 256 loops. In the DELAY.ASM program, the outer loop variable, Counter2, decre-
keeping track of keyboard ments 256 times resulting in a total loop count of 65 536 loops (256 X 256) before
rows and columns. incrementing the count on the LEDs. In pseudo-code:

Initialize Clear Counter1 and Counter2


Set Port B for output
Clear Port B

Main Increment Port B

Loop Decrement Counter1


inner loop If Counter1 > 0, go to Loop
Decrement Counter2
outer loop If Counter2 > 0, go to Loop
Go to Main

You may find it useful to pull out DELAY.ASM from the Pull-Out Program
References Section as we examine DELAY.ASM in detail.

Actually, labels are sym- After the directives, you’ll notice the Hardware Equates comment. The EQU
bols—they are assigned a (EQUate) directive, assigns values to labels and symbols. A label is a memory loca-
numeric address value by tion that the program can jump to, and a symbol is simply characters which have
the assembler during been assigned a numeric value.
assembly.

Finite Loops
66 Microchip Code ©1998 Sirius microSystems
;Hardware Equates
An ‘=’ can be used in
Counter1 EQU 0Ch ;First delay counter register
Counter2 EQU 0Dh ;Second delay counter register place of the EQU directive.

At assembly time, the equate statement assigns the value 0Ch to the symbol
Counter1, which is also the first unused address location in the RAM register file.
Similarly, 0Dh is assigned to the symbol Counter2.

Don’t confuse Program


memory locations 000Ch
and 000Dh with RAM
Register File locations. The
Program memory contains
only program instructions,
not the variables used by
programs.

The variables Counter1


and Counter2 will be stored
here.

The equates section is followed by the initialization code commonly used in pre-
vious example programs.

Initialize BSF RP0 ;Select memory register page 1


CLRF TRISB ;Make Port B output by clearing TRISB
BCF RP0 ;Go back to register page 0
CLRF PORTB ;Clear Port B register
CLRF Counter1 ;Clear Counter1 register (0Ch)
CLRF Counter2 ;and Counter2 register(0Dh)

The initialize routine prepares Port B for output, clears the LEDs, and clears the
Counter1 and Counter2 variables. When power is applied to the microcontroller, the
unused RAM file registers are not automatically cleared to zero. They contain ran-
dom data and should be cleared before use.

Chapter 8
©1998 Sirius microSystems Microchip Code 67 Looping
Main INCF PORTB ;Add 1 to Port B register
Loop DECFSZ Counter1 ;Decrement Counter1 and check for 0
GOTO Loop ;If not 0, decrement Counter 1 again
DECFSZ Counter2 ;If 0, decrement Counter2
GOTO Loop ;If Counter2 is not 0, decrement
;Counter1 another 256 times
GOTO Main ;Update the LEDs after 65536 counts

INCF PORTB (Increment the File Register, Port B) adds one to the contents of
the Port B register. Since Port B is connected to the LED bar graph, the value in Port
B immediately appears on the LEDs.

DECFSZ Counter1 (Decrement File Register, Counter1, and skip the next in-
DECFSZ and INCFSZ are
struction if zero) is a combined variable modification and jump instruction. Since
commonly used for loops.
this is a common loop structure, Microchip includes a number of single instruction
words which accomplish both the modification and jump functions.

Before DECFSZ Counter1 executes, Counter1 contains the data 00h (it was
cleared in the initialize section). When DECFSZ Counter1 executes for the first time,
Counter1 will contain FFh (a decrement from 00h causes a roll-back to FFh). Since
FFh is not equal to zero, the GOTO Loop instruction which follows is not skipped.
This inner loop will continue until Counter1 equals 0—256 loops later. When Coun-
ter1 finally reaches zero, the DECFSZ Counter1 (Decrement File register, Counter1,
and Skip the next instruction if the file register is Zero) skips the GOTO Loop in-
struction and DECFSZ Counter2 is the next instruction to be executed.

When DECFSZ Counter2 executes for the first time, Counter2 contains the value
FFh. Since FFh is not equal to zero, the GOTO Loop instruction which follows is
executed next, which starts the inner loop a second time. After 256 more counts of
the inner loop, Counter2 will decrement to FEh. For each decrement of Counter2,
Counter1 has decremented 256 times.

Eventually, Counter1 and Counter2 both reach zero. In this case, the DECFSZ
Counter2 instruction causes the microcontroller to skip the GOTO Loop instruction
and GOTO Main is the next instruction to be executed.

Again, the total number of loops executed by a nested loop is inner loops X outer
loops. In DELAY.ASM this nested loop takes a relatively long time and allows us see
the transitions between successive LED increments.

Calculating Execution Times


The speed at which code executes is dependent on the oscillator clock speed and
number of machine cycles executed. Instructions require either 1 or 2 machine cycles
to execute. A machine cycle is an internal clock used by the PIC to synchronize
internal events and is equal to four oscillator clock cycles. Therefore the period of
one machine cycle equals 4 times the main oscillator period.

Clock Period Oscillator Clock


One Machine Cycle
Nested Loops
68 Microchip Code ©1998 Sirius microSystems
Since,
1
Period =
f

If the PIC-MDS clock oscillator frequency is 10 MHz, the oscillator period would
be: 1 ¸ 10 MHz = 100 ns. A machine cycle would therefore take 4 X 100 ns = 400 ns.

The number of machine cycles needed to execute an instruction depends on the


instruction type. Any instruction that modifies the program counter requires two
machine cycles to execute. All other instructions require only one machine cycle.
Let’s calculate the exact time taken by the nested loop in DELAY.ASM.
Number of
machine cycles
Main INCF PORTB ;Add 1 to Port B register
Loop DECFSZ Counter1 ;Decrement Counter1 and check for 0 1 (2 if skip)
GOTO Loop ;If not 0, decrement Counter 1 again 2
255 X
DECFSZ Counter2 ;If 0, decrement Counter2 1 (2 if skip)
255 X GOTO Loop ;If Counter2 is not 0, decrement 2
;Counter1 another 256 times
GOTO Main ;Update the LEDs after 65536 counts 2

The inner loop will take three cycles to execute, and will execute a total of 255
times. The 256th time takes only two cycles, because the 00h result in Counter1
causes DECFSZ to modify the program counter. GOTO Loop is skipped.

The total number of machine cycles executed in the inner loop is:

(255 X 3) + 2 = 767

After 767 inner loop machine cycles, the outer loop adds three cycles to get back
to the inner loop. The outer loop executes 255 times, including the inner loop. On the
256th loop, Counter2 will equal zero and the DECFSZ command will skip the GOTO
Loop instruction, taking two cycles. Algebraically:

(255 X (767 + 3)) +2 = 196 352

Finally, GOTO Main adds another two cycles giving a total delay until the next
increment of 196 354 machine cycles.

Since a 10 MHz clock produces a 400 ns machine cycle time, the overall delay
between LED increments is:

196 354 cycles X 400 ns = 78.5416 ms (or a frequency of 12.7 Hz)

In COUNT.ASM, the number of machine cycles used to increment the LEDs is


three. INCF PORTB requires 1 cycle, GOTO Loop requires two. This means that
LEDs are updated every 3 X 400 ns = 1.2 ms (or at 833.3 kHz)!
The PIC16C711 supplied
With a 10 MHz clock, the execution time of programs can be calculated down to
with the PIC-MDS Profes-
400 ns periods. Although this level of accuracy is not always required, knowing how sional can be clocked at up
to calculate cycle times exactly is crucial for timing sensitive applications. to 20 MHz, giving a 200 ns
cycle time. That’s 5 million
instructions per second!
Chapter 8
©1998 Sirius microSystems Microchip Code 69 Looping
Chapter Summary
Loops are used to repeat commonly used sections of code and to count. Loops
can be infinite, or be dependent on conditions. Finite loops deliberately modify a
variable and branch depending on the occurance of a condition. Microchip provides
a number of commands which combine variable modification with a conditional
branch. Nested loops allow for the efficient execution of a large number of loops.

The time taken by loops is dependent on the instructions used and the number of
machine cycles taken by those instructions. For the PIC microcontrollers, one ma-
chine cycle is four times the oscillator clock period. Most instructions complete in
one machine cycle. Those that modify the program counter always take two machine
cycles to complete.

After much frustration, Suzette finally executes the looping of her code.

Chapter Summary
70 Microchip Code ©1998 Sirius microSystems
Questions
1. Where in a program would you expect to find commands which form an infi-
nite loop? Select from the following:

at the beginning
near the middle
near the beginning and end
near the end
really doesn’t matter, could be anywhere

Explain the reasoning you used to choose your answer.

2. Why do variables need to be initialized as part of a finite loop structure?

3. When does the DECFSZ instruction require 2 cycles? When does it require 1?

4. Examine the PIC16F8x Data Sheets and list all of the instructions that com-
bine variable modification and conditional branching.

5. Draw arrows showing program flow in the BLIP.ASM code below. BLIP.ASM is supplied on
the PIC-MDS disk so that
6. Calculate the length of time for each blip and the delay between blips. you can run it and see what
it does.
;Hardware Equates
Counter1 EQU 0Ch ;First delay counter register
Counter2 EQU 0Dh ;Second delay counter register
Counter3 EQU 0Eh ;Third delay counter register

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector
ORG 05h ;One location past Interrupt vector

Initialize BSF RP0 ;Select memory register page 1


CLRF TRISB ;Make Port B output by clearing TRISB
BCF RP0 ;Go back to register page 0
CLRF PORTB ;Clear Port B register
CLRF Counter1 ;Clear Counter1 register (0Ch)
CLRF Counter2 ;and Counter2 register (0Dh)

Main MOVLW 0FFh ;Load W with ones to turn on LEDs


MOVWF PORTB ;and write to Port B register
MOVLW 03h ;Load W with 3
MOVWF Counter2 ;and preset Counter2 before Loop_On

Loop_On DECFSZ Counter1 ;Decrement Counter1 and check for 0


GOTO Loop_On ;If not 0, decrement Counter1 again
DECFSZ Counter2 ;If 0, decrement Counter2
GOTO Loop_On ;If not 0, do Counter1 loop

CLRF PORTB ;Turn off LEDs by clearing Port B


MOVLW 0Dh ;Load W with 13
MOVWF Counter3 ;and preset Counter3 before Loop_Off

Loop_Off DECFSZ Counter1 ;Decrement Counter1 and check for 0


GOTO Loop_Off ;If not 0, decrement Counter 1 again
DECFSZ Counter2 ;If Counter1=0, decrement Counter2
GOTO Loop_Off ;If not 0, do Counter1 loop
DECFSZ Counter3 ;If Counter2=0, decrement Counter3
GOTO Loop_Off ;If not 0, do Counter1 & 2 loops
GOTO Main ;If 0, go to Main From BLIP.ASM
Chapter 8
©1998 Sirius microSystems Microchip Code 71 Looping
Assignment
1. Write a program which will sweep a single LED across the LED bar graph
display continuously. (Hint: Look at the rotate instructions)

2. Modify the program, above, to sweep the LED back and forth across the LED
bar graph display.

3. Write a program which will generate a 440 Hz, 50% duty cycle square wave
on an output port pin. You can connect a piezo audio transducer (or a speaker
in series with a 270 W resistor, or preferably a 1 mF capacitor) between the
output port pin and ground on the screw terminal to hear this tone.

4. Write a program which will generate a beep every second. Make the beep
duration 250 ms.

Assignment
72 Microchip Code ©1998 Sirius microSystems
Switch Input
9 Programming

Microcontroller applications often depend on receiving and acting upon inputs.


Many of these inputs come from other binary digital devices and are in the form of a
voltage (0V or +5V) on an I/O pin. Common binary input devices include pushbuttons, Although the PIC-MDS
key switches, rotary switches, rotary position encoders, slotted opto-isolators, ma- system uses +5V for its
trix keypads, RS-232 transceivers, and infra-red remote receivers. power supply and logic
high state, many of the
PICmicro™ processors can
run at 2-6V. We’ll repre-
Interfacing to Switches sent this voltage as V+.

Switches represent one of the most common microcontroller interfaces. Most


switches provide two contacts which close or open when activated. Normally open
(N.O.) pushbuttons provide closed contacts when activated and normally closed (N.C.)
switches provide open contacts when activated. Both types of switches can be used to “Active high” means that
provide active high or active low inputs to a microcontroller. the PIC reads a high (V+)
voltage when the switch is
The diagram below shows how a normally open pushbutton can be wired to activated, and a low (0V)
provide an active low input to a microcontroller. The pull-up resistor provides a logic voltage otherwise. Active
low inputs are the opposite.
one (or V+) level to the microcontroller input when the switch is not activated. When
the switch is pressed, the switch connects the microcontroller input to ground. The
pull-up resistor prevents the power supply (V+) from being shorted directly to ground.

Port B of the PIC16Cxx


microcontrollers contains
built-in, user controllable
pull-up resistors. This
keeps external part counts
to a minimum. The nominal
value of these internal pull-
ups is 20 kW .

Chapter 9 - Switch
©1998 Sirius microSystems Microchip Code 73 Input Programming
This next diagram shows how a normally closed pushbutton can be used to pro-
vide a logic high level when activated. Once again, the pull-up resistor performs the
same function of providing a logic high when the switch is open, and preventing a
short circuit when the switch is closed.

Let’s look at the program ALARM.ASM which uses a piece of wire as a switch.
An LED is turned on if the input wire is disconnected from ground. The structure of
this program could be used as the basis of an alarm circuit. The pseudo-code for the
program is as follows:

main
if wire disconnected from ground,
turn on LED
and jump to main
otherwise,
turn off LED
and jump to main

If the LED turns on, it indicates that someone has broken the alarm loop.

ALARM.ASM uses the programmable internal pull-up resistors on Port B. This


means that an external pull-up resistor is not needed and allows a single piece of wire
to act as our switch.

Interfacing to
Switches 74 Microchip Code ©1998 Sirius microSystems
Although they are a part of the PIC, our program must enable the pull-up resis-
tors in order to use them. The pull-ups are only active when the port pin is an input.
Output ports have no need for pull-ups unless they are open-collector outputs.
PORTA.4 is the only open-collector output on the PIC16C711 and PIC16F84. RA.4 is pulled up by R3 in
the PIC-MDS—a 4.7 kW
Before running ALARM.ASM you resistor. See the schematic
in Chapter 4.
will need to make a connection to the PIC-
MDS terminal strip (CON1) to create the
alarm loop. Attach a wire to the PIC-MDS
as shown so that CON1-9 (PortB.0) is con-
nected to CON1-3 (GND). Remove the wire
from either terminal to simulate the break-
ing of the alarm loop.

You may wish to pull out the program


ALARM.ASM from the Pull-Out Program
References section as we describe it.

Remember, RP0 is the


Initialize BSF RP0 ;Select register page 1
MOVLW 00000001b ;Load W with desired I/O pattern register page selection bit.
MOVWF TRISB ;Move W to TRISB to make bit 0 input Setting RP0 selects register
;(1=input, 0=output) page 1.
BCF RBPU ;Enable Port B pull-up resistors
;(OPTION.7 on register page 1)
BCF RP0 ;Back to register page 0 The symbol RBPU has been
CLRF PORTB ;Turn off all LEDs assigned to be Option.7 by
the .INC file.
The Initialize section of the program configures the PORTB tristate register,
enables the pull-up resistors and turns off the LEDs on Port B. Note how the MOVLW
00000001b instruction sets only PORTB.0 as an input. The BCF RBPU (Bit Clear
in File register, Port B Pull-Up enable) instruction clears bit 7 in the Option register.
Clearing Option.7 enables the pull-up resistors on all Port B inputs.

Note that both TRISB and the OP- If you haven’t yet done so,
TION register are on register page 1. Al- consider reading the
though the TRISB and OPTION regis- Microchip data sheets now.
ters are both on the PIC block diagram, They provide invaluable
there is no indication of where the RBPU insight into the inner
workings of the PICmicro™
bit is. RBPU is defined in the .INC file
family of microcontrollers.
as Option.7, but referencing RBPU does
not automatically select register page 1.
It is up to you to select register pages, so
it is imperative to check the data sheets
before using register bits that you are un-
familiar with. As you gain more experi-
ence with the PIC family, you will get a
better idea of the location of key regis-
ters and control bits.

Chapter 9 - Switch
©1998 Sirius microSystems Microchip Code 75 Input Programming
Main BTFSC PORTB.0 ;Check Port B bit 0 for a low
Remember, the .0 in
GOTO LED_On ;If we’re here, bit 0 is high
PORTB.0 is Microchip’s BCF PORTB.1 ;If bit 0 is low, turn off LED
way of checking a single GOTO Main ;Check bit 0 again
bit in a file register—not
LED_On BSF PORTB.1 ;Turn on LED on bit 1
the whole register.
GOTO Main ;Check bit 0 again

The Main routine of ALARM.ASM checks our wire and determines whether or
not to light the LED. BTFSC PORTB.0 (Bit Test File register, Skip the next instruc-
tion if Bit is clear) is a combination condition test and branch instruction, and checks
the state of the input at Port B, bit 0. If the input is low—or clear, as it would be if the
wire is connected—the GOTO LED_On instruction will be skipped, and the BCF
PORTB.1 (Bit Clear File register, PORTB.1) instruction will be executed. Clearing
Since PORTB.0 is an input, a Port B bit turns off the LED associated with it. This part of the program has one
the LED connected to function: if the wire is connected from PORTB.0 to ground, the LED on PORTB.1 is
PORTB.0 will show the turned off.
state of the input wire. The
LED on PORTB.1 shows If the wire is disconnected from ground, the input will be pulled high (or set) by
the output from the PIC.
the internal pull-up resistor, and the GOTO LED_On instruction will be executed
next. The PIC jumps to the BSF PORTB.1 (Bit Set File register, PORTB.1) instruc-
tion and lights the LED on Port B.

Assemble and download the program ALARM.ASM and verify that it works.

Counting Switch Activations


Counting how many times an event has occurred is another common microcon-
troller application. Programs which count how many times a switch has been pressed
must take into account one significant characteristic of many switches, namely con-
tact bounce. Every time switch contacts close, they may make and break many times
before settling down to their final state. The duration of each contact bounce depends
on the switch but can be up to a few milliseconds. Remember that instructions take
Software switch de-bounc- only 400 to 800 ns to execute at a 10 MHz clock rate (see Chapter 8). Since the
ing is cheaper than hard- microcontroller can easily execute over 2000 instructions per millisecond it is fast
ware solutions. enough to count each contact bounce as a switch closure. To avoid this, a short
software delay is used to de-bounce the switch, and count only one switch closure.

Contact Bounce
V+

V+

0V

Pressed Released

This diagram represents typical switch contact bounces. Your results may vary—widely!

Counting Switch
Activations 76 Microchip Code ©1998 Sirius microSystems
BOUNCE.ASM is a program which
will count the number of times a switch
bounces. Program a PIC16F84 with
BOUNCE.ASM. BOUNCE.ASM uses
PORTA.4 as the input and displays the Wait! Since the PIC only
number of bounces on the LEDs in binary. has built-in pull-ups on
Before running BOUNCE.ASM, connect Port B, and BOUNCE.SRC
a wire or switch to ground (CON1-3) and uses Port A, don’t we need
PORTA.4 (CON1-8). The program dis- a pull-up resistor? Yes, and
plays a cumulative count of each switch PORTA.4 is pulled up by
contact bounce to ground. To reset the count R3 on the PIC-MDS—a 4.7
to zero, press the RESET button on the kW resistor. See the sche-
PIC-MDS. matic in Chapter 4.

You should notice that a wire connecting PortA.0 to ground bounces many times.
Try a few different switches and note how many times they bounce.

Pull BOUNCE.ASM from the Pull-Out Program References section as we ex-


amine how it works. The pseudo-code looks like this:

Initialize variables & ports

Main
If PortA.4 is high, go to main
Otherwise, increment Port B

Wait
If PortA.4 is low, go to Wait
Otherwise, go to main

Counting Contact Bounce


V+

V+

0V

Pressed
Note that BOUNCE.SRC
cannot just check for a low
to increment Port B. It must
wait until the input bounces
high before counting the
next low bounce.

Wait for Inc. Inc. Inc. Inc. Inc.


activation count count count count count
& wait & wait & wait & wait & wait
for for for for for
high high high high high

Chapter 9 - Switch
©1998 Sirius microSystems Microchip Code 77 Input Programming
Initialize BSF RP0 ;Select register page 1
MOVLW 00010000b ;Load W with the desired I/O pattern
MOVWF TRISA ;Make Port A bit 4 input
;(1=input, 0=output)
CLRF TRISB ;Make Port B output
BCF RP0 ;Back to register page 0
CLRF PORTB ;Turn off all LEDs

The Initialize section of the program configures the PORTA and B tristate regis-
ters, and turns off the LEDs on Port B.

Main BTFSC PORTA.4 ;Check Port A bit 4 for a low


GOTO Main ;If we’re here, bit 4 is high
INCF PORTB ;If bit 4 is low, increment Port B

Wait_for_High BTFSS PORTA.4 ;Check Port A bit 4 for a high


GOTO Wait_for_High ;If we’re here, bit 4 is still low
GOTO Main ;Bit 4 went high, wait for next bounce

Main waits for PORTA.4 to go low before incrementing the count on Port B.
Then the PIC then executes the Wait_for_High loop until PORTA.4 returns high.

BTFSC PORTA.4 (Bit Test File register, Skip the next instruction if bit Clear)
will skip the GOTO Main instruction if PORTA.4 is low. A low on PORTA.4 repre-
sents a contact bounce to ground. When this happens, INCF PORTB (Increment File
register) adds one to the contents of Port B. Note that the Port B register not only
connects to the LEDs, but is also used to store our count.

You can use BOUNCE.SRC After incrementing Port B, BTFSS PORTA.4 (Bit Test File register, Skip the
to check switches for next instruction if bit Set) will execute GOTO Wait_for_High as long as PORTA.4
contact bounce by connect- remains low. When PORTA.4 goes high, BTFSS PORTA.4 will skip GOTO
ing a switch between Wait_for_High and GOTO Main will execute next, repeating the program.
PORTA.4 and ground.
Some switches rarely
bounce while others may
bounce more than ten Switch Debouncing
times.
If our applications are going to use switches, our programs obviously need to be
able to accommodate the contact bouncing that occurs. The software method of switch
debouncing involves waiting for a switch activation, and then pausing for a few
milliseconds before checking to see if the button is still activated. By that time the
contacts should have settled down and the activation can be sensed by the program.
Noise can be generated by If the code finds the switch is not activated when it checks for the second time, the
electrostatic discharge first detection was likely noise and should not be registered as a switch activation.
(ESD) from people, or can
be induced from high DBOUNCE.ASM demonstrates switch debouncing. The pseudo-code is:
currents being switched
nearby. Microchip recom-
mends 100 W series Initialize variables & ports
resistors on inputs to
keyswitches for ESD Main
protection. If PortA.4 is high, go to main
Otherwise, execute debounce delay
If PortA.4 has returned high, go to main
Otherwise, increment Port B
Go to main

Switch Debouncing
78 Microchip Code ©1998 Sirius microSystems
DBOUNCE.ASM uses the same connections as BOUNCE.ASM. Assemble,
download and execute DBOUNCE.ASM to verify its operation. You should be able
to quickly touch and release the wire (or a switch) to PORTA.4 (CON1-8) and cause
Port B to increment only once.

Pull out DBOUNCE.ASM as we examine it, below:

;Hardware Equates

Counter1 EQU 0Ch ;First delay counter variable


Counter2 EQU 0Dh ;Second delay counter variable

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector

ORG 05h ;One location past Interrupt vector

The Equates section assigns register file locations to our two delay counter vari-
ables. The standard Reset Vector code follows the equates.

Initialize BSF RP0 ;Select register page 1


MOVLW 00010000b ;Load W with the desired I/O pattern
MOVWF TRISA ;Make Port A bit 4 input
;(1=input, 0=output)
CLRF TRISB ;Make Port B output
BCF RP0 ;Back to register page 0
CLRF PORTB ;Turn off all LEDs
CLRF Counter1 ;Clear location Counter1 (0Ch)
MOVLW 40h ;Load W with preset for counter 2
MOVWF Counter2 ;Store W to Counter2 (0Dh)

Initialize configures the Port A and B tristate registers, setting PORTA.4 as


input and all of PORTB as output.

Counter1 and Counter2 are set to 00h and 40h, respectively. This provides an
overall loop delay of 64 (40h) loops of 256. Counter1 decrements from 00h, to FFh,
then FEh, and so on back to 00h, providing 256 inner loops.

Main BTFSC PORTA.4 ;Check Port A bit 4 for a low


GOTO Main ;If we’re here, bit 4 is high

Main waits for PORTA.4 to drop low. When it does, the GOTO Main instruction
is skipped and the Delay subroutine code executes.

Delay DECFSZ Counter1 ;If we’re here, bit 4 is low


GOTO Delay ;Let’s wait at least 20 ms for the
DECFSZ Counter2 ;contacts to settle
GOTO Delay

MOVLW 40h ;Once delay is done, reset counter 2


MOVWF Counter2 ;Store W to Counter2 (0Dh)

The Delay routine is a two-level deep nested loop that executes 16 384 times,
wasting 48 512 processor cycles. At a 10 MHz clock speed this provides a delay of
approximately 19.4 ms—a typical debounce delay time. When the delay loop is com-
pleted, Counter2 is re-initialized by MOVLW 40h and MOVWF Counter2 so that it
restarts from 40h rather than 00h.
Chapter 9 - Switch
©1998 Sirius microSystems Microchip Code 79 Input Programming
BTFSS PORTA.4 ;Is Port A bit 4 still low?
INCF PORTB ;If so, increment Port B
Wait_for_High BTFSS PORTA.4 ;Wait for Port A bit 4 to go high
GOTO Wait_for_High ;If low, keep checking
GOTO Main ;If high, go back to Main

BTFSS PORTA.4 checks the input, and only increments Port B if PORTA.4 is
still low after the debounce delay. Next, the BTFSS PORTA.4 after the Wait_for_High
label causes GOTO Wait_for_High to be executed while PORTA.4 is low. Only
when PORTA.4 goes high will GOTO Main be executed.

Interfacing to Matrix Keypads


Matrix keypads are wired in a row-by-column arrangement in order to reduce
the number of input/output lines needed to interface them to a microcontroller. In a
non-matrix keyboard each button requires its own input line. A matrix keypad is
organized such that each key connects to a row and column in a matrix of wires. The
number of lines needed for the matrix keypad is equal to the sum of the columns and
the rows. The number of switches that can be connected in a matrix is the product of
columns and rows.

Rows Cols. Sw. Lines


Matrix Keypad
2 2 4 4
2 3 6 5
3 3 9 6
3 4 12 7
4 4 16 8
4 5 20 9
... etc.

Note that for fewer than four


switches there are no input/output line
savings when using a matrix.

The software technique used to scan matrix keypads connected to microcontrol-


lers involves the use of both input and output signals. The rows are connected to the
output pins, and the columns to the inputs. A ‘0’ output is placed on one row, and ‘1’s
are placed on the remaining rows. If a key in the ‘0’ row is pressed, the ‘0’ appears at
Eight non-matrix switches the row-column intersection. Column inputs are scanned sequentially, looking for a
require eight separate ‘0’. If no ‘0’ is found, the first row is set to a ‘1’ before the second row is lowered to
lines—the same number ‘0’ and the columns are scanned again.
used to interface sixteen
matrix switches on the PIC- If a key in a row is not pressed, the input wires are effectively floating. For this
MDS. reason, pull-up resistors are required to pull the inputs up to the power supply high
level. The PIC’s programmable internal pull-ups allow us to interface to matrix keypads
without adding any external components!
Interfacing to Matrix
Keypads 80 Microchip Code ©1998 Sirius microSystems
The diagram shows an You could, conversely,
example of key scanning. output on the columns and
After making the top row scan the rows for a
low and scanning the col- keypress. We don’t do this,
however, since the columns
umns, each of the inputs
of the keypad in the PIC-
would be sensed as a ‘1’ MDS are wired to the Port
since none of the top row B pins which have interrupt
keys are pressed. The pro- capability.
gram would then advance
the low to the second row.

As soon as the first


column is scanned, the low
will be sensed. The pro-
gram now knows that the
key at the intersection of
row two, column one is
being pressed.

The pseudo-code for a routine which will scan 16 keys, determine which was
pressed, and assign a number to the key pressed looks like this:

Initialize variables and ports

Main
Place a low on first row
Set key counter to 1

Column_Check
If column 1 low, go to Done
Otherwise increment key_counter
If column 2 low, go to Done
Otherwise increment key_counter
If column 3 low, go to Done
Otherwise increment key_counter
If column 4 low, go to Done
Otherwise increment key_counter

Row_Set
If key_counter > 16, go to Main
Otherwise, set next row low
Goto Column_Check

Done
add any code that will use the key press value stored in
key_counter

The program KEYSCAN.ASM is a program which does just this and displays
the key pressed on the LEDs as a binary number for approximately 0.5 seconds. A
clever feature of this program is that is Port B is shared between the LEDs and
keypad (see the schematic of the PIC-MDS in Chapter 4). Port B is reconfigured to Sharing two or more
be an output port during the display phase, and half input and half output during devices on a microcontrol-
keypad scanning. ler’s I/O ports is an effi-
cient way of using I/O. The
In order to protect two Port B outputs from being shorted by a key press, each PIC-MDS also shares Port
row includes a series 2.2 kW resistor (see the schematic in Chapter 4). B with the LCD display.

Chapter 9 - Switch
©1998 Sirius microSystems Microchip Code 81 Input Programming
; Col. 1 2 3 4
; Row +----+----+----+----+
; Port B.0----1--| 1 | 2 | 3 | 4 |
; +----+----+----+----+
The key numbers are
; Port B.1----2--| 5 | 6 | 7 | 8 |
assigned by the order in ; +----+----+----+----+
which the matrix scanning ; Port B.2----3--| 9 | 10 | 11 | 12 |
takes place. ; +----+----+----+----+
; Port B.3----4--| 13 | 14 | 15 | 16 |
; +--+-+--+-+--+-+--+-+
; Port B.4----------+ | | |
; | | |
; Port B.5---------------+ | |
; | |
; Port B.6--------------------+ |
; |
; Port B.7-------------------------+

The opening comments of KEYSCAN.ASM show the keypad row-column con-


nections to Port B (as does the schematic) as well as the number assigned to each key.

;Hardware Equates

Counter1 EQU 0Ch ;Delay counter register


Counter2 EQU 0Dh ;Delay counter register
Counter3 EQU 0Eh ;Delay counter register
Key EQU 0Fh ;This register will hold a number from
;0-15 representing the last key pressed

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector

ORG 05h ;One location past Interrupt vector

The Hardware Equates section sets up variables for a delay counter and for the
key return code. The standard reset code follows the variable equates.

Initialize BSF RP0 ;Select register page 1


MOVLW 0F0h ;Set keypad column connections to input
;(Port B.4-7) and row connections to
;output (Port B.0-3)
MOVWF TRISB ;Write to Port B tristate register
BCF RBPU ;Enable pull-ups on inputs
BCF RP0 ;Go back to register page 0
CLRF Counter1 ;Clear delay loop counters
CLRF Counter2
MOVLW 08h ;Preload Counter3 delay loop counter
MOVWF Counter3 ;for 1/2 second delay

Initialize sets half of Port B to input and the other half to output with the MOVLW
0F0h and MOVWF TRISB instructions. BCF RBPU enables the internal pull-ups,
but they are only active on the input pins (PORTB.4-PORTB.7). Remember that
pull-ups are needed to hold column inputs high when keys are not pressed. Next, the
counter variables are cleared and pre-loaded as indicated by the comments in order to
provide a half second display delay.

Main CLRF Key ;Clear Key register and


INCF Key ;Increment Key
MOVLW 0Eh ;Output 0 to first row only,
MOVWF PORTB ;Output to Port B
NOP ;Wait for signals to settle

Main resets the Key register to one by using the CLRF Key and INCF Key
Interfacing to Matrix
Keypads 82 Microchip Code ©1998 Sirius microSystems
instructions. The MOVLW 0Eh and MOVWF PORTB instructions place a low on
PORTB.0, the top row of the keypad.

The NOP (No OPeration) instruction is very important, although it seems to do


nothing. Whenever the state of an output pin is changed, time must be given for that Though BCF and BSF
output to settle to the new value before the pin is read. The capacitance of a load on appear to be output
an output pin requires time to charge or discharge to its new value. A NOP instruc- instructions, they are
tion can provide a one cycle delay—long enough for an output to stabilize. Even very actually read-modify-write
low I/O capacitances can introduce a read error because a port write occurs at the instructions. They read the
entire port value, modify
very end of an instruction cycle, and a port read occurs at the very beginning of a
one bit, and write the value
cycle. Therefore, any port write immediately followed by a port read should be sepa- back to the port. Separate
rated from by a NOP or other non-port modifying instruction so the pin can settle. these and subsequent port
read instructions with
Col_Check BTFSS PORTB.4 ;Check first column for low NOPs.
GOTO Dispkey ;and if low, display key
INCF Key ;If no key press, increment key number
BTFSS PORTB.5 ;Check second column for low
GOTO Dispkey ;and if low, display key
INCF Key ;If no key press, increment key number
BTFSS PORTB.6 ;Check third column for low
GOTO Dispkey ;and if low, display key
INCF Key ;If no key press, increment key number
BTFSS PORTB.7 ;Check fourth column for low
GOTO Dispkey ;and if low, display key
INCF Key ;If no key press, increment key number

The Col_Check routine matches the pseudo-code quite closely. The Done label
in the pseudo-code has been replaced with Dispkey, which displays the value in Key
on the LEDs for half a second. INCF Key updates the key variable after each check.

Row_Set MOVLW 11h ;Load W with number of keys + 1


SUBWF Key,0 ;and compare with current key value
BTFSC Z ;If keys + 1 = current key then
GOTO Main ;no key was pressed

BSF C ;Set carry bit


RLF PORTB ;so that row 1 is high during rotate
GOTO Col_Check ;and check next column

If no key in the first row is found to be pressed, the Row_Set subroutine will The ‘,0’ in SUBWF Key,0
execute. Row_Set checks to see that the Key variable has not been incremented past denotes that the result of
the number of keys on the keypad (11h equals 17 decimal) by checking if Key equals the operation will be stored
17. It does this by subtracting 11h from the Key variable using MOVLW 11h and in W. A ‘,1’ suffix will store
SUBWF Key,0 (SUBtract W from File register Key, leaving the result in W). If Key the result in the file register
used in the operation. The
equals 17, the result of the subtraction will be zero and the Z bit of the Status register
PM assembler also recog-
will be set. BTFSC Z (Bit Test File register, and Skip the next instruction if the
nizes ‘,W’ as a suffix to
specified bit is Clear) tests the Z bit of the Status register and returns to Main if no leave the result of the
keys were pressed, beginning the key scanning again. operation in W. Not
specifying a destination
If the Key variable is below 17, Z will not be set and the BSF C (Bit Set File suffix leaves the result in
register, Carry Bit) instruction executes. RLF PORTB (Rotate Left File register) the file register by default.
shifts all bits in Port B one position to the left through the Carry bit. This moves the
C Port B C Port B

Before RLF PORTB After RLF PORTB


Chapter 9 - Switch
©1998 Sirius microSystems Microchip Code 83 Input Programming
low from row one to row two. Following the rotate, Col_Check scans the four key-
pad columns again. If no key press is detected, Row_Set repeats, checking for the
highest key code and setting the next row low.

Dispkey BSF RP0 ;Select register page 1


CLRF TRISB ;Set Port B to output
BCF RP0 ;Go back to register page 0

MOVF Key,0 ;Put value of Key into W


MOVWF PORTB ;and display on LEDs

If a key is pressed, the low found during Col_Check causes the program to
execute the Dispkey subroutine. Dispkey reconfigures all Port B pins to be outputs
and then moves the contents of the key variable to Port B.

Delay DECFSZ Counter1 ;3-level nested loop


GOTO Delay ;gives approx. 1/2 second delay
DECFSZ Counter2
GOTO Delay
DECFSZ Counter3
GOTO Delay

GOTO Initialize ;We’re done. Reset Port B and delay


;counters

Delay is a three-level nested loop providing approximately half a second to view


the key return code. Following the time delay, the program begins again at Initialize
so that Port B is reconfigured and the delay counters are reset.

Chapter Summary
Switches are common input devices for microcontrollers. They can be normally
open or normally closed and are used with pull-up resistors to provide a logic high or
logic low to the microcontroller when activated.

Switches exhibit contact bounce and this may adversely affect some programs.
Debouncing is easily done in software by using a short time delay.

Keypads are commonly wired in a matrix to save on I/O lines. Matrix keypads
require row and column scanning to determine the key pressed.

Interfacing to Matrix
Keypads 84 Microchip Code ©1998 Sirius microSystems
Questions
1. What is the function of a pull-up resistor?

2. In the switch circuit below, what is the level of the output both during activa-
tion and during release?

3. Does bouncing occur on activation, release or both? Explain your reasoning.

4. Explain the concept behind switch debouncing.

5. You are working on a simplified television remote control with five buttons:
power, volume up, volume down, channel up and channel down. Show how
you would wire the buttons to a microcontroller. Explain why you chose ma-
trix or non-matrix wiring.

6. Explain the concept behind matrix keypad scanning.

7 You are designing a simple serial output keyboard. If you dedicate one I/O line
to the serial output, what is the maximum number of key switches that can
interfaced?

When Grog began working in the


Quality Control department at
Zerocks Information Systems, certain
product lines showed signs of severe
switch contact bounce.

Chapter 9 - Switch
©1998 Sirius microSystems Microchip Code 85 Input Programming
Assignment
1. Find at least five different switches and using the BOUNCE program make a
chart of the average number of bounces they produce both on activation and
release.

2. Using ALARM.ASM as a guide, create a program to indicate not only when a


circuit is open, but to flash an LED if the circuit was opened and reconnected.

3. Modify your program, above, so that a key press on the keypad clears the
flashing LED.

4. Modify the program further still so that a four-digit code disables the LED.

Assignment
86 Microchip Code ©1998 Sirius microSystems
Calls and
10 Includes

Most microcontrollers include instructions that allow you to jump to a subrou-


tine and return to your main program routine when the subroutine is finished. Calling
subroutines from your main program has a number of advantages. First, commonly
used sections of code can be written as subroutines which can later be re-used by
other programs (for example, a keypad scanning routine). Second, subroutines make
your programs modular—you can quickly write a new program by stringing together
existing subroutines. Third, they save typing and, more importantly, debugging since
the same pre-tested subroutine can be used again, and again. Finally, code becomes
simpler to read because you can get an overview of the program by reading through
the subroutine calls, not all of the subroutine instructions.

Include, CALL and RETURN


The INCLUDE directive and the CALL and RETURN instructions are needed
to incorporate subroutines in your programs. The INCLUDE directive pastes the file
referred to by it into your program, at the location of the INCLUDE statement. The
included file is inserted into your code at assembly time.

CALL (CALL subroutine) is the instruction that causes program execution to


continue at the subroutine memory location, similar to a GOTO. Unlike a GOTO,
however, CALL pushes the memory location of the next instruction to be executed
after the call onto the stack in the processing unit. When the subroutine finishes
executing, a RETURN (RETURN from subroutine) instruction can pop the memory
location saved in the stack into the Program Counter, and the PIC continues execut-
ing the program from the instruction following the CALL instruction. RETURN is
always the last instruction executed in a subroutine.

The stack in the mid-range PICmicro™ family is an eight-level, first-in, last-out With an eight level stack a
subroutine can call another
memory. If a CALL occurs within a called routine, the address of the next return
subroutine, which can call
memory location is pushed onto the stack on top of the first memory location. As another subroutine, and so
such, the second memory location will be the first to be popped off the stack by the on, a maximum of eight
RETURN instruction—similar to stacks of dinner plates at a buffet restaurant. times.

Chapter 10
©1998 Sirius microSystems Microchip Code 87 Calls and Includes
Scanning a matrix keypad is just the kind of application that is suited to being
written as subroutine. KEYSCLB.ASM is a program which accomplishes the same
task as KEYSCAN.ASM in Chapter 9, but uses the INCLUDE directive along with
CALL and RETURN. Let’s look at the pseudo-code for KEYSCLB.ASM first.

Initialize variables

Start
Notice how much Call keypad initialize subroutine
smaller the main Main
program has become by Call keypad scanning subroutine
using calls to the If no key was pressed, go to Main
subroutine rather than Otherwise, set Port B to output
Display key for 0.5 s
writing the subroutine Go to Start
as part of the main
program code.
The keypad initialize and scanning subroutines look like:

Initialize
Set PORTB.0-3 as output and PORTB.4-7 as input
Return

Scan
Place a low on first row
Set key counter to 1

Column_Check
If column 1 low, Return
Otherwise increment key_counter
If column 2 low, Return
Otherwise increment key_counter
If column 3 low, Return
Otherwise increment key_counter
If column 4 low, Return
Otherwise increment key_counter

Row_Set
If key_counter > 16, go to No_Keys
Otherwise, set next row low
Goto Column_Check

No_Keys
Clear key_counter
Return

Normally, program pseudo-code does not need to show the subroutine’s pseudo-
code. We have included the matrix key scanning pseudo-code to highlight the execu-
tion sequence. When subroutines are written, they can be documented with their own
comments, pseudo-code, or flow charts.

The PIC-MDS comes with a The real power behind subroutines lies in the fact that it is not necessary for you
number of pretested to understand the inner workings of the subroutine in order to use it. As long as you
subroutines to assist you in understand what the subroutine does and how to call it, you can use it in your code.
programming.
You may wish to pull out both KEYPAD.LIB and KEYSCLB.ASM from the
Pull-Out Program References section as we describe how KEYSCLB.ASM calls
KEYPAD.LIB to perform the matrix keypad scanning.
Include, CALL and
RETURN 88 Microchip Code ©1998 Sirius microSystems
;Hardware Equates

Counter1 EQU 0Ch ;Delay counter register


Counter2 EQU 0Dh ;Delay counter register
Counter3 EQU 0Eh ;Delay counter register

;Equates required by KEYPAD.LIB


Key EQU 0Fh ;This register will hold a number from
;0-15 representing the last key pressed

Counter1-3 are variable locations used by the three-level, 0.5 s display delay
loop. The Key variable is used by the included KEYPAD.LIB subroutine library.

The calling program—in this example, KEYSCLB.ASM—must define the file Now might be a good time
register locations that its included subroutines use. To find out which subroutine to read over the comments
variables require registers, you must read the comment sections of the subroutine in the KEYPAD.LIB
libraries. These comments also explain the function and use of the subroutines. subroutine library.

Although the Included library files can define register locations by using EQUate
statements, the subroutine library file has no way of knowing if these locations have
already been assigned by your program. Therefore, the PIC-MDS subroutines re-
quire that the calling program assigns all register locations to variables.

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after interrupt vector

ORG 05h ;One location past interrupt vector

Include ‘KEYPAD.LIB’ ;KEYPAD.LIB subroutines go here

The Include directive inserts the file specified within quotes at the exact location
of the Include statement. In this example, the instructions in the file KEYPAD.LIB
will be placed into program memory starting at location 0005h.

106 ORG 00h ;Reset Vector loc


107 0000- 2825 GOTO Initialize ;Start program af
108
109 ORG 05h ;One location pas
110 If you look further down
111 Include ‘KEYPAD.LIB’ ;KEYPAD.LIB subro
* 1 ;KEYPAD.LIB v1.1 Last Modified on May 20, 1996
the .LST file, you will find
* 2 the first instruction of the
* 3 ;These program subroutines were written for the Sirius Mi
* 4 ;microcontroller development system (http://www.siriusmic KEYPAD.LIB file, or 1683h
* 5
* 6 ;Sirius MicroSystems provides this software on an “as is”
(BSF RP0), at location
* 7 ;warranty, either expressed or implied. All Sirius MicroS 0005h.

After assembly, the KEYSCLB.LST file will show the included files. Included
files have an asterisk beside their line number to denote that they were not a part of
the original source code.

Placing Include directives at the beginning of your program is a convention that


makes it easy to find the files that have been included into your program. The include
statement can, however, be placed anywhere in your program. Care must be taken so
that the include file does not disrupt or break into any existing code. For this reason,
another convention is to place the Include directives at the end of the program.

Chapter 10
©1998 Sirius microSystems Microchip Code 89 Calls and Includes
Initialize CALL KB_Port ;Library call to initialize Port B for
;keypad input
CLRF Counter1 ;Clear delay loop counters
CLRF Counter2
MOVLW 08h ;Preload Counter3 delay loop counter
MOVWF Counter3 ;for 1/2 second delay

The KB_Port label references a subroutine that is a part of the KEYPAD.LIB


include file. You will not find the KB_Port subroutine in KEYSCLB.ASM. KB_Port
sets Port B for keypad input, and when KB_Port returns, CLRF Counter1 is the next
instruction to be executed. Let’s examine KEYSCLB.LST to see what takes place in
the hardware stack when this call instruction occurs.

113 0025- 2005 Initialize CALL KB_Port ;Library call to


114 ;keypad input
115 0026- 018C CLRF Counter1 ;Clear delay loop
116 0027- 018D CLRF Counter2
117 0028- 3008 MOVLW 08h ;Preload Counter3
118 0029- 008E MOVWF Counter3 ;for 1/2 second d

Processing
The CALL KB_Port instruction pushes the
Unit
Fetch/Decode Unit
address of the next instruction (CLRF Coun-
ter1) on to the stack before loading the Pro-
ALU
gram Counter with the address of KB_Port.
Though most PIC instruc- W After address 0026h is saved on the stack, ex-
tions execute in one cycle, Program Counter ecution begins at KB_Port (location 0005h).
any instruction that 0026

modifies the Program


Counter requires two Processing After the KB_Port subroutine has finished,
Unit
cycles. CALL and RETURN Fetch/Decode Unit its RETURN instruction pops the top stack
both need two cycles. address back into the program counter. Pro-
ALU
gram execution continues at the address loca-
W
tion immediatley following the CALL (0026h).
Program Counter
0026

Main CALL KB_Scan ;Library call to scan keypad


MOVF Key,0 ;Load value of Key into W
BTFSC Z ;Check for no key
GOTO Main ;If Z set, no key so scan again

KB_Scan is another subroutine in the included KEYPAD.LIB subroutine library.


KB_Scan scans the keypad, and returns a value in the Key variable. If a key is
pressed, the value returned in Key is a number from one to sixteen. If no key is
pressed, the value returned in Key is zero. Examine the KEYPAD.LIB library file for
details.

MOVF Key,0 and BTFSC Z check to see if the Key value is equal to zero, and if
Key is zero, KB_Scan is called again. The MOVF Key,0 instruction is used with
BTFSC Z to ensure that the Z flag accurately reflects the value in Key. If you exam-
ine KB_Scan closely, you will find that no instructions modify the Z flag after Key is
cleared. However, it is good programming practice to force flag updates before con-
ditional checks, since previous instructions and subroutines may have corrupted the
flags. This is especially important with subroutines that you have not created or
thoroughly examined.

Include, CALL and


RETURN 90 Microchip Code ©1998 Sirius microSystems
Dispkey BSF RP0 ;Select register page 1 Actually, MOVF Key,0 is
CLRF TRISB ;Set Port B to output not needed as W contains
BCF RP0 ;Go back to register page 0 Key from the earlier check.
However, if memory allows,
MOVF Key,0 ;Put value of Key into W
MOVWF PORTB ;and display on LEDs adding the MOVF instruc-
tion allows you to make
If the Key value is not zero, BTFSC causes GOTO Main to be skipped and the modifications within or
Dispkey routine executes next. Dispkey sets all of Port B to output, and displays the before Dispkey without
worrying about the con-
key value on the Port B LEDs.
tents of W changing. This
convention results in more
Delay DECFSZ Counter1 ;3-level nested loop robust code which can be
GOTO Delay ;gives approx. 1/2 second delay more easily modified.
DECFSZ Counter2
GOTO Delay
DECFSZ Counter3
GOTO Delay

GOTO Initialize ;We’re done. Reset Port B and delay


;counters

Delay is a 3 level nested loop which ensures that the key value remains on the
LEDs for about 0.5s

Like most of us, Gus was


already familiar with the
stack concept of last-in,
first-out.

Reading ROM Data Tables using Calls


A ROM data table is a list of constants in program memory. These constants can
be musical tunes, delay values, ASCII characters, default parameters, serial num-
bers, sine wave look up tables, or any constant required by your program. ROM
tables should not be confused with RAM data tables which contain dynamic values
stored in file registers or the PIC16F84’s Data EEPROM. Although LCD.LIB is
described in more detail in
Chapter 12, that shouldn’t
Our example for ROM data tables is the KEY.ASM program which displays the deter you from using it.
key value on the LCD display. In addition to demonstrating data tables it also uses One of the advantages of
two subroutine libraries (LCD.LIB and BIN2DEC.LIB) that you are not yet familiar subroutines is that they
with. contain pre-written code
that works! You only need
Pull out KEY.ASM from the Pull-out Program References section and find the to know how to call the
highlighted sections of code as we describe them. subroutines and define the
variables they require.
Chapter 10
©1998 Sirius microSystems Microchip Code 91 Calls and Includes
;Hardware Equates

ORG 0Ch ;Start of File register area

;Equates required by KEYPAD.LIB:


Key DS 1 ;Key code return register
KEY.ASM uses DS to
dynamically allocate ;Equates required by BIN2DEC.LIB and DEC2BIN.LIB:
Hundreds DS 1 ;Hundreds digit
registers instead of Tens DS 1 ;Tens digit
EQUate. See the text for Ones DS 1 ;Ones digit
the advantages and disad-
vantages of doing this. ;Other equates
Counter DS 1 ;character counter for LCD
Counter1 DS 1 ;general purpose counter
Counter2 DS 1 ;general purpose counter
Counter3 DS 1 ;general purpose counter

As discussed earlier, ORG sets the ORiGin for program instructions. ORG can
also be used to set the origin for file register memory. In KEY.ASM, above, ORG
0Ch points to the first free file register location (0Ch). The DS (Define Space) direc-
tives which follow the ORG assign file register locations to the referenced symbols.

In KEY.ASM, for example, the variable Key is assigned a one byte location at
0Ch. Hundreds follows at 0Dh. In contrast with EQU, using DS to define variable
locations makes the locations dynamic—the assembler assigns locations as needed at
assembly time. EQU requires you to assign each location.

The advantage of using DS is that variables can be created and removed without
manually reassigning their addresses. The disadvantage of using DS is that variable
locations may not be known until assembly time. Another consideration when using
DS is that the ORG used to define the beginning of file register space also defines the
beginning of program memory. A subsequent ORG statement must be used to reset
the pointer to program memory.

ORG 00h ;Start program at Reset Vector

CLRF Key ;Clear Key storage register


CALL LCD_Port ;Set up ports for LCD output
CALL LCD_Init ;Initialize LCD and clear screen
GOTO Initialize ;Continue with initialize routine

ORG 05h ;Continue after interrupt vector

Include ‘LCD.LIB’ ;LCD subroutines go here


Include ‘KEYPAD.LIB’ ;followed by Keypad subroutines
Include ‘BIN2DEC.LIB’ ;and Binary to Decimal conversion

Initialize CALL DisplayInit ;Display “Key Pressed:” on LCD

The ORG 00h directive resets the origin to the beginning of program memory.

Up to this point, the first instruction following ORG 00h has been a GOTO
which will jump over the interrupt vector. This program shows how you can cram an
Interrupts are described in extra three words of program code into the space from 0000h to 0003h. Remember
more detail in Chapter 11. that the Interrupt Vector is still at location 0004h. Therefore, CLRF Key, CALL
Actually, this program will LCD_Port, CALL LCD_Init, and GOTO Initialize occupy the first four locations of
be modified in Chapter 11 program memory. The fifth location (0004h) is jumped over by the GOTO Initialize
to use interrupts. and is left blank for use as an interrupt vector if needed.
Reading ROM Data
Tables using CALLs 92 Microchip Code ©1998 Sirius microSystems
Notice again that the Include directives occur after the ORG 05h directive. All
three included subroutine library files are located in program memory starting with
LCD.LIB at location 0005h.

CLRF Key initializes the Key register to zero. CALL LCD_Port configures Ports
A and B for LCD use. Chapter 12 and the LCD.LIB subroutine explain the operation
of LCD.LIB in more detail. For now, all you need to know to use the LCD display is
that you must first initialize the ports for LCD use by calling LCD_Port, and then
initialize the LCD by calling LCD_Init. After this, load W with an ASCII character
value and call LCD_Data to display the character. Commands to set cursor position,
scroll the display, set line number and cursor options are also loaded in W, but
LCD_Reg is called rather than LCD_Data. Also, LCD.LIB calls a delay subroutine
called Delay_5ms. You must include a five millisecond or longer delay subroutine
with this name in your calling program.

Delay_5ms ;Delay loop used to initialize LCD

CLRF Counter1 ;Wipe first counter


MOVLW 1Ah ;Load W with Timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;from constant, above
RETURN

The Delay_5ms subroutine in KEY.ASM assumes a clock speed of 16 MHz.


You can change MOVLW 1Ah to increase or decrease the delay to match your clock
frequency. The delay can be longer than 5 ms, but not shorter—so you can leave the
MOVLW 1Ah unchanged for slower clock speeds.

After the LCD is initialized, GOTO Initialize is the next instruction to be ex-
ecuted. The GOTO Initialize calls DisplayInit. You may wonder why a CALL
DisplayInit is not used in place of GOTO Initialize. Remember that DisplayInit is a
subroutine and therefore the last instruction executed will be a RETURN. Return
causes the execution of the instruction following the CALL to occur—in this case
there is no instruction at 0004h, the interrupt vector, where the program execution
would return had a CALL DisplayInit been used.

DisplayInit ;Writes ‘Key Pressed:’ to first line of LCD using


;LCD display library (LCD.LIB).

MOVLW LCDCLR ;Send LCD clear display code


CALL LCD_REG ;to LCD as a command
MOVLW LCDLine1 ;Send LCD line one address to
CALL LCD_REG ;LCD as a command
CLRF Counter ;Reset character counter

DisplayInit writes the words ‘Key Pressed:’ on the LCD using a Data Table
read. The first part of DisplayInit sends commands to the LCD display which clear
the display and set the cursor to the first character of line 1. In preparation for the
data table read, CLRF Counter resets the data table pointer to zero.

Chapter 10
©1998 Sirius microSystems Microchip Code 93 Calls and Includes
Get_Char MOVF Counter,0 ;Get character offset into W
CALL Message ;use it to get character
IORLW 00h ;RETLW won’t affect flags so use OR to
BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Counter,1 ;Add 1 to Counter
GOTO Get_Char ;Do it again for next character

Message ADDWF PCL ;Offset program counter by adding W


RETLW ‘K’ ;Message
RETLW ‘e’
RETLW ‘y’
RETLW ‘ ‘
RETLW ‘P’
RETLW ‘r’
RETLW ‘e’
RETLW ‘s’
RETLW ‘s’
RETLW ‘e’
RETLW ‘d’
RETLW ‘:’
RETLW 0 ;End of message marker

The Get_Char loop reads one character at a time from the data table, compares
the character value to zero—a check to see if the end of data has been reached—and
sends the character to the LCD for display.

The first time through the loop, Counter is zero. The CALL Message jumps to
At this point, two levels of Message where the ADDWF PCL (ADD W to File register, Program Counter Low
Stack are used: one for the byte) adds the value of counter to the low byte of the Program Counter. What isn’t
CALL DisplayInit and one obvious at this point is that the Program Counter is already pointing at the location of
for CALL Message. the RETLW ‘K’ instruction. Microprocessors typically increment the Program Counter
to the next location after having read the current location.

Therefore, the ADDWF PCL adds zero to the location of the Program Counter,
so the Program Counter continues to point to the memory location containing RETLW
‘K’. RETLW ‘K’ (RETurn from subroutine with Literal in W) returns execution of
the program to the line following CALL Message with the ASCII value of ‘K’ in W.

With W now containing the first character from the table, the character needs to
Since subroutines may be checked to see if it equals zero, representing the end of data. RETLW does not,
modify flags during however, update the Z flag based on the contents of W. IORLW 00h (Inclusive OR
execution, RETURNs do Literal with W) is a non-destructive way of checking W for zero and updating the Z
not change the status of the flag—subtracts, adds and ANDs can also be used.
flags so your calling
program can check them.
If the RETLW character is not zero, BTFSC Z skips the RETURN, and CALL
LCD_Data is executed next. Calling LCD_Data writes the character in W to the
LCD display. INCF Counter,1 increments the data table counter so that the next
character will be read by CALL Message. GOTO Get_Char starts the table read
process again with the new value of Counter in W.

When CALL Message executes the second time, W will contain one. ADDWF
PCL adds one to the PCL this time, offsetting the Program Counter to the line con-
taining RETLW ‘e’. Each successive time through the Get_Char loop, INCF Coun-
ter,1 causes ADDWF PCL to return and display the next character, until the zero
character is returned. This process shows how the Message data table is read.

Reading ROM Data


Tables using CALLs 94 Microchip Code ©1998 Sirius microSystems
Main ;This program loop scans the keypad using KEYPAD.LIB and
;gets the key value from Key register. BIN2DEC.LIB is used
;to convert the binary key number to three decimal digits.
;Each decimal digit is converted to ASCII by adding 30h and
;is sent to the LCD display.

MOVF Key,0 ;Get key code in W


CALL BIN_DEC ;and convert to decimal
CALL LCD_Port ;Set up ports for LCD output
MOVLW 8Dh ;Send address of hundreds digit
CALL LCD_REG ;to LCD display data RAM
MOVLW 30h ;Load constant to convert to ASCII
ADDWF Hundreds,1 ;and add to hundreds digit
ADDWF Tens,1 ;add to tens digit
ADDWF Ones,1 ;and add to ones digit
MOVF Hundreds,0 ;Get hundreds digit into W
CALL LCD_Data ;and send it to LCD
MOVF Tens,0 ;Get tens digit into W
CALL LCD_Data ;and send it to LCD
MOVF Ones,0 ;Get ones digit into W
CALL LCD_Data ;and send it to LCD
CALL KB_Port ;Set up Port B for keypad input
CALL KB_Scan ;Read Port B for key press
GOTO Main ;Do it again!

Finally, we can examine the main program routine. MOVF Key,0 is placed here
to load W with the key value from a later call to KB_Scan. The first time through
Main, Key will be zero since it has been cleared by the very first instruction after
ORG 00h. CALL BIN_DEC converts the value in W to three decimal digits—one You can examine the
for each of the hundreds, tens and ones digits. The result of the conversion is stored comments in the
in the previously defined Hundreds, Tens and Ones registers. BIN2DEC.LIB and
DEC2BIN.LIB files for a
CALL LCD_Port is executed again, since the call to KB_Port in Main modifies detailed explanation of
the port configuration. MOVLW 8Dh loads W with the address location of the thir- how they work.
teenth (0Dh equals 13, and 80h is the start of line 1) character position on line one of
the LCD display. The call to LCD_REG sends the 8Dh command to move the cursor
to the specified position.

MOVLW 30h and ADDWF Hundreds,1 converts the binary number in Hun-
dreds to an ASCII number. The digits 0-9 are encoded in ASCII as values 30h-39h.
The tens and ones digits are also converted, and in each case the ‘,1’ specifies that the Remember, a ‘,0’ stores the
result is stored in the file register, and not in the working register. Note how W still result of operations in W.
contains 30h after each addition.

With the ASCII equivalent of the numbers now in Hundreds, Tens, and Ones, the
following MOVF and CALL LCD_Data instructions write the numbers to the LCD
display. The cursor automatically moves to the next position after each character is
written.

Finally, CALL KB_Port and CALL KB_Scan reconfigure the ports for matrix
key scanning and return a key value in the Key register. GOTO Main restarts the
process and updates the LCD display with the current value of Key.

Notice how calls to included files greatly simplify the Main code. Main calls
subroutines to control and write to the LCD display, convert numbers from binary to
decimal, and scan the matrix keypad, but the details of these operations do not clutter
the Main code. As such the Main code is easily readable and understandable.

Chapter 10
©1998 Sirius microSystems Microchip Code 95 Calls and Includes
Chapter Summary
CALL is a powerful instruction that lets you jump to program subroutines. A
RETURN command in the called subroutine returns execution to the instruction
following the CALL. CALLing and RETURNing is different from GOTO, which
simply redirects program execution.

The Include directive allows you to easily insert previously written subroutines
into your program and execute them with either CALLs or GOTOs.

RETLW is a variation of RETURN that loads W with a constant before return-


ing execution to the calling routine. RETLW is ideally suited to reading data tables
from program memory.

Chapter Summary
96 Microchip Code ©1998 Sirius microSystems
Questions
1. Why must every called subroutine have a RETURN instruction?

2. Can a subroutine have more than one RETURN? Explain.

3. What limits whether a subroutine can be called from within a subroutine?

4. How does RETLW differ from RETURN?

5. Why can RETLW not be used in the Data EEPROM of the PIC16F84?

6. Describe what the assembler does when it encounters an Include directive.

7. Explain why the included library is corrupted in the program segment, below:

ORG 00h ;Start program at Reset Vector


GOTO Initialize ;Continue with initialize routine

Include ‘KEYPAD.LIB’ ;followed by Keypad subroutines

ORG 05h ;Continue after interrupt vector

Initialize BSF RP0 ;Select register page 1


CLRF PORTB ;Set Port B to output

8. What variables must be defined by your calling program in order to use each
of the following subroutine libraries:

KEYPAD.LIB BIN2DEC.LIB DEC2BIN.LIB


LCD.LIB ATOD.LIB EEPROM.LIB
RS232RX.LIB RS232TX.LIB SEEPROM.LIB

Chapter 10
©1998 Sirius microSystems Microchip Code 97 Calls and Includes
Assignment
1. Using a data table and KEYPAD.LIB, write a program to light the LED corre-
sponding to the number of the key pressed (from Key one to eight). For exam-
ple, pressing key one should light LED RB0, pressing key two should light
LED RB1, etc.

2. Write a program to display the numbers 01 to 99 in BCD (binary coded deci-


mal) on the Port B LEDs. For example, pressing key 1 followed by key 6
should display the value 00010110 on the LEDs.

3. Write the pseudo-code for digital lock program subroutine that compares six
digits entered on the keypad to six numbers stored in a data table. If the correct
code is entered the subroutine should clear a file register bit named Code_Ok,
otherwise Code_Ok should be set to one.

4. Write the subroutine using the pseudo-code described in 3, above. Define


Code_Ok as a single bit in the file register Alarm_Bits. You can do this by:

Alarm_Bits EQU 0Ch


Code_Ok EQU Alarm_Bits.0

5. Write alarm code which displays the message ‘Enter Code’ and checks the
next six digits entered from the keypad against values stored in the data table
using the subroutine from 4, above. If the correct code is entered, your pro-
gram should display ‘Access Granted’, otherwise display ‘Access Denied’.

Assignment
98 Microchip Code ©1998 Sirius microSystems
Interrupts
11

Interrupts are microcontroller hardware responses to specific events. When an


interrupt event occurs, the microcontroller hardware temporarily suspends the cur-
rent program in order to handle the interrupt. Once the interrupt has been serviced,
normal processing resumes. This process is very similar to calling a subroutine and
then returning to the calling code except that hardware events, not software calls,
trigger a call to the interrupt service routine. Interrupt events can be internal or exter-
nal. Internal interrupt triggers include timer/counter (TMR0) overflow, the comple- TMR0 can count external
tion of an EEPROM write, and the completion of an A/D conversion. External events events (counter mode) or
that cause interrupts are a change on PortB.0 (INT), a change on PortB.4-7 (Port B internal processor cycles
Change), or an overflow of the timer/counter (TMR0). (timer mode), but not at the
same time. An interrupt is
generated whenever TMR0
Interrupts are ideally suited to processing random events as they occur, and then
overflows.
returning to the previous task. In essence, this enables an efficient form of multi-
tasking. In interrupt-driven programs, the processor focuses on one main task until
an interrupt occurs. As soon as an interrupt occurs, the processor always executes an
interrupt service routine, and, once finished, the main program resumes execution
from where it was interrupted. For example, the keypad interface programs in the
previous chapters repeatedly polled the keypad for user input. Polling is inefficient if
other processing must take place while waiting for a key press. That is, your program
spends valuable clock cycles checking for key presses—clock cycles that may be
needed for a complex math routine, for example. With interrupts, the program can
perform other tasks and respond to a key press only when it occurs, because the
keypress itself forces the program to read the keys. The only time the key scanning
code would execute when using interrupts is in response to a key press.

The response of the microcontroller to an interrupt is similar to that of the CALL RETFIE (RETurn From
instruction. During an interrupt the microcontroller finishes the current instruction, Interrupt, & Enable
pushes the address of the next instruction onto the stack, and performs an automatic interrupts) is most com-
call to the Interrupt Vector at memory location 0004h—which is where you would monly used. An interrupt
disables further interrupts
either put the interrupt service subroutine, or a GOTO to the routine. The interrupt
so that interrupt processing
service routine should determine the cause of the interrupt, respond appropriately, isn’t interrupted. RETFIE
and exit with a RETURN or RETFIE instruction. The RETURN or RETFIE in- re-enables interrupts
struction pops the top address off the stack so that processing can continue from whereas a RETURN does
where the microcontroller was interrupted. not.
Chapter 11
©1998 Sirius microSystems Microchip Code 99 Interrupts
Interrupt Registers and Flags
Interrupts are controlled through registers and flags. A number of registers con-
tain interrupt control bits, and the INTCON register (0Bh or 8Bh) contains most
interrupt flag bits. Interrupt control bits enable and configure interrupts. Interrupt
flag bits signify that an interrupt event has occurred.
Interrupts connect to the
PIC16F84 microcontroller Interrupt Logic
through the logic at right. T0IF
T0IF is the TMR0 Interrupt T0IE
Wake-up if in
Flag, and T0IE is the SLEEP
TMR0 Interrupt Enable bit. INTF
Likewise, the INT pin INTE
(PORTB.0) has a flag and Interrupt to CPU
RBIF
enable bit, as do PORTB
RBIE
(RB) change interrupts,
and the data EEPROM.
EEIF
The PIC16C711 has A-to-D
EEIE
ADIF and ADIE inputs
instead of EEIF and EEIE. GIE

The Global Interrupt Enable (GIE) bit in the INTCON register enables all inter-
rupts. Each interrupt flag has a corresponding enable bit that must be set in order for
the interrupt to pass on to the final AND operation with GIE. Notice also, that each
interrupt can wake the processor from a SLEEP instruction, even with GIE cleared.

EEIF signifies the comple- The interrupt flags and enable bits are found in the INTCON register with the
tion of an EEPROM Data exception of EEIF in the PIC16F84 and ADIF in the PIC16C711.
write. ADIF signifies the
completion of an A/D
INTCON Register
conversion.
GIE EEIE T0IE INTE RBIE T0IF INTF RBIF
bit 7 bit 0

TMR0 Interrupt
A Timer 0 (TMR0) interrupt flag is generated when the TMR0 register over-
flows from FFh to 00h. Timer 0 can be fed by either the internal instruction cycle
clock or by an external clock on the PortA.4 pin. The INTCON register bit T0IE
enables the timer 0 interrupt, and T0IF is the timer 0 interrupt flag bit. The OPTION
register controls the TMR0 clock source, the clock edge used, and the prescaler
divisor.
OPTION Register
Pages 16-17 of the
PIC16F8X data sheets RBPU INTEDG T0CS T0SE PSA PS2 PS1 PS0
summarize the OPTION bit 7 bit 0
and INTCON register bits. 0
Clock Out (fosc/4)
M 1
U
RA4/T0CKI 1 X M
U TMR0 Register
T0SE 0 X
8-bit Prescaler

T0CS T0IF

PS2 PS1 PS0 PSA


Interrupt Registers
and Flags 100 Microchip Code ©1998 Sirius microSystems
Setting the timer 0 Clock Select bit (T0CS, or OPTION.5) selects a transition on
the PortA.4 pin, whereas clearing T0CS selects the internal instruction cycle clock.
When using an external clock (T0CS is set), setting T0SE selects a high to low clock
transition to increment the TMR0 register. Conversely, clearing T0SE increments
TMR0 on a low to high clock transition.

When cleared, the Prescaler Assignment Bit (PSA, or OPTION.3) divides the See page 16 of the
TMR0 clock source by a programmable prescaler value of 2 to 256. The prescaler PIC16F8X data sheet for
divisor is selected using bits PS0, PS1 and PS2. To increment TMR0 on every clock prescaler assignments.
(without a prescaler), the PSA bit must be set, assigning the prescaler to the Watch Note: The prescaler may be
Dog Timer (WDT). assigned to either TMR0 or
WDT, but not both.
When TMR0 is set to count internal cycles, it can provide accurate time delays
while allowing other processing to still take place. TMR0 can count external events
to a maximum frequency of 50 MHz.

In the PIC-MDS, PortA.4 is connected to the serial receiver input. A serial char-
acter arriving from an external device can overflow TMR0, generating an interrupt.

INT Interrupt
PortB.0 is also known as the interrupt pin (INT). The INTF flag is generated
whenever a transition matching the interrupt edge setting (INTEDG, or OPTION.6)
occurs. The INT interrupt is enabled by the interrupt enable bit (INTE) and GIE.

A single event generated by an external peripheral such as a limit switch can be


sensed using the INT pin.

Port B Change Interrupt


When set as inputs, PortB.4-7 were designed to generate an interrupt in response
to any change in signal level from the last level read. RBIF and RBIE are the flag and
enable bits, respectively.

The Port B change interrupt is ideally suited to scanning keypads for a change,
even while the PIC is in SLEEP mode. The PIC-MDS uses PortB.4-7 as inputs for
the matrix keypad, so that any key press can generate an interrupt.

Waiting for a PortB change while putting the PIC to ‘sleep’ is an effective way of
prolonging battery life. The PIC SLEEP instruction stops the processor clock, greatly
reducing power consumption. A television remote control can save battery power by
‘sleeping’ most of the time, and ‘waking up’ in response to a key press.

EEPROM Interrupt
The EEIF interrupt flag bit (EECON1.4) is set when a write to the EEPROM Refer to Chapter 13 for
Data Memory of the PIC16F84 is finished. EEIE (INTCON.6) gates the EEIF inter- more information on the
rupt. An EEPROM interrupt is useful since a write to the EEPROM can take a Data EEPROM.
considerable amount of time. A typical EEPROM write takes 10 ms. In 10 ms a 10
MHz PIC16F84 can execute 25 000 instructions!
Chapter 11
©1998 Sirius microSystems Microchip Code 101 Interrupts
A/D Converter Interrupt
The ADIF flag (ADCON0.1) is set when the A/D converter in the PIC16C711
has finished its conversion. The A/D interrupt is gated by ADIE (INTCON.6). Al-
though the A/D converter is quite fast, interrupt capability is provided so that the
PIC can be put to sleep to minimize switching noise during conversion. See Chapter
16 for more information on the A/D converter.

Interrupt Service Routines


Unlike a planned CALL, an interrupt can occur during the execution of any part
of your program, totally disrupting your program’s normal execution. The job of an
Interrupt Service Routine (ISR) is to transparently respond to the interrupt before
restarting your program from where it was interrupted. The ISR does this by deter-
mining the cause of the interrupt, doing some action related to the interrupt (servicing
the interrupt), and clearing the appropriate interrupt flag bit before exiting and re-
turning control to your main code.

Although servicing the interrupt seems to be the primary task of the ISR, an
equally important requirement is that the ISR leave the processor state unchanged.
For example, the ISR code is just a new set of software commands that execute
within the processor after an interrupt. If, during the execution of the ISR, any proc-
essor registers are modified by the ISR, their contents must be restored to pre-inter-
rupt values before returning to your program. Otherwise, your program will not
work as expected after returning from the interrupt.

Saving and restoring registers without modifying their contents is not as straight-
forward as it first seems. The W register contents must be saved first, as all other
See 8.10, page 49 in the registers pass through W on the way to their temporary storage locations. But, sim-
PIC16F8X data sheets for ply moving W to another register can corrupt the Z flag, modifying the STATUS
more information. register, and potentially invalidating a math operation in progress before the inter-
rupt. Microchip’s recommended code sequence provides a way to save and restore
registers without modifying them. We’ll examine this code in detail in our examples.

First, let’s examine the pseudo-code of a typical interrupt serviced routine:

Save
Store W in temporary register
Store STATUS in temporary register
Store PORTB in temporary register if needed
Store other registers if needed

Service_Interrupt
Determine cause of interrupt
Service interrupt
.
.
Clear interrupt flag

The interrupt automatically Restore


clears GIE, disabling Restore other registers if saved
interrupts so that your ISR Restore PORTB if saved
Restore STATUS
is not interrupted. RETFIE Restore W
combines a RETURN and
BSF GIE. Return and enable interrupts

Interrupt Service
Routines 102 Microchip Code ©1998 Sirius microSystems
Using Interrupts to Wake-up on Key Press
KEY.ASM from Chapter 10 spent most of its time scanning the keypad waiting
for the user to press a key. Instead of constantly polling the keypad, KEYINT.ASM
puts the PIC to ‘sleep’ and uses the Port B Change interrupt to wake the processor
from ‘sleep’ whenever a key is pressed.

Although interrupt code is more complex than polling, it provides the following
advantages:
• processor current is reduced from 8 mA during polling to less than 0.05 mA
when asleep
• SLEEP can be replaced by other code routines, so the PIC doesn’t waste its time
waiting for a key press

Since KEYINT.ASM performs no processing other than executing the SLEEP


instruction, no registers need to be saved or restored during the interrupt service
routine.

Pull KEYINT.ASM from the Program References Section as we describe it.

ORG 00h ;Start program at Reset Vector

CLRF Key ;Clear key storage register


CALL LCD_Port ;Set up ports for LCD use
CALL LCD_Init ;Initialize LCD and clear screen
GOTO Initialize ;Continue with initialize routine

The CLRF Key instruction presets the Key register with the no-key code. The
next two CALLs initialize the LCD for later use. GOTO Initialize continues initiali-
zation after the interrupt service routine with a call to DisplayInit.

Initialize CALL DisplayInit ;Display “Key Pressed:” on LCD

The operation of DisplayInit is described in Chapter 10 in the description of


KEY.ASM. After returning from DisplayInit, Nap_Time is the next routine to be
executed.

Nap_Time MOVLW 8Dh ;Send address of hundreds digit


CALL LCD_REG ;to display data RAM
MOVLW ‘Z’ ;Load ASCII character Z
CALL LCD_Data ;and send it to LCD
MOVLW ‘Z’ ;Re-load ASCII character Z
CALL LCD_Data ;and send it to LCD
MOVLW ‘Z’ ;One more time!
CALL LCD_Data ;and send it to LCD

CALL Init_Port_B ;Get Port B ready for interrupts

Rather than displaying ‘000’ during a no-key press, Nap_Time displays ‘ZZZ’
to indicate that the PIC is going to sleep. CALL Init_Port_B configures Port B for
key scanning and enables the Port Change interrupt.

Chapter 11
©1998 Sirius microSystems Microchip Code 103 Interrupts
Init_Port_B ;Sets Port B up for keypad scanning. RB0-3 are low outputs
;and RB4-7 are inputs with pull-ups enabled. When a key
;press occurs, one of the RB4-7 inputs goes low, generating
;and interrupt.

CALL KB_Port ;Set Port B for keypad scanning

CLRF PORTB ;Make outputs low


MOVLW 08h ;Set only RB port change interrupt
MOVWF INTCON ;and write to interrupt register
RETFIE ;Return and enable interrupts

Init_Port_B first calls KB_Port to configure the Port B tristate registers and
pull-up resistors for the keypad. CLRF PORTB clears the keypad output lines so
that a key press will generate a change on one of the Port B input lines. Remember,
Port B inputs are pulled-up and normally read as a high. If the Port B outputs were
also high, pressing a key would not change the level on the input pins, consequently
not generating a Port Change interrupt.

Moving 08h into INTCON sets only the Port B Change enable (RBIE, or
INTCON.3). This allows the RBIF flag to be passed on to the GIE gate. Finally,
RETFIE (RETurn From Interrupt, and Enable all interrupts) returns execution to
Main and simultaneously enables all interrupts by setting GIE. RETFIE is usually
also the last instruction of any interrupt service routine.

The NOP is often placed Main SLEEP ;Shut down and wait for key press
after a SLEEP as the NOP
GOTO Main
instruction following a
SLEEP is always executed
upon wake-up. The CALL After initialization, Main executes putting the PIC to sleep. Pressing a key on the
to the ISR occurs after the keypad will change the state of PortB.4-7 and generate both an interrupt and wake up
NOP has executed. (See from sleep signal. Normally an interrupt would cause the PIC to push the address of
8.12 on pg. 51 of the the NOP onto the Stack, but the SLEEP instruction pre-fetches the NOP and ex-
PIC16F8X data sheets) ecutes it before the ISR, and leaves the address of GOTO Main on the stack.

ORG 04h ;Interrupt service routine starts

Check_RBIF ;When an interrupt occurs, Check_RBIF confirms it was


;generated by RB Port Change. If not, and other interrupts
;are enabled, they must get serviced in the Other_Int
;routine. When a valid key arrives, it gets displayed,
;then the port is re-configured for keypad input. Exiting
;this interrupt service routine, re-enables interrupts.

BTFSS RBIF ;Check for RB port change interrupt


GOTO Other_Int ;If cleared, check other interrupts
CALL Delay_5ms ;Wait key to settle
CALL Delay_5ms ;10 ms should be enough time
CALL KB_Port ;Set up Port B for keypad scanning
CALL KB_Scan ;Scan keys for key press
MOVF Key,0 ;Check Key register for 0 - no key
BTFSC Z ;by testing the Z flag
GOTO Nap_Time ;If no key was returned, user let go
;so we display ZZZ to indicate sleep

CALL BIN_DEC ;If key returned, convert to decimal

CALL LCD_Port ;Set up ports for LCD output


MOVLW 8Dh ;Send address of hundreds digit
CALL LCD_REG ;to display data RAM

Using Interrupts to
Wake-up on Key 104 Microchip Code ©1998 Sirius microSystems
Press
MOVLW 30h ;Load constant to convert to ASCII
ADDWF Hundreds,1 ;and add to hundreds digit,
ADDWF Tens,1 ;add to tens digit
ADDWF Ones,1 ;and add to ones digit
MOVF Hundreds,0 ;Gets hundreds digit into W and
CALL LCD_Data ;send it to LCD
MOVF Tens,0 ;Get tens digit into W and
CALL LCD_Data ;send it to LCD
MOVF Ones,0 ;Get ones digit into W and
CALL LCD_Data ;send it to LCD

CALL KB_Port ;Set up Port B for keypad scanning


CLRF PORTB ;and get ready for Port B change
MOVF PORTB,0 ;Update Port B input latches
BCF RBIF ;Clear the Interrupt flag
RETFIE ;and return

Other_Int RETFIE ;Return and enable global interrupts

This is the interrupt service routine for KEYINT.ASM. The ISR immediately
services the interrupt without saving the contents of any registers. In this case no
other event could have caused the interrupt, but BTFSS RBIF is included to show
how you can check to see which event caused the interrupt. If RBIF is not set, you
can use GOTO Other_Int to poll INTCON, determine what caused the interrupt, and
service it appropriately. Here, Other_Int returns to the previously executing code and
enables further interrupts via the RETFIE instruction because all other interrupts are This double-check ensures
disabled. that nothing has corrupted
the INTCON register.
After confirming that a port change caused the interrupt, CALL Delay_5ms is
used twice to allow the keys to finish bouncing before they are scanned. CALL
KB_Port and CALL KB_Scan configure Port B for keypad use and determine which
key is being pressed. The variable Key contains the key return code and is placed into
W via the MOVF Key,0 instruction. When a key is being pressed, BTFSC Z will
skip GOTO Nap_Time as the key return code is not zero. When the key is released
the key return code will be zero and GOTO Nap_Time will display the ‘ZZZ’ to Actually, the PIC will goto
indicate sleeping between key presses. sleep while the key is being
held, but the LCD contin-
CALL BIN_DEC converts the value in W (key return code) from binary to BCD ues to display the key code
at this time.
digits which are stored in the Hundreds, Tens and Ones variables.

CALL LCD_Port is required because of the CALL KB_Port earlier. The LCD
cursor is told to move to position 8D via the MOVLW 8Dh and CALL LCD_Reg
instructions. 8Dh is the 14th position on line 1 of the LCD.

Adding 30h to the Hundreds, Tens and Ones variable converts them to ASCII,
and then the MOVF and CALL LCD_Data instructions send the Hundreds, Tens and
Ones digits to the LCD.

Next, CALL KB_Port configures Port B for keypad scanning, CLRF PORTB
clears Port B outputs in preparation for the Port Change, and MOVF PORTB,0
performs a Port B read. The read is necessary to update the Port B input latches.
When interrupts are re-enabled, the Port B Change interrupt continuously compares
the value of Port B to the value stored in the input latches. Reading Port B updates
the input latches so that they reflect the key being held. When interrupts are re-
enabled, the PIC won’t generate a new Port Change Interrupt until the key is re-
leased.
Chapter 11
©1998 Sirius microSystems Microchip Code 105 Interrupts
Finally, BCF RBIF clears the Port B Change Interrupt flag just before RETFIE
returns to Main and re-enables interrupts. The interrupt flag should be cleared just
before exiting the ISR. If the interrupt flag is cleared too early, an ISR operation
could set the flag, causing an interrupt to be re-triggered immediately after exiting
the ISR causing an endless interrupt loop.

Include ‘BIN2DEC.LIB’ ;Binary to Decimal conversion routin


Include ‘KEYPAD.LIB’ ;Key pad scanning routines
Include ‘LCD.LIB’ ;LCD subroutine library

If you really wanted to In KEYINT.ASM, the Include directives are placed at the very end of the code.
place the included files at Since KEYINT.ASM uses interrupts, placing the Include directives at location
the top of the program, you 0005h— as was done with KEY.ASM—would have written over the interrupt serv-
could either place a GOTO
ice routine beginning at location 0004h.
in location 0004h to
redirect the interrupt to a
new location, leaving the
includes at location 0005h, Managing Multiple Tasks using the TMR0 Interrupt
or you could just add the
includes between the ISR 0
Clock Out (fosc/4)
and main code—just don’t M 1
U
use ORG to force the RA4/T0CKI 1 X M
U TMR0 Register
includes to a specific T0SE 0 X
address. 8-bit Prescaler

T0CS T0IF

PS2 PS1 PS0 PSA

CLOCK.ASM demonstrates two tasks running concurrently. The program cy-


cles a single LED across the LED bar graph and uses the TMR0 interrupt to keep
track of how long the program has been running. This elapsed time is displayed on
the LCD. Before explaining the program code, let’s look at how CLOCK.ASM uses
the TMR0 register.

See page 16 of the Timer 0 (TMR0) is set to count internal oscillator clocks by clearing T0CS. PSA
PIC16F8X data sheet for is cleared so that the instruction cycle clock (Clock Out in the diagram) is divided by
prescaler assignments. the 8-bit prescaler. PS2, PS1 and PS0 are set to divide the input clock by 256. The
Note: The prescaler may be end result of this is that TMR0 increments at a rate of 9765.6 times per second (at a
assigned to either TMR0 or 10 MHz clock oscillator frequency).
WDT, but not both.
Let’s look at how this is calculated. A 10 MHz clock is divided by four internally
to generate the 2.5 MHz instruction cycle clock. Dividing the 2.5 MHz instruction
cycle clock by a prescaler of 256 yields the 9765.6 Hz TMR0 clock.

TMR0 increments on every input clock. TMR0 generates an interrupt after 256
counts. At the 9765.6 Hz rate, interrupts are generated at a rate of 38.15 Hz
(9765.6÷256).

We chose 60 Hz because Often, TMR0 is modified to provide interrupts at a specific rate. CLOCK.ASM
that is the North American pre-loads TMR0 to 93 to provide an interrupt rate close to 60 Hz. By doing this,
power line frequency, TMR0 increments from 93 to 256—instead of from 0 to 256—generating an over-
which just might be useful flow after 163 counts (256-93). With an input clock rate of 9765.6 Hz to TMR0,
for other projects. interrupts will be generated at 59.91 Hz (9765.6÷163).
Managing Multiple
Tasks using the 106 Microchip Code ©1998 Sirius microSystems
TMR0 Interrupt
Refer to CLOCK.ASM in the Program References Section as we describe its
operation.

Temp_W DS 1 ;Temporary registers We know that servicing the


Temp_Status DS 1 ;used to save values during interrup TMR0 interrupt will disrupt
Temp_TRISB DS 1 ;service routine (ISR) The ISR
Temp_TRISA DS 1 ;will save their values on entry the LED cycling on Port B.
Temp_PortB DS 1 ;and restore them on exit. All of the Port B registers
Temp_PortA DS 1 must be saved, and later
restored.
In the Equates section, these Temp_ registers are noteworthy because the
CLOCK.ASM ISR saves and restores the contents of all the registers that it uses.

MOVLW 60 ;Preload sixtieths


MOVWF sixtieth ;with 60

CALL LCD_Port ;Set up ports for LCD use


CALL LCD_Init ;Initialize LCD and clear screen
CALL Disp_Init ;Display “Elapsed time:” on line 1
CALL Disp_Time ;Display time on line 2

CALL TMR0_Init ;Initialize Real Time Clock Counter


;Timer 0 (TMR0) and enable interrupt

In the Initialize subroutine the Counter variables are cleared, and sixtieth is set to
60 by the MOVLW 60 and MOVWF sixtieth instructions. The ISR decrements six-
tieth to determine when one second has passed. CALLS to initialize the LCD and
display the text ‘Elapsed time:’ and ‘00:00:00’ on the LCD follow. The CALL
TMR0_Init sets TMR0 to generate an interrupt 59.91 times per second.

TMR0_Init ;Assign prescaler to TMR0 and preload TMR0 for 60 Hz


;interrupts.

CLRWDT ;Clear WDT and prescaler


BSF RP0 ;Select register page 1
MOVF OPTION,0 ;Load W with current OPTION reg.
ANDLW 11000111b ;Clear T0CS, T0SE and PSA bits
;T0CS=OPTION.5, Counter select
;0=Timer mode, 1=Counter mode
;T0SE=OPTION.4, Source Edge select
;0=Rising edge, 1=Falling edge
;PSA=OPTION.3, Prescaler Assignment
;0=TMR0, 1=WDT
IORLW 00000111b ;Set PS2, PS1 and PS0
;000=/2, 001=/4, ...111=/256
MOVWF OPTION ;Set OPTION register with new value
BCF RP0 ;Return to register page 0

MOVLW 93 ;Load W with 93 because incrementing


MOVWF TMR0 ;TMR0 from 93-256 takes 1/60s

MOVLW 20h ;Enable only the TMR0 interrupt


MOVWF INTCON ;and write to INTCON

RETFIE ;Return and enable global interrupts

TMR0 and the watchdog timer (WDT) share the prescaler. The CLRWDT in-
struction is recommended by Microchip to ensure that a WDT time-out does not
occur while assigning the prescaler to TMR0.

Chapter 11
©1998 Sirius microSystems Microchip Code 107 Interrupts
The technique makes the Unlike KEYINT.ASM where the registers are loaded with an absolute value,
code more portable. That CLOCK.ASM loads the current state of OPTION into W and modifies only the
is, it can be used in other required bits, leaving the others unchanged. The MOVF OPTION,0 loads OPTION
programs with little or no into W and the ANDLW 11000111b clear the bits 4, 5 and 6 of OPTION leaving the
modification.
remaining bits unchanged. IORLW 00000111b sets bits 0, 1 and 2 in OPTION leav-
ing the remaining bits unchanged. MOVWF OPTION stores W into the OPTION
register.

MOVLW 93 and MOVWF TMR0 pre-loads TMR0 with the preset value 93. 93
will cause TMR0 to generate interrupts 59.91 times per second as described earlier.
INTCON is loaded with 20h so that only the TMR0 interrupt is enabled.

RETFIE ends the TMR0_Init initialization routine. It enables interrupts and re-
turns to Initialize.

BSF RP0 ;Select Register Page 1


CLRF TRISB ;Make Port B output
BCF RP0 ;Back to Register Page 0

MOVLW 01h ;Light up the first LED


MOVWF PORTB ;on Port B
BCF C ;Clear the Carry

Main ;This code runs when the Interrupt service routine isn’t
;running and cycles a single LED across the display.

:Loop DECFSZ Counter3,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter4,1 ;Decrement, second counter
GOTO :Loop ;from constant, above

RLF PORTB ;Rotate PORTB to the left


GOTO Main ;Do it again and again and ...

It takes ~80 ms to complete Here, Port B is set for output and begins to cycle the LED. The scan rate of the
the delay loop for the LED. LED is determined by the nested loop. At this point interrupts have been enabled and
Four interrupts will have
when TMR0 overflows (~16.7 ms later) the ISR takes control of the PIC.
occurred and been serviced
before the LED moves to
the next position! Check_T0IF ;When an interrupt occurs, Check_T0IF confirms it was
;generated by a TMR0 overflow. If not, and other interrupts
;are enabled, they must get serviced in the Other_Int
;routine. When TMR0 overflows sixtieth is decremented and
;checked for equalling zero. If Zero then Seconds, Minutes
;and Hours are updated and displayed. Otherwise, interrupts
;are re-enabled and execution continues.

Save MOVWF Temp_W ;Save W in Temp_W


SWAPF Status,0 ;Swap Status halves into W
MOVWF Temp_Status ;and save Status in Temp_Status

MOVF PORTA,0 ;Load W with Port and TRIS contents


MOVWF Temp_PortA ;and save to temporary registers
MOVF PORTB,0
MOVWF Temp_PortB
BSF RP0
MOVF TRISA,0
MOVWF Temp_TRISA
MOVF TRISB,0
MOVWF Temp_TRISB
BCF RP0

Managing Multiple
Tasks using the 108 Microchip Code ©1998 Sirius microSystems
TMR0 Interrupt
The Save routine must be the first part of the ISR to execute. As mentioned
earlier, W and the STATUS registers must be saved without altering their contents.
MOVWF Temp_W stores the contents of W into one of the previously defined
storage registers. SWAPF STATUS,0 (SWAP nybbles of File register, store result
in W) copies the contents of the STATUS register into W with upper and lower
nybbles exchanged. SWAPF is used because a MOVF modifies Z which is one of
the STATUS register bits. With STATUS now in W, albeit with reversed nybbles, it
is moved to a temporary storage register by MOVWF Temp_Status.

The subsequent series of MOVF and MOVWF instructions save the contents
of the PORT and TRIS registers. With all of the important registers now saved, the
ISR can service the interrupt.

ISR BTFSS T0IF ;Check for TMR0 interrupt


GOTO Other_Int ;If cleared, check other interrupts

DECFSZ sixtieth ;Has 1 second elapsed?


GOTO Exit ;If not, use Exit to leave ISR
MOVLW 60 ;If zero, reset sixtieth counter
MOVWF sixtieth ;to 60
INCF Seconds ;Update seconds and
SUBWF Seconds,0 ;check for overflow (Seconds=60)
BTFSS Z ;by testing Z
GOTO Update_Clock ;If Z=0, update clock with new time

CLRF Seconds ;If Z=1, Seconds is 60, reset to 0


MOVLW 60 ;reload W with 60
INCF Minutes ;Update Minutes and
SUBWF Minutes,0 ;check for overflow (Minutes=60)
BTFSS Z ;by testing Z
GOTO Update_Clock ;If Z=0, update clock with new time

CLRF Minutes ;If Z=1, Minutes is 60, reset to 0


MOVLW 24 ;Load W with 24
INCF Hours ;Update Hours and
SUBWF Hours,0 ;check for overflow (Hours=24)
BTFSS Z ;by testing Z
GOTO Update_Clock ;If Z=0, update clock with new time

CLRF Hours ;If Z=1, reset hours to 00

Update_Clock CALL LCD_Port ;Reconfigure Ports for LCD and


CALL Disp_Time ;display the new time

The BTFSS T0IF and GOTO Other_Int form the structure needed to test
INTCON and select the appropriate interrupt to service. In this case, only the TMR0
interrupt is enabled, but this type of check can used to identify the cause of an
interrupt if more than one is enabled.

DECFSZ sixtieth determines if 60 interrupts have occurred and exits the ISR if
not. After 60 interrupts, the elapsed time on the clock is updated.

The time is updated by first incrementing Seconds, and checking for an over-
flow to 60. If an overflow occurs, Minutes is incremented, again checking for an
overflow to 60. If an overflow occurs, Hours is incremented. Hours is checked for
an overflow to 24. If Hours overflows, the Hours, Minutes and Seconds are all reset
to zero. Finally, the calls in Update_Clock display the updated time on the LCD.

Chapter 11
©1998 Sirius microSystems Microchip Code 109 Interrupts
Exit ;Reloads TMR0 so the next 60th second time-out can generate
;an interrupt and restores all registers.

MOVLW 93 ;Preload W for 60 Hz delay


MOVWF TMR0 ;and save to TMR0
BCF T0IF ;Clear TMR0 interrupt flag and

Restore MOVF Temp_PortA,0 ;Restore registers from temporary


MOVWF PORTA ;registers
MOVF Temp_PortB,0
MOVWF PORTB
BSF RP0
MOVF Temp_TRISA,0
MOVWF TRISA
MOVF Temp_TRISB,0
MOVWF TRISB
BCF RP0

SWAPF Temp_Status,0 ;Swap Status halves to W


MOVWF Status ;and return Status to pre-interrupt
;value
SWAPF Temp_W,1 ;Swap halves of Temp_W
SwAPF Temp_W,0 ;Swap Temp_W back to W

RETFIE ;Return and enable interrupts

Other_Int ;Insert other interrupt checks here

RETFIE ;Return and enable global interrupts

To end the interrupt, Exit reloads TMR0 with the 1/60th second delay value and
clears the T0IF flag.

The Restore subroutine restores the contents of the Port and Tris registers to the
values they contained before the interrupt.

SWAPF Temp_Status,0 moves the saved STATUS register (with its nybbles re-
versed) into W in its correct order. The MOVWF STATUS instruction copies W—
containing the saved Status—back to the STATUS register. MOVWF does not affect
any of the STATUS register flags.

Finally, W must be restored. Since MOVF cannot be used since it can affect the
STATUS register flags, two SWAPFs are used to restore W. SWAPF Temp_W,1
reverses the order of the nybbles in Temp_W, leaving the result in Temp_W. This
must be done because the W register itself cannot be swapped. The next SWAPF
Temp_W,0 swaps the nybbles back to their original form and leaves the result in W.

Once all of the registers have been restored, RETFIE returns execution to Main
where the LED scanning continues.

CLOCK.ASM demonstrates how easily the PIC can accomplish two tasks at the
same time. What is not as apparent, however, is exactly how much unused processor
time is available for use by other tasks. Updating the clock uses less than 1% of the
processor’s time! By exploiting interrupts, you can cram a lot of functionality into a
simple microcontroller.

Managing Multiple
Tasks using the 110 Microchip Code ©1998 Sirius microSystems
TMR0 Interrupt
Chapter Summary
Interrupts are used to place one program subroutine on hold while another
program subroutine automatically responds to the hardware event that caused the
interrupt. The PIC16F84 can be interrupted by Timer 0 overflows, transitions of
the INT pin, changes on PortB.4-7, and completed EEPROM writes. The PIC16C711
includes the same interrupt sources except that the EEPROM write complete inter-
rupt is replaced with an A/D conversion complete interrupt.

The INTCON and OPTION registers control most interrupt functions. All in-
terrupts have an interrupt enable and an associated interrupt flag. The enable bit
does not suppress the generation of the flag, but only the generation of an interrupt.
All interrupts are gated with the Global Interrupt Enable bit (GIE).

Interrupts cause the execution of the instruction at location 0004h—the Inter-


rupt Vector. An interrupt service routine located here must:
• save all registers they modify
• determine the cause of the interrupt and service it
• clear the interrupt flag
• restore all registers to their original values

Interrupts can be used to wake the processor from sleep (reducing power con-
sumption), manage multiple concurrent tasks, and allow the PIC to respond to un-
predictable events as they occur.

No matter how complex the interrupt code became, Phil was


always impressed by how quickly Spike could locate the errors.

Chapter 11
©1998 Sirius microSystems Microchip Code 111 Interrupts
Questions

1. Describe how interrupt-driven input differs from polling an input for a change.

2. What are the four interrupt sources for the PIC16F84?

3. List the pseudo-code steps to enable the INT interrupt for a falling-edge input
on RB.0.

4. How does the GIE bit affect a wake-up from a SLEEP? Refer to the interrupt
logic diagram and the Microchip data sheets.

5. Explain why it is important to update the Port B input latches before enabling
the Port B change interrupt.

6. How much error does the displayed time in CLOCK.ASM have due to soft-
ware? How can it be made more accurate?

Assignment

1. Write the pseudo-code for a program which incorporates interrupts and flashes
an LED at a set rate. When a button on the keypad is pressed the flashing rate
should change to a new rate determined by the number of the key pressed.
Include the pseudo-code for the ISR.

2. Write the program outlined in 1.

3. Write the pseudo-code for a program which uses TMR0 to generate an inter-
rupt after 10 ms have elapsed.

4. Write the pseudo-code for a program which uses a transition from high to low
on the INT (PORTB.0) pin to display the text ‘INT pin interrupt’ on the LCD
display. Otherwise, the LCD should be cleared and a single LED should be
scanning across the bar graph display from PORTB.1 to PORTB.7 (PORTB.0
will be needed to generate the interrupt).

5. Write the pseudo-code for a program which accepts a 60 Hz input clock on


PORTA.4 and displays the elapsed time on the LCD in hours, minutes, sec-
onds, and tenths of seconds. When a key is pressed, generate a Port B change
interrupt. The ISR should determine which event caused the interrupt. If TMR0
generated the interrupt, the elapsed time routine should be serviced. If a key
press caused the interrupts, they key pressed should either increment or decre-
ment the hours, minutes, seconds, or tenths of seconds variables.

6. Write the programs outlined in 4 and 5.

Questions and
Assignments 112 Microchip Code ©1998 Sirius microSystems
Using the
12 LCD Display

The PIC-MDS includes an intelligent 2-line by 16-character LCD display. Intel-


ligence is provided by an on-board controller chip based on the Hitachi HD44780— LCD displays using the
a common LCD controller. The LCD controller: HD44780 controller and its
derivatives are widely
• displays ASCII characters as well as some Kanji and Greek characters available. The techniques
• can shift characters left or right on the display used in this chapter apply
to any LCD using this
• provides absolute and relative character position addressing controller family.
• has a 40 character memory for each line of the display
• supports cursor movement and appearance
• allows 8 custom characters to be programmed
• can be connected to a microcontroller using a 4-bit or 8-bit interface

Adding LCD capability to your projects is remarkably easy, once you know how
to communicate with the LCD controller. This chapter will give two examples of
using the LCD. The first program displays the ASCII character entered using the
keypad and demonstrates character positioning. The second uses custom characters
to demonstrate cursor cell animation and display scrolling.

Before we examine the code, we need to understand how the LCD is connected to
the microcontroller and the function of the internal LCD registers.

The LCD Interface


In the PIC-MDS, the LCD display is connected to both Port A and Port B of the
microcontroller (refer to the schematic segment on the next page). Port A is used to
activate the LCD control lines, and Port B connects to the LCD data lines.

As you look at the schematic, notice that the LCD data lines are shared with the
keypad (and with the LED’s—see Chapter 4). Sharing Port B like this takes advan-
tage of the PIC’s ability to easily and rapidly reconfigure ports. KEY.ASM,
KEYINT.ASM and CLOCK.ASM have all used Port B for more than one function.
Chapter 12 Using
©1998 Sirius microSystems Microchip Code 113 the LCD Display
A section of the PIC-MDS schematic showing the LCD and Keypad connections to the PIC microcontroller.

LCD Controller Commands


COMMAND RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 DESCRIPTION
Clear Display 0 0 0 0 0 0 0 0 0 1 Clears display and sends
cursor to home position.
Return Home 0 0 0 0 0 0 0 0 1 • Returns cursor to home
position, leaving characters.
Entry Mode 0 0 0 0 0 0 0 1 Inc. 0 Sets cursor increment/dec-
rement mode.
Display Cont. 0 0 0 0 0 0 1 Disp. Curs. Blink Display and cursor on/off
control, and cursor blink.
Shift Mode 0 0 0 0 0 1 D/C R/L • • Sets cursor and display
shift direction.
Function Mode 0 0 0 0 1 Data Lines Font • • Sets data width, number of
lines and character font.
CGRAM Addr. 0 0 0 1 CGRAM Address Sets character generator
MSB LSB RAM (CGRAM) address.
DDRAM Addr. 0 0 1 DDRAM Address Sets display data RAM
MSB LSB (DDRAM) address.
Read Busy 0 1 Busy RAM Address Reads LCD Busy Flag
MSB LSB

RAM Write 1 0 RAM Data Writes data to RAM


MSB LSB

RAM Read 1 1 RAM Data Reads data from RAM


MSB LSB

Inc. - Increment or decrement cursor position. 1=increment, 0=decrement


Disp. - Display On/Off control. 1=on, 0=off
Curs. - Cursor On/Off control. 1=on, 0=off
Blink - Cursor blink. 1=blinking, 0=underscore
D/C - Shift display or cursor. 1=shift display, 0=shift cursor
R/L - Right/left shift direction. 1=shift right, 0=shift left
Data - Interface data bus width. 1=8 bits, 0=4 bits
Lines - Number of display lines. 1=2 lines, 0=1 line
Font - Font select. 1=5X10 dots, 0=5X7 dots
Busy - Busy Flag. 1=busy, 0=ready
• - Not used.

This chart summarizes the LCD controller commands used by LCD.LIB, the LCD subroutine library.
The LCD Interface
114 Microchip Code ©1998 Sirius microSystems
Port A connects to the LCD control lines is as follows:
PORTA.2 LCD Enable (LCDE in LCD.LIB) LCD.LIB is the subroutine
PORTA.0 LCD Register Select (RS in the chart, and LCDRS in LCD.LIB) library that controls the
PORTA.1 LCD Read/Write (R/W in the chart, and LCDRW in LCD.LIB) LCD. Its use is described
later in this chapter.
LCD Enable
LCD Enable is an active-high input on the LCD. When low, the LCD is disabled
and all other LCD I/O lines are in the high impedance state—effectively disconnect-
ing the LCD display from the PIC. The LCD Enable line must be pulsed high in order
to write or read commands or data to the LCD. The duration of this pulse must be at
least 500 ns. The LCD_Enable routine in LCD.LIB pulses the enable line.

LCD Register Select


RS on the LCD selects either command mode (when RS=0) or character read/
write mode (when RS=1). CALL LCD_Reg is used to write commands to LCD
registers. The CALL LCD_Reg subroutine in LCD.LIB ensures that RS is low be-
fore pulsing the enable line. Similarly, CALL LCD_Data is used to write characters
to the LCD. The CALL LCD_Data subroutine in LCD.LIB sets RS high before
pulsing the enable line.

LCD Read/Write
The R/W line determines whether a read or write to the LCD takes place. If R/W
is high (R/W=1) the contents of LCD RAM will be read and if R/W is low (R/W =0)
the LCD RAM will be written. The R/W line along with the RS line must be set prior
to issuing the enable pulse.

LCD Commands
LCD.LIB has predefined command equates, shown below. These equates are
derived from the LCD Controller Commands table at left. To send a command to the
LCD, load W with the command equate and CALL LCD_Reg. LCD_Reg controls
the RS and R/W lines, and pulses the enable to complete the command.

Chapter 12 Using
©1998 Sirius microSystems Microchip Code 115 the LCD Display
LCD Initialization

If you use other types of Before the LCD can be used, the LCD controller (the HD44780 on the LCD)
LCD displays based on the must be initialized for the correct display format. We’ll configure the display on the
HD 44780 controller, or if PIC-MDS to use 8-bit data, two display lines, and a 5X7 character matrix. The
you want to use the LCD in LCDFunction equate of 38h configures the LCD for these settings. This value is
4-bit mode, you will need derived from the LCD Controller Commands chart, under the Function Mode com-
to modify the LCDFunction mand.
equate. Refer to the
LCD4BIT.LIB library file
Initialization must follow a specific order, which is shown below in pseudo-code.
for details.
Calling LCD_Init in LCD.LIB does this for you.

LCD_Init
The LCD controller is reset Send LCDFunction data (38h) to LCD
pulse the LCD enable line
in software by three wait 5 ms
successive writes of 38h.
The LCD controller should Send LCDFunction data (38h) to LCD
automatically be reset on pulse the LCD enable line
wait 5 ms
power-up. We’ve included
the software reset just in Send LCDFunction data (38h) to LCD
case the power supply rise pulse the LCD enable line
time does not meet the wait 5 ms
controller reset require- Send LCDFunction data (38h) to LCD
ments. pulse the LCD enable line
wait 5 ms
The fourth 38h sets the
Send LCDOn data (C0h) to LCD
LCD function register. The pulse the LCD enable line
next three writes turn on
the LCD display, clear the Send LCDCLR data (01h) to LCD
display, and set the cursor pulse the LCD enable line
into increment mode. The Send LCDInc data (06h) to LCD
LCD is now ready for use. Pulse the LCD enable line

Return

The first part of the LCD_Init subroutine is shown below:

We will represent called LCD_Init ;LCD initialization instructions from the Optrex data book.
library routines as greyed- ;Sets LCD functions for DMC16207 display, performs soft-
;ware reset, clears memory and turns the display on.
out text to indicate that the
code can be found in MOVLW LCDInit ;Load W with initialize LCD code
‘.LIB’ files. CALL LCD_Reg_Init ;and send it to LCD
CALL Delay_5ms ;...and wait
MOVLW LCDInit ;Load W with initialize LCD code
CALL LCD_Reg_Init ;and send it to LCD again
CALL Delay_5ms ;...and wait
MOVLW LCDInit ;Load W with initialize LCD code
CALL LCD_Reg_Init ;and send it to LCD again
CALL Delay_5ms ;...and wait
MOVLW LCDFunction ;Load W with initialize 8-bit code
CALL LCD_Reg ;and send it to LCD
CALL Delay_5ms ;...and wait
From LCD.LIB

LCD Initialization
116 Microchip Code ©1998 Sirius microSystems
;Change the constant in the next line to set how the displa
;is activated. eg. LCDOn, CursOn, CursBlink. The Constant i
;from the LCD software commands, above.

MOVLW LCDOn ;Command for display on & cursor of

CALL LCD_Reg ;Send it to LCD


MOVLW LCDCLR ;Load W with clear LCD code
CALL LCD_Reg ;and send it to LCD
MOVLW LCDInc ;Load W with increment mode code
CALL LCD_Reg ;and send it to LCD
RETURN

You may have noticed two major differences when comparing the library code
with the pseudo-code. First, the LCDInit constant is actually the same as the
LCDFunction constant. They have been equated separately so that the LCDFunction
constant can be changed for other display types without changing the initialization
code.

Next, two slightly different routines, LCD_Reg and LCD_Reg_Init, are used to
pulse the enable line of the LCD controller after writing the LCD command. LCD_Reg
checks the LCD controller’s busy flag before enabling the command write and can-
not be used during initialization. LCD_Reg_Init ignores the state of the LCD busy
flag during a software reset, blindly performing writes. After 5ms, the LCD control-
ler is ready to receive the next initialization command.

LCD Display Addressing


Each line of the LCD display has forty characters of Display Data RAM
(DDRAM) associated with it. The forty RAM locations are organized as a circular
buffer so that the last location wraps around and ends up beside the first. Of these
forty characters, sixteen are visible in the display window. Sixteen characters are
visible in a 2X16 display. If
After the LCD is initialized by calling LCD_Init, the first character that is writ- we had a 2X20 display, the
first 20 characters
ten to the LCD is placed into DDRAM at location 80h.
(DDRAM addresses 80h to
93h) would be visible.
LCD Character Position (DDRAM Address) Larger displays use the
39 40 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 same DDRAM addresses.

Visible Display Window

After writing one character, the DDRAM address increments to 81h automati-
cally, since LCD_Init sets Entry Mode to increment. Subsequent characters fill suc-
cessive locations up to A7h (the 40th position) and eventually wrap around to C0h on
the second line. Remember that display locations past 8Fh are not visible on a sixteen
character display. To make these characters visible, the display contents can be shifted
left or right. Moving the equates LCDLeft or LCDRight into W and issuing a CALL
to LCD_Reg shifts the display one position left or right. The diagram on the next
page illustrates the result of a display shift to the left.
Chapter 12 Using
©1998 Sirius microSystems Microchip Code 117 the LCD Display
LCD Character Position (DDRAM Address)
40 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Visible Display Window after Display Shift

Notice that the display shift commands shift both lines of the LCD display in the
specified direction.

Absolute Addressing
Characters can be written to specific LCD locations (DDRAM Addresses) using
the DDRAM Address command. The LCDLine1 and LCDLine2 equates incorporate
the DDRAM Address command. The default position of LCDLine1 and LCDLine2
is at the beginning of DDRAM.

By adding an offset value of between 00h and 27h to the LCDLine1 and LCDLine2
equates, characters can be placed anywhere in DDRAM. For example, to display a
character at the very last position on line 2 of the LCD, you would move the equate
A more efficient method of LCDLine2 to W, add 0Fh to W, and then issue a call to LCD_Reg.
doing this is moving the
character position—in this Relative Addressing
case CFh—directly to W
before CALLing LCD_Reg. Movements can be made to the left or right of the current cursor position using
the CURSLeft and CURSRight commands. Cursor refers to the current DDRAM
location, and can be indicated on the LCD by an underscore ‘_’ or a blinking block if
the cursor is on. Sending the CURSOn command displays the cursor as an under-
score, and sending CURSBlink activates the blinking cursor.

Cursor movement occurs regardless of whether the cursor is on, off or blinking.
Each time the CURSLeft or CURSRight command is sent, the cursor moves one
position to the left or right.

Displaying LCD Characters


The program ASCII.ASM displays the LCD character corresponding to a three
digit value (0-255) entered from the keypad. ASCII.ASM demonstrates LCD initiali-
zation, LCD command writes, LCD character writes, absolute cursor positioning
and the auto cursor increment mode.

Assemble and download ASCII.ASM can be used to view all of the characters the LCD is able to display.
ASCII.HEX to a Codes 032-127 display the standard ASCII character set, and codes from 128-255
PIC16F84. Characters show some Kanji, Greek, accents and other characters. Codes 0-7 display custom
will not display until all characters, codes 8-15 repeat the custom characters, and codes 16-31 are blank.
three digits have been
entered.
Pull ASCII.ASM from the Pull-out Program References section as we dissect it.

Displaying LCD
Characters 118 Microchip Code ©1998 Sirius microSystems
;Equates required by BIN2DEC.LIB and DEC2BIN.LIB:
Hundreds DS 1 ;Hundreds digit
Tens DS 1 ;Tens digit
Ones DS 1 ;Ones digit

;Other equates
Counter DS 1 ;LCD character counter

Counter1 DS 1 ;LCD delay counter


Counter2 DS 1 ;LCD delay counter

Key DS 1 ;Key return code variable

Digit DS 1 ;ASCII digit counter variable

Let’s begin by examining the Equates section. Hundreds, Tens, and Ones store
the three digits that make up the character code. They also happen to be the variable
names required by DEC2BIN.LIB. The subroutine Dec_Bin, in DEC2BIN.LIB, con-
verts the three decimal digits in Hundreds, Tens, and Ones to an equivalent binary
number.

Counter1 and 2 variables are used by the LCD Delay_5ms subroutine. Counter
is used to read a data table containing text for line 1. Key is used to hold the key
return code after a scan of the keypad. ASCII.ASM remaps the value in key so that
only the digits 0-9 are entered from the keypad. Digit keeps track of how many digits
of the code have been entered.

ORG 00h ;Start program at Reset Vector

CLRF Key ;Clear Key return variable


CLRF Counter1 ;and delay counters
CLRF Counter2
GOTO Initialize ;Continue with initialize routine

ORG 05h ;One location past Interrupt Vector

Include ‘DEC2BIN.LIB’ ;Decimal to Binary conversion routin


Include ‘KEYPAD.LIB’ ;Keypad scanning subroutine library
Include ‘LCD.LIB’ ;LCD subroutine library

After clearing some of the variables, GOTO Initialize jumps over the included
subroutines. Initialize continues with CLRF Digit.

Initialize ;This subroutine initializes the LCD display and writes


;a message on to line 1 and ‘=’ on to line 2. The cursor
;is turned on to indicate where input will be shown.

CLRF Digit ;Clear digit counter


CALL LCD_Port ;Set up ports for LCD use
CALL LCD_Init ;Initialize LCD and clear screen
CALL Disp_Init ;Send first line

The LCD_Port and LCD_Init subroutines are parts of LCD.LIB. LCD_Port


configures Ports A and B for use with the LCD. As seen earlier, LCD_Init initializes
the LCD (by sending the LCDFunction as outlined by the LCD_Init pseudo-code),
clears the display, resets the cursor to the home position (position 1 of line 1), and
sets cursor increment mode. Let’s take a closer look at LCD_Port.

Chapter 12 Using
©1998 Sirius microSystems Microchip Code 119 the LCD Display
LCD_Port ;Initializes the Port B tristate buffers as outputs for
;LCD data lines. Sets Port A to digital (on PIC16C71) and
;sets the LCD Register Select, Read/~Write, and Enable
;lines to outputs.

BSF RP0 ;Select memory register page 1


If you use LCD.LIB with
the PIC16C711, remove the ;the next two lines are for the PIC16C711 only and should b
semicolons from the ;removed for the PIC16F84 (PM produces an error when this
commented-out code. The ;is assembled for the ’84).
‘711 powers up with Port A ;MOVLW 03h ;1’s set Port A to digital
in analog mode. Before ;MOVWF ADCON1 ;Write W to ADCON1 (88h)
using the LCD, Port A must
be configured for digital MOVLW 11111000b ;Set lower 3 bits of RA to
ANDWF TRISA ;digital output in TRISA
output. CLRF TRISB ;Set Port B to output
BCF RP0 ;Go back to register page 0
BCF LCDE ;Keep LCD Enable line off
From LCD.LIB RETURN ;Ports are now set up for LCD

LCD_Port sets the lower three pins of Port A as outputs. ANDing the literal into
TRISA does this without disturbing the upper two pins of Port A. All of Port B is
used as outputs to send data and commands to the LCD. (Remember, a call to
LCD_Init, which we’ve already described, follows LCD_Port.)

Call Disp_Init, the last Initialize command, can now display the text ‘ASCII
Code=Char.’ on the first line of the LCD.

Disp_Init ;Writes ‘ASCII Code=Char.’ to the first line of the LCD


;display using LCD display library (LCD.LIB).

CLRF Counter ;Reset character counter


Get_Char MOVF Counter,0 ;Get character offset into W
CALL Message ;use it to get character
IORLW 00h ;RETLW won’t affect flags so use OR
BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Counter,1 ;Add 1 to Counter
GOTO Get_Char ;Do it again for the next character

Message ADDWF PCL ;Offset program counter by adding W


RETLW ‘A’ ;Message
RETLW ‘S’
RETLW ‘C’
RETLW ‘I’
RETLW ‘I’
RETLW ‘ ‘
RETLW ‘C’
RETLW ‘o’
RETLW ‘d’
RETLW ‘e’
RETLW ‘=’
RETLW ‘C’
RETLW ‘h’
RETLW ‘a’
RETLW ‘r’
RETLW ‘.’
RETLW 0 ;End of message

The Disp_Init subroutine is basically the same as Get_Char in Key.ASM (see


Chapter 10 for a more detailed explanation). The Counter variable points to the
position of the character in the Message data table. Each time the loop calls Message,
Counter offsets the Program Counter to retrieve the next character from the table.
Displaying LCD
Characters 120 Microchip Code ©1998 Sirius microSystems
RETLW returns the numeric value for the character in quotation marks in W. The
CALL LCD_Data instruction writes the character value in W to the current position
of the LCD DDRAM.

LCD_Data ;Load W with the ASCII character code to send to LCD.


;LCD_Data outputs the character to the LCD and blips
;the enable line with LCD_Enable to complete the send.

BCF LCDRS ;Enter register mode


MOVWF PORTB ;and send W to LCD on Port B
CALL LCD_Check ;Check LCD busy flag
BSF LCDRS ;Enter ASCII mode
GOTO LCD_Enable ;Send ASCII character
From LCD.LIB

LCD characters are written to the display by placing the ASCII value on Port B,
setting the LCDRS line, and pulsing the LCD enable line. Before writing a new
character, the LCD must have finished the last operation. CALL LCD_Check moni- For more detail, examine
tors the busy flag and returns when the LCD is not busy. the LCD.LIB file.

After the CALL to LCD_Data writes the character, Counter increments. If the
returned character is zero, BTFSC Z does not skip to CALL LCD_Data, but instead
returns to the calling subroutine.

Using the technique of marking the end of the message with a specific charac-
ter—zero in this case—allows this subroutine to be used for messages of varying
lengths. Zero is a good character to use as a marker since it sets the Z flag. Unfortu-
nately, RETLW does not affect any flags. Thus, the returned character is first OR’ed
with 00h because IORLW will set flags.

Send_Equals MOVLW LCDLine2 ;Load W with address of line 2 (C0h) You can’t use the name
ADDLW 0Ah ;and offset cursor to position 11 ‘Send=’ as a label, since
CALL LCD_REG ;Send cursor position to LCD
‘=’ means EQUate.
MOVLW ‘=’ ;Load W with ASCII ‘=’
CALL LCD_Data ;and send to LCD for display

The Send_Equals routine positions an equals sign at line two, position eleven.
Loading LCDLine2 loads the first DDRAM address of line two into W. Adding 0Ah
to W increases the DDRAM address in W by 10. The call to LCD_Reg moves the
cursor to DDRAM position CAh, the 11th position on the LCD.

LCD_Reg ;Load W with LCD software constant from table, above.


;LCD_Reg outputs the command to the LCD and blips the
;enable line with LCD_Enable to complete the command.

BCF LCDRS ;Enter register mode


MOVWF PORTB ;and send W to LCD reg. on Port B
CALL LCD_Check ;Check LCD busy flag
GOTO LCD_Enable ;Send register command
From LCD.LIB

LCD commands are written to the LCD by placing the command word on Port
B, clearing the LCDRS line, and pulsing the LCD enable line. Once again, CALL
LCD_Check ensures that the LCD has completed its last operation by checking the
busy flag.

Send_Equals finishes by loading W with the code for ‘=’ and the call to LCD_Data
writes this code to the current DDRAM address.
Chapter 12 Using
©1998 Sirius microSystems Microchip Code 121 the LCD Display
Set_Cursor MOVLW LCDLine2 ;Load W with address of line 2 (C0h)
ADDLW 06h ;and offset cursor to position 7

CALL LCD_REG ;Send cursor position to LCD

Cursor_On MOVLW CursOn ;Load W with cursor on command (0Eh)


CALL LCD_REG ;and send to LCD

CALL KB_Port ;Configures Port B for keypad

Set_Cursor moves the current DDRAM address to position 7 of line 2 in the


same way the ‘=’ sign DDRAM address was set.

Cursor_On turns on the underscore cursor by loading the CursOn equate into W
and sending it to the LCD through the call to LCD_Reg. An underscore cursor is the
default cursor used by LCD.LIB. To use the blinking cursor, replace CursOn with
the equate CursBlink.

After setting up the LCD, KB_Port is called to reconfigure the I/O ports for the
keypad.

Get_Key CALL KB_Scan ;Get Key return code


MOVF Key,0 ;Check Key return code
BTFSC Z ;for no key press (0=no key)
GOTO Get_Key ;If no key pressed, try again

CALL Delay_5ms ;Wait for key to settle


CALL Delay_5ms
CALL Delay_5ms
CALL Delay_5ms

CALL KB_Scan ;Read Key code after settling


MOVF Key,0 ;Read Key code into W
CALL Key_Remap ;and Remap key codes
MOVWF Key ;Save new Key code to key

The Main program routine retrieves and debounces keystrokes. The call to
KB_Scan returns a value in Key. If Key equals zero, no key has been pressed, and
GOTO Get_Key executes forming a wait loop.

Once a key has been pressed, Get_Key calls Delay_5ms four times to provide a
20 ms debounce delay. LCD.LIB requires a 5 ms delay routine called Delay_5ms
anyway, and calling it four times provides 20 ms for the key switch contacts to settle.
After the delay, KB_Scan is called again to obtain the now stable key return code.
The Key code is loaded into W for remapping by the Key_Remap subroutine.

Remember, KEYPAD.LIB The reason for remapping the keypad is that a zero key value is needed. Keys are
provides key codes from 1 easily remapped using a ROM data table. Remapping also eliminates key boundary
to 16, and a key code of 0
indicates that no keys are ; Old key from KB_Scan gets remapped to new key values:
pressed. ; +----+----+----+----+ +----+----+----+----+
; | 1 | 2 | 3 | 4 | | 1 | 2 | 3 | 0 |
; +----+----+----+----+ +----+----+----+----+
; | 5 | 6 | 7 | 8 | | 4 | 5 | 6 | 0 |
; +----+----+----+----+ ----> +----+----+----+----+
; | 9 | 10 | 11 | 12 | | 7 | 8 | 9 | 0 |
; +----+----+----+----+ +----+----+----+----+
; | 13 | 14 | 15 | 16 | | 0 | 0 | 0 | 0 |
; +----+----+----+----+ +----+----+----+----+
Displaying LCD
Characters 122 Microchip Code ©1998 Sirius microSystems
checking in the program. The key values returned from the Key_Remap routine can
be directly input into the Hundreds, Tens and Ones variables without modification.

Key_Remap ADDWF PCL ;Use old Key to offset PC The NOP instruction is
NOP ;No Key=0 code
RETLW 1 ;old key 1 remapped to new key 1
occupies the memory
RETLW 2 ;old key 2 remapped to new key 2 location that represents the
RETLW 3 ;old key 3 remapped to new key 3 result of adding 0 (from W)
RETLW 0 ;old key 4 remapped to new key 0 to PCL. Since W will be a
RETLW 4 ;old key 5 remapped to new key 4
RETLW 5 ;old key 6 remapped to new key 5
value from 1 to 16, the
RETLW 6 ;old key 7 remapped to new key 6 NOP is needed to offset the
RETLW 0 ;old key 8 remapped to new key 0 data table.
RETLW 7 ;old key 9 remapped to new key 7
RETLW 8 ;old key 10 remapped to new key 8
RETLW 9 ;old key 11 remapped to new key 9
RETLW 0 ;old key 12 remapped to new key 0
RETLW 0 ;old key 13 remapped to new key 0
RETLW 0 ;old key 14 remapped to new key 0
RETLW 0 ;old key 15 remapped to new key 0
RETLW 0 ;old key 16 remapped to new key 0

The Key_Remap data table works similarly to the Message data table. Note the
NOP as the first entry. Even though a zero key value would never be passed to
Key_Remap, we must account for a zero offset here so that the other Key values
remap properly.

MOVF Digit,0 ;Get digit count in W This jump table is similar


ADDWF PCL ;and offset PC with digit to the Case command in
GOTO Digit1 ;First time through, write Hundreds
GOTO Digit2 ;next, Tens some programming lan-
GOTO Digit3 ;then, Ones guages.

When the first key is returned, Digit contains the value zero. The Digit value is
loaded into W for use in a jump table. A jump table is similar to a data table except
that instead of returning a value, it executes a GOTO based on the value in W. Since
W is zero the first time this table executes, the PIC will be redirected to the Digit1
subroutine by the first GOTO.

Digit1 CALL LCD_Port ;Configure Ports for LCD


MOVF Key,0 ;Get Key return code
MOVWF Hundreds ;and store in Hundreds variable
ADDLW 30h ;Convert Key to ASCII
CALL LCD_Data ;and display on LCD
INCF Digit ;Add one to digit counter
GOTO Release ;Wait for user to release key

Digit2 CALL LCD_Port ;Configure Ports for LCD


MOVF Key,0 ;Get Key return code
MOVWF Tens ;and store in Tens variable
ADDLW 30h ;Convert Key to ASCII
CALL LCD_Data ;and display on LCD
INCF Digit ;Add one to digit counter
GOTO Release ;Wait for user to release key

Digit1 and Digit2 are similar in function. They reconfigure the PIC I/O ports for
the LCD, retrieve the Key value in order to save it in Hundred or Tens, and change
the Key value to its ASCII equivalent by adding 30h to it. CALL LCD_Data then
displays this ASCII digit and moves the cursor to the next DDRAM address. After
incrementing the Digit counter, GOTO Release waits for the key to be released.
Chapter 12 Using
©1998 Sirius microSystems Microchip Code 123 the LCD Display
Release ;This is the opposite of the first key check. It waits for
;the Key code to be zero and pauses for the debounce delay.

CALL KB_Port ;Set Port B for keypad use


Wait CALL KB_Scan ;Scan keypad
MOVF Key,0 ;Check key for 0
BTFSS Z ;And if Z=1 key has bee released
GOTO Wait ;Otherwise, wait for release
CALL Delay_5ms ;Wait for key to settle
CALL Delay_5ms
CALL Delay_5ms
CALL Delay_5ms
GOTO Main ;Get next digit

The Release subroutine reconfigures the I/O ports for keypad scanning before
performing a key scan. While a key is being pressed, the GOTO Wait line executes.
When the key is released, another 20 ms debounce delay occurs. Without this delay,
a key bounce on release would be interpreted as the next keystroke entered by the
program.

Now that the first digit has been retrieved, stored in the Hundreds variable, and
displayed on the LCD, GOTO Main starts the process again for the second digit.

The second digit is processed similarly, except that it is stored in the Tens vari-
able. After returning to Main for the third digit, the Digit3 subroutine executes.

Digit3 CALL LCD_Port ;Configure Ports for LCD


MOVF Key,0 ;Get Key return code
MOVWF Ones ;and store in Ones variable
ADDLW 30h ;Convert Key to ASCII
CALL LCD_Data ;and display on LCD

Move_Cursor MOVLW LCDLine2 ;Load W with address of line 2 (C0h)


ADDLW 0Ch ;and offset cursor to position 13

CALL LCD_REG ;Send cursor position to LCD

CALL Dec_Bin ;Converts Hundreds, Tens Ones to bin


CALL LCD_Data ;and display on LCD

CLRF Digit ;Reset digit counter

Reset_Cursor MOVLW LCDLine2 ;Load W with address of line 2 (C0h)


ADDLW 06h ;and offset cursor to position 7

CALL LCD_REG ;Send cursor position to LCD

The third digit is saved to the Ones variable and is displayed on the LCD in the
same way as the first and second digits were. The Move_Cursor subroutine moves
the DDRAM address to point to position 13 on line 2 of the LCD so that the charac-
ter just entered can be displayed on the opposite side of the ‘=’ sign.

When Dec_Bin is called, the binary digit values stored in Hundreds, Tens and
Ones are converted into a single binary number which is returned in W. The call to
LCD_Data displays the this character represented by this number on the LCD.

Before exiting the Digit3 routine, the Digit counter is reset and the cursor is
repositioned to the DDRAM address C6h (the Hundreds digit location). After Digit3
finishes, execution falls through to the Release subroutine. After debouncing, execu-
tion returns to Main so the next character code can be entered.

124 Microchip Code ©1998 Sirius microSystems


Creating Custom Characters
We now know how to display any of the ASCII, Kanji or Greek characters on the
LCD. There are times, however, when other special characters are needed.
CUSTOM.ASM demonstrates how to create custom characters, perform single char-
acter cell animation, and scroll messages.

First, assemble and download CUSTOM.ASM to a PIC16F84. Once you see


what it does, we’ll look at how custom characters are programmed.

CGRAM
ASCII data values 0-7 display custom characters defined in the CGRAM ad-
dresses. CGRAM is used to store custom generated characters. You can program a
total of eight custom characters.

There are actually 64 CGRAM locations. Each custom character is stored in


eight successive CGRAM locations. A CGRAM address command is made up of
three fields as shown in the CGRAM Custom Character Programming diagram.

The first field (bits 7 and 6) contains 01 to denote the CGRAM addressing com- Refer back to the LCD
mand mode. CGRAM address bits 5, 4 and 3 designate the ASCII character code Controller Commands
being programmed. These three bits accommodate the definitions for eight character chart to see why bits seven
codes (000-111). Finally, CGRAM address bits 2, 1 and 0 specify one of the eight and six are 0 and 1.
rows of the character being defined (Character Row Select bits).

At each CGRAM address, data


CGRAM Custom Character Programming corresponding to one line of the cus-
CGRAM Address bits CGRAM Data bits tom character must be stored. The
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
character chart at left shows how char-
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 1
acter 0 (Truck1) in the program is de-
0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 1 fined.
0 1 0 0 0 0 1 1 0 0 0 0 1 1 1 1
0 1 0 0 0 1 0 0 0 0 0 0 1 1 1 1 Each character is a 5X8 cell. The
0 1 0 0 0 1 0 1 0 0 0 1 1 0 1 0 Character Row Select bits are used to
0 1 0 0 0 1 1 0 0 0 0 0 0 1 1 1 select the row being defined. The data
0 1 0 0 0 1 1 1 0 0 0 0 0 0 1 0
based on the character bitmap must
CGRAM ASCII Char. Character
be written to the CGRAM address for
Address Char. Row Bitmap each row. In pseudo-code, this char-
Mode Code Select
acter would be programmed as shown:

Load W with LCDCGRAM (CGRAM starting address - 01000000b) In CUSTOM.ASM, this


CALL LCD_Reg to write CGRAM address to LCD procedure is accomplished
Load W with character data for row 1 (00000000b) using a ROM data lookup
CALL LCD_Data to write data to CGRAM address 01000000b table. Like DDRAM,
CGRAM addresses auto-
Load W with character data for row 2 (00000011b) matically increment after
CALL LCD_Data to write data to CGRAM address 01000001b
. CGRAM is written. As
. character rows are written,
. CGRAM increments into
Load W with character data for row 8 (00000010b) the next character.
CALL LCD_Data to write data to CGRAM address 01000111b

Chapter 12 Using
©1998 Sirius microSystems Microchip Code 125 the LCD Display
Pull-out and refer to the CUSTOM.ASM program as we describe it.

Initialize ;This subroutine initializes the LCD display and programs


;the custom characters by calling Prog_Character.

CALL LCD_Port ;Set up ports for LCD use


CALL LCD_Init ;Initialize LCD and clear screen
CALL Prog_Character ;Load LCD with custom characters

After the ports have been configured for LCD use and the LCD has been initial-
ized, Prog_Character is called to program the custom characters.

Prog_Character ;Loads the custom character data into the LCD Character
;Generator RAM. CGRAM is ASCII characters 0-7. Each charact
;is loaded as a bit-map, one line at a time. The cursor
;auto-increments to the next CGRAM location after each
;write.

MOVLW LCDCGRAM ;Send LCD CGRAM address (40h) to


CALL LCD_REG ;LCD as a command
CLRF Counter ;Reset character counter
Get_Char MOVF Counter,0 ;Get character offset into W
CALL Characters ;use it to get character data
CALL LCD_Data ;If not done, send character to LCD
INCF Counter,1 ;Add 1 to Counter
MOVLW 64 ;Load W with number of char. bytes
SUBWF Counter,0 ;and compare with Counter
BTFSC Z ;by checking Z flag
RETURN ;If Counter=64, we’re done
GOTO Get_Char ;Do it again for the next character

Characters ADDWF PCL ;Offset PC with Counter in W

Truck1 RETLW 00000000b ;Row 1, ASCII character 00


RETLW 00000011b ;Row 2, ASCII character 00
RETLW 00000011b ;Row 3, ASCII character 00
RETLW 00001111b ;etc.
RETLW 00001111b
RETLW 00011010b
RETLW 00000111b
RETLW 00000010b

Truck2 RETLW 00001111b ;Row 1, ASCII character 01


RETLW 00001111b ;Row 2, ASCII character 01
RETLW 00001111b ;etc.
RETLW 00001111b
.
.
.
Man4 RETLW 00000000b ;Row 1, ASCII character 07
RETLW 00000000b ;Row 2, ASCII character 07
RETLW 00000001b
RETLW 00000011b
RETLW 00000001b
RETLW 00000011b
RETLW 00000001b
RETLW 00000000b ;Row 8, ASCII character 07

MOVLW LCDCGRAM and CALL LCD_Reg set the LCD to the first CGRAM
address. The Counter variable is used to point to and return the custom character row
data from the ROM data table.

CALL Characters and CALL LCD_Data retrieves the current row data from the
data table and writes it to CGRAM. CGRAM automatically increments to the next
address. Counter is incremented by INCF and is used to determine when the end of
Creating Custom
Characters 126 Microchip Code ©1998 Sirius microSystems
CGRAM data has been reached, as well as to point to the next row data in the data
table.

MOVLW 64 loads W with the number of CGRAM addresses to be programmed. 64 is the number of charac-
SUBWF Counter,0 subtracts W from Counter, leaving Counter unchanged. If the ter rows in the data table.
result is zero, Counter equals 64 and CGRAM is programmed. Otherwise, BTFSC Z
skips the RETURN and the next character is programmed into CGRAM.

MOVLW LCDLine1 ;Load W with Line 1 address


MOVWF Position ;Save W in Position register
CALL LCD_REG ;and send to LCD as command
MOVLW 04h ;Load W with Man1 Character code
MOVWF Counter ;and save in LCD character counter

Walk ;Makes a little man walk across the screen by successively


;writing each of the 4 Man characters into the same cursor
;position and then moving the cursor 1 position to the
;right before repeating.

MOVF Counter,0 ;Get current Man Character


CALL LCD_Data ;and send to LCD
MOVLW CursLeft ;Load W with Cursor Left shift
CALL LCD_Reg ;command and send to LCD
CALL Delay ;Wait a bit
INCF Counter ;Increment to next Man Character
MOVLW 08h ;Load W with number of last Man
SUBWF Counter,0 ;and check for last count
BTFSS Z ;by checking Z
GOTO Walk ;If not at last Man, display next ma

MOVLW ‘ ’ ;If at last Man, Load W with ‘ ‘


CALL LCD_Data ;to clear character
INCF Position ;Increment cursor position variable
MOVLW 04h ;Load W with Man1 Character
MOVWF Counter ;and save to character counter
MOVLW 90h ;Load W with last visible position
SUBWF Position,0 ;and compare with Position
BTFSS Z ;by checking Z
GOTO Walk ;If not at last position, do it agai

CALL Delay ;If done, wait before rolling Truck

After the Prog_Character routine completes, both W and the Position variable
are set to 80h by the LCDLine1 equate. Position is used to keep track of the DDRAM
address—the character position of the man on the display. Calling LCD_Reg sets the
LCD to line 1, position 1. Then the ASCII value of the first Man character (04h) is The Man 1-4 characters
loaded into the Counter variable. have been programmed as
ASCII characters 4-7.
The Walk routine successively writes each of the four Man characters into one
DDRAM address to create an animation. Then, the current DDRAM address is cleared
and the four Man characters are written to the next DDRAM address. The result is
the appearance of motion within each character position, and also across the LCD.

MOVF Counter,0 and CALL LCD_Data move the ASCII code of the current
Man character to the LCD display. MOVLW CursLeft and CALL LCD_Reg move
the cursor back to the last DDRAM address so the next Man character can overwrite
the first. A nested delay loop is used to keep the current Man character on the display
long enough for you to see it.

Chapter 12 Using
©1998 Sirius microSystems Microchip Code 127 the LCD Display
Next, Counter is incremented and compared with 08h. If Counter is not equal to
08h, the four Man characters have not been displayed and the GOTO Walk is ex-
ecuted. If Counter equals 08h, all four Man characters have been displayed, and the
current position must be cleared.

MOVLW ‘ ’ and CALL LCD_Data write a space character to clear the cell
address. MOVLW 04h and MOVWF Counter reset Counter to ASCII code 04h—
the first Man character.

INCF Position updates the position counter in preparation for a check to see if
the end of the LCD screen has been reached. While Position is less than 90h, the
GOTO Walk command executes, continuing the loop that displays the four Man
characters in the next DDRAM cell. When Position reaches 90h, the Man has reached
the end of the screen and a short delay occurs before the Roll routine executes.

Roll ;Scrolls a Truck back across the screen continuously by


;writing the 4 Truck characters off the screen (cursor was
;left at position 90h by Walk) and then scrolling the
;screen to the left. Since the display was cleared earlier
;you will see only the Truck. The line length is 40 chars.
;Every 40 display shifts, the Truck comes around again.
The :Next loop could have CLRF Counter ;Clear character counter variable
been replaced by four :Next MOVF Counter,0 ;Load W with counter
independent MOVLW and CALL LCD_Data ;and send character to LCD
CALL LCD_Data opera- INCF Counter ;Increment Counter register
MOVLW 04h ;Load W with number of Truck chars.
tions. This would have SUBWF Counter,0 ;and compare with counter
taken about the same BTFSS Z ;by checking Z
amount of PIC program GOTO :Next ;If not done, send next Truck char.
memory.
:Loop MOVLW LCDLeft ;If done, load W with LCD shift left
CALL LCD_Reg ;command and send to LCD
CALL Delay ;Wait a bit
GOTO :Loop ;Keep scrolling the display

In Roll, the LCDLeft command is used to scroll the entire DDRAM contents
from right to left generating the illusion of motion. Also of note is that the Truck
characters are written off the visible display screen (locations 90h to 93h) and are
scrolled into the visible window. Since DDRAM is configured in a circular fashion,
the Truck drives by every forty display shifts.

The Counter variable is used to hold the ASCII character code to be displayed.
Counter is cleared to start at ASCII character 00h—the front of the Truck from the
CGRAM Custom Character Programming chart. The ASCII code is moved into W
The Walk routine exits and CALL LCD_Data places the first Truck character at the current DDRAM loca-
when the DDRAM address tion (90h from the end of the Walk subroutine). The LCD DDRAM pointer auto-
increments to 90h. matically increments to the next address. Counter is incremented and checked before
the next ASCII character, Truck2, is written to DDRAM.

After all four Truck characters have been written to DDRAM, the :Loop subrou-
tine shifts the DDRAM contents left by writing the LCDLeft equate as a command.
A nested delay loop separates successive shifts and completes the illusion of motion.

Notice the colon (:) in front of the :Loop label. The colon denotes that :Loop is a
local label. Both this :Loop and :Next belong to the Roll routine.

128 Microchip Code ©1998 Sirius microSystems


Delay ;Delay between Man & Truck movements

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;256 more times
RETURN

Delay_5ms ;Delay loop used to initialize LCD

CLRF Counter1 ;Wipe first counter


MOVLW 1Ah ;Load W with timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;from constant, above
RETURN

The Delay and Delay_5ms subroutines also include :Loop labels. The PM as-
sembler associates each :Loop label with the routine in which it resides. You can re- Not all assemblers support
local labels.
use local label names, and as long as they are placed in separate routines, they won’t
be mistaken for one another when they are called.

Chapter Summary
LCDs have a number of features dependent on their internal controller. In order
to use LCDs you need to know the commands necessary to operate the LCD control-
ler.

In the PIC-MDS, three Port A lines connect to the LCD control lines. Port B
connects to the LCD data bus. LCD.LIB contains the subroutines which configure
the ports, intitialize the display, and write commands and data to the LCD.

The LCD displays a window of 16 characters in a 40 character long circular


buffer. This DDRAM buffer is addressable and can be shifted left or right to provide
text scrolling.

Eight custom characters can be programmed into the LCD CGRAM.

Chapter 12 Using
©1998 Sirius microSystems Microchip Code 129 the LCD Display
Questions
1. What is the difference between absolute and relative character addressing?

2. How many custom characters can be programmed into the LCD CGRAM?

3. Describe the function of the three LCD control signals.

4. How is it possible for the LCD to share Port B with the keypad and LEDs?

Assignment
1. Read the LCD.LIB include file and describe the function of each subroutine.

2. In pseudo-code, list the steps required to display the words ‘Hello World!’ on
the LCD.

3. Modify the program ASCII.ASM so that one key backs the cursor up by one
position to fix entry mistakes.

4. Modify ASCII.ASM to be a decimal to binary conversion calculator. Instead


of displaying the ASCII character equivalent to the digits entered, display the
binary equivalent of the three digits. eg. entering 142 displays 10001110

5. Write a program that scrolls a message across the LCD display.

6. Program a set of custom characters to provide a vertical bargraph display in


one character position of the LCD. For testing, entering the numbers 1-8 on the
keypad should indicate eight different levels on the bar graph.

After you have read and fully


understood this entire chapter,
you’ll find your brain has ex-
panded to approximately five
times its normal size.

130 Microchip Code ©1998 Sirius microSystems


Using the PIC16F84
13 Data EEPROM

One of the unique features of the PIC16F84 is its internal data EEPROM. The
64 bytes of EEPROM can be used to store data that must be retained while power is
off such as passwords, operating defaults, tuning parameters or current operating
modes. In contrast, the RAM registers lose their contents when power is off.

For example, a PIC16F84 can be used to replace the mechanical timer in a wash-
ing machine. During the operation of the washing machine, the data EEPROM can
be programmed with the current operating cycle: wash, rinse or spin. If power fails
during the rinse cycle, the PIC16F84 in the washing machine will know enough to
continue the rinse cycle when power returns, closely emulating a mechanical timer.

Using the PIC16F84 Data EEPROM


The PIC16F84 data EEPROM is not accessed in the same way as a file register.
Instead, four file registers—EEDATA (08h), EEADR (09h), EECON1 (88h) and
EECON2 (89h)—control access to the EEPROM.

EEADR is the data EEPROM address pointer and holds a value representing
one of the sixty-four possible storage location addresses. EECON1 contains flags

These four file registers


control access to the data
EEPROM, here.

Chapter 13
©1998 Sirius microSystems Microchip Code 131 Using the PIC16F84
Data EEPROM
that control EEPROM reads (RD) and writes (WR), along with the write enable
(WREN), write error (WRERR), and interrupt flag (EEIF) bits. EEDATA contains
the data to be written to, or the data previously read from the EEPROM address
pointed to by EEADR. EECON2 is used during EEPROM writes.

When the PIC16F84 is first powered up, the WREN bit is cleared, disabling
writes to data EEPROM. The WREN bit must be set before EEPROM writes can
EEPROM.LIB takes care of place. This protects the EEPROM contents during power up. To safeguard your data
all of these details. from unwanted changes during a power down, brown-out or software failure, clear
the WREN bit after storing your data. EEPROM writes also require that a specific
sequence of bytes is written into EECON2 (see page 34 of the PIC16F8X data sheets).

EEPROM writes typically take 10 ms—or 25,000 processor cycles at 10 MHz.


Writing successive values into the data EEPROM requires that you either poll the
EEIF or WR bits, or use interrupts in your EEPROM write routine.

Reading From and Writing To the Data EEPROM


The program NVMEM.ASM displays the contents of the first four data EEPROM
locations and prompts the user to enter a four-digit code. This code is stored in the
first four data EEPROM locations before a power down message appears on the
LCD display. After removing and reapplying power the program runs again, display-
ing the previously entered four-digits. NVMEM.ASM demonstrates how values can
be saved and restored despite power interruptions.

Pull NVMEM.ASM and EEPROM.LIB from the Program References section.

;Hardware Equates

ORG 0Ch ;Start of File register area

Counter DS 1 ;LCD character counter

Counter1 DS 1 ;LCD delay counter


Counter2 DS 1 ;LCD delay counter

Key DS 1 ;Key return code variable

The Counter variable contains the offset used to retrieve characters from the data
tables in the Disp_Line1, Disp_Line2 and Disp_Done subroutines. Counter1 and
Counter2 are used in the 5 ms delay loop required by LCD.LIB. The Key variable
contains the key return code used by KEYPAD.LIB.

Include ‘EEPROM.LIB’ ;EEPROM subroutine library


Include ‘KEYPAD.LIB’ ;Keypad scanning subroutine library
Include ‘LCD.LIB’ ;LCD subroutine library

After initializing the Key and Counter variables and resetting the program Ori-
gin to 0005h, the EEPROM, KEYPAD and LCD libraries are included.
Reading From and
Writing To the Data 132 Microchip Code ©1998 Sirius microSystems
EEPROM
Initialize ;This subroutine initializes the LCD display and writes
;a message on to line 1 and ‘=’ on to line 2. The cursor
;is turned on to indicate where input will be shown.

CALL LCD_Port ;Set up ports for LCD use


CALL LCD_Init ;Initialize LCD and clear screen
CALL Disp_Line1 ;Send first line message to LCD

Program initialization continues by calling the subroutines necessary to initialize


the LCD. Disp_Line1 displays the message “Old Data: ” on line one of the LCD.

Disp_Line1 ;Writes ‘Old Data: ‘ to the first line of the LCD


;display using LCD display library (LCD.LIB).

CLRF Counter ;Reset character counter


:Get_Char MOVF Counter,0 ;Get character offset into W
CALL Message1 ;use it to get character
IORLW 00h ;RETLW won’t affect flags, use OR to
BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Counter,1 ;Add 1 to Counter
GOTO :Get_Char ;Do it again for the next character

Message1 ADDWF PCL ;Offset program counter by adding W


RETLW ‘O’ ;Message1
RETLW ‘l’
RETLW ‘d’
RETLW ‘ ‘
RETLW ‘D’
RETLW ‘a’
RETLW ‘t’
RETLW ‘a’
RETLW ‘:’
RETLW ‘ ‘
RETLW 0 ;End of message

Disp_Line1 retrieves characters stored in the program memory by using a data


table read. The Counter variable holds the character offset for the Message1 data
table. The :Get_Char loop retreives one character at a time from Message1, sends the This structure is introduced
character to the LCD for display, and increments the Counter variable before retriev- and described in detail in
ing the next character. The loop exits with a RETURN when a “0” is read from the Chapter 10.
data table.

Send_Old ;Reads EEPROM addresses 0-3 and writes the contents to the
;LCD display.

CLRF EEADR ;Select EEPROM address 00


:Loop CALL EE_Read ;Call EE_Read to place data into
MOVF EEDATA,0 ;EEDATA, and read EEDATA into W
CALL LCD_Data ;Copy W to LCD DDRAM
INCF EEADR ;Increment to next EEPROM address
MOVLW 04h ;Load W with number of data bytes
SUBWF EEADR,0 ;and compare with EEADR
BTFSS Z ;by checking Z
GOTO :Loop ;If not at EEADR 04, get next data

Line2 MOVLW LCDLine2 ;Load W with line 2 DDRAM address


CALL LCD_Reg ;and write to LCD
CALL Disp_Line2 ;Send second line message to LCD

The Send_Old routine reads the data from the first four EEPROM addresses.
The ASCII characters equal to each data value are displayed. If the EEPROM in the
Chapter 13
©1998 Sirius microSystems Microchip Code 133 Using the PIC16F84
Data EEPROM
All new PIC16F84 proces- PIC16F84 has never been programmed, you will likely see four blocks which repre-
sors have FFh in the sent the character equal to the value 255. CLRF EEADR resets the EEPROM ad-
EEPROM. The assembler dress pointer to 00h. CALL EE_READ reads the contents of the location specified
can set the contents of the by EEADR and copies the contents into EEDATA.
EEPROM at programming
time. See Appendix C for
information. EE_Read ;Sets the RD bit in EECON1 to read the contents of EEADR
;into EEDATA.

BSF RP0 ;Select memory register page 1


BSF RD ;Set the EECON1.RD bit to read
BCF RP0 ;Return to memory register page 0
RETURN
From EEPROM.LIB

Reading data from the EEPROM requires that EEADR contains the address to
be read and is completed by setting the RD bit in EECON1. The contents of the
EEPROM location are transferred to the EEDATA register and can be read by the
next program instruction. The PIC16F84 automatically clears the RD bit in prepara-
tion for the next read.

Following the RETURN in EE_Read, MOVF EEDATA,0 transfers the data read
from the EEPROM into W so that CALL LCD_Data can display a character equal
to its ASCII value. EEADR is then incremented and compared with 04h, causing the
first four locations (00h to 03h) to be read. If EEADR is less than 04h, the result of
the SUBWF EEADR,0 instruction is not zero and the BTFSS Z does not skip the
GOTO :Loop. Therefore, while EEADR equals 0, 1, 2 or 3, the GOTO :Loop in-
struction executes and the value returned in EEDATA is displayed. After the four
locations have been displayed, the Line2 routine displays the message “New Data: ”
on the second line of the LCD.

The Disp_Line2 subroutine is a copy of the Disp_Line1 subroutine, but uses the
Message2 data table.

MOVLW CursOn ;Load W with Cursor On command


CALL LCD_Reg ;and write to LCD

Get_New ;Wait for key presses and after a debounce delay stores th
;ASCII value of the current key codes in EEPROM memory fro
;address 0-3.

CLRF EEADR ;Reset EEADR to the beginning


CALL KB_Port ;Configure Port B for keypad

Get_Key CALL KB_Scan ;Get Key return code


MOVF Key,0 ;Check Key return code
BTFSC Z ;for no key press (0=no key)
GOTO Get_Key ;If no key pressed, try again
CALL Delay_5ms ;Wait for key to settle
CALL Delay_5ms
CALL Delay_5ms
CALL Delay_5ms

CALL KB_Scan ;Read Key code after settling


MOVF Key,0 ;Read Key code into W
CALL Key_Remap ;and Remap key codes

After the message “New Data: ” has been displayed, the cursor is turned on by
the MOVLW CursOn and CALL LCD_Reg instructions. The CursOn command
activates the underscore cursor at the current CGRAM address—which is always

Reading From and


Writing To the Data 134 Microchip Code ©1998 Sirius microSystems
EEPROM
the address after the last character written. In this case, the cursor appears in the
second space after the colon, since the last character of the message is a space.

CLRF EEADR resets the EEPROM address pointer to zero in preparation for
entering and storing the four new character values. CALL KB_Port prepares Port B
for the matrix keypad and CALL KB_Scan returns the key code in Key.

MOVF Key,0 transfers the key code to W and updates the Z flag. If the value of
Key is zero, the BTFSC Z instruction does not skip the GOTO Get_Key instruction
and the process loops until a key is pressed.

When a key is pressed, the four CALL Delay_5ms instructions provide a 20 ms


delay for the key to settle so it is not bouncing when read the second time. Instead of
writing a 20 ms delay routine, we chose to call the Delay_5ms routine required by
LCD.LIB four times.

Once the key has settled, it is re-read and remapped to an ASCII value by the
Key_Remap subroutine.

Key_Remap ;Changes key codes into ASCII values.

ADDWF PCL ;Use old Key to offset PC


NOP ;No Key=0 code
RETLW 30h ;key 1 remapped to ASCII 30h ‘0’
RETLW 31h ;key 2 remapped to ASCII 31h ‘1’
RETLW 32h ;key 3 remapped to ASCII 32h ‘2’
RETLW 33h ;key 4 remapped to ASCII 33h ‘3’
RETLW 34h ;key 5 remapped to ASCII 34h ‘4’
RETLW 35h ;key 6 remapped to ASCII 35h ‘5’
RETLW 36h ;key 7 remapped to ASCII 36h ‘6’
RETLW 37h ;key 8 remapped to ASCII 37h ‘7’
RETLW 38h ;key 9 remapped to ASCII 38h ‘8’
RETLW 39h ;key 10 remapped to ASCII 39h ‘9’
RETLW 41h ;key 11 remapped to ASCII 41h ‘A’
RETLW 42h ;key 12 remapped to ASCII 42h ‘B’
RETLW 43h ;key 13 remapped to ASCII 43h ‘C’
RETLW 44h ;key 14 remapped to ASCII 44h ‘D’
RETLW 45h ;key 15 remapped to ASCII 45h ‘E’
RETLW 46h ;key 16 remapped to ASCII 46h ‘F’

The Key_Remap subroutine is a data table that changes keycodes to ASCII Key remapping is ex-
values before they are stored in the EEPROM. This way, the EEPROM holds data plained in more detail in
that can be immediately displayed on the LCD without requiring conversion. the ASCII.ASM program
found in Chapter 12.
MOVWF EEDATA ;Save new Key code in EEDATA
CALL EE_Write ;Write key data to current EEADR
CALL EE_Wait ;and wait for write to finish

CALL EE_Read ;Read current EEADR to check


;that EEDATA was written properly

CALL LCD_Port ;Configure Ports for LCD


MOVF EEDATA,0 ;Get saved Key code from EEPROM
CALL LCD_Data ;and display on LCD

The remapped key value is stored in the EEDATA register by MOVWF EEDATA.
The CALL to EE_WRITE stores the contents of the EEDATA register into the
EEPROM location pointed to by EEADR. The first time through, EEADR will be
00h since it was cleared at the start of the Get_New routine.
Chapter 13
©1998 Sirius microSystems Microchip Code 135 Using the PIC16F84
Data EEPROM
EE_Write ;Writes the contents of EEDATA to EEADR as specified in
;the PIC16F84 data sheets after enabling WREN. After
;writing the data, WREN is cleared, disabling accidental
;writes.

BSF RP0 ;Select memory register page 1


BSF WREN ;Enable EEPROM writes
MOVLW 55h
MOVWF EECON2 ;Write 55h to EECON2
MOVLW 0AAh
MOVWF EECON2 ;Write AAh to EECON2
BSF WR ;Set EECON1.WR bit
BCF WREN ;Disable any further writes
BCF RP0 ;Return to memory register page 0
RETURN
From EEPROM.LIB

EE_Write must first enable EEPROM writes by setting the WREN (WRite
ENable) bit. The contents of EEDATA will be written into the EEPROM address
specified by EEADR by setting the WR (WRite) bit . On power-up, the WREN bit is
cleared, preventing unwanted EEPROM writes.

However, before the WR bit can be set—to write EEDATA into the EEPROM—
a unique pattern of bits must be written to EECON2. See page 34 of the PIC16F8X
data sheets for more detail. Following this peculiar initialization of writing 55h and
0AAh to EECON2, BSF WR initiates the internal PIC16F84 write sequence. The
write sequence can take up to 10 ms to complete. When the internal sequence is
complete, the contents of EEDATA have been transferred to the address in EEADR,
and the PIC clears the WR bit and sets the EEIF bit.

After initiating the write using BSF WR, BCF WREN disables further EEPROM
writes, safeguarding the data from being overwritten by program errors, brown-outs
or erratic behaviour on power-down. Even though the write sequence initiated by
BSF WR may not be complete, it is safe to disable further EEPROM writes.

Since the RETURN from EE_Write occurs before the internal EEPROM write
sequence is complete, subsequent EEPROM writes cannot occur until the previous
write has finished. A wait loop is provided by EE_Wait.

EE_Wait ;Wait for an EE_Write to finish by checking the EEIF


;flag bit in EECON1.

BSF RP0 ;Select memory register page 1


:Wait BTFSS EEIF ;Check EEIF for a high (1=finished)
GOTO :Wait ;If low, wait for EEIF to go high
BCF EEIF ;Clear EEIF after write is done
BCF RP0 ;Return to memory register page 0
From EEPROM.LIB RETURN

The completion of an EEPROM write is indicated by the PIC clearing WR and


setting EEIF. EE_Wait monitors the EEIF interrupt flag bit. Before the next write
can take place, the EEIF flag must be reset by software. A program could also moni-
tor the WR bit, since the WR bit is cleared automatically after the write sequence
finishes.

Following the RETURN from EE_Wait, the CALL to EE_Read retreives the
recently written data from the EEPROM to verify that the value of the key press is
stored properly. Although the program does no real checking, reading back the
Reading From and
Writing To the Data 136 Microchip Code ©1998 Sirius microSystems
EEPROM
EEPROM data allows you to verify the keypress. In this case, the recently written Remember, all of this is
value is displayed on the LCD by CALL LCD_Port, MOVF EEDATA,0 and CALL still part of the write
LCD_Data. sequence initiated about
two pages back.
CALL KB_Port ;Set Port B for keypad use
Wait CALL KB_Scan ;Scan keypad
MOVF Key,0 ;Check key for 0
BTFSS Z ;And if Z=1 key has been released
GOTO Wait ;Otherwise, wait for release
CALL Delay_5ms ;Wait for key to settle
CALL Delay_5ms
CALL Delay_5ms
CALL Delay_5ms

Like the key press code, the key release code waits for the key to settle when you
remove your finger from the keypad. The only change from the key press code is the
BTFSS Z which causes the loop to wait until the key is released. Once the key is
released, 20 ms is provided for settling time by calling Delay_5ms four times.

INCF EEADR ;Increment to next EEPROM address


MOVLW 04h ;Load W with number of data bytes
SUBWF EEADR,0 ;and compare with EEADR
BTFSS Z ;by checking Z
GOTO Get_Key ;If not at EEADR 04, get next data
CALL LCD_Port ;Reconfigure ports for LCD
MOVLW LCDLine1 ;Load W with line 1 DDRAM address
CALL LCD_Reg ;and write to LCD
CALL Disp_Done ;Display done message
SLEEP

At this point, the first value has been entered from the keypad, saved in the
EEPROM, read from the EEPROM, and displayed on the LCD. The EEADR regis-
ter is now incremented by INCF EEADR so that the process can repeat for the next
three characters.

Until four characters have been entered, MOVLW 04h, SUBWF EEADR,0 and You may have noticed that
BTFSS Z cause the execution of GOTO Get_Key to repeat the key scanning, storing, Disp_Done is slightly
retrieval, and display process. When the fourth value has been retrieved via the GOTO different from other data
Get_Key instruction, the result of SUBWF EEADR,0 will be zero and the zero flag tables. It uses a technique
will be set. The BTFSS Z will then cause GOTO Get_Key to be skipped, and the re- explained in Chapter 14
maining commands set up the LCD and call Disp_Done to display the message “Power that overcomes memory
page boundry problems
down now.”. The SLEEP command at the end of the main line code places the
that would otherwise
PIC16F84 into low power sleep mode. prevent this code from
working.
The result is that the NVMEM.ASM program has now placed four new values,
representing the four keys pressed on the keypad, into the internal EEPROM. Re-
moving power from the microcontroller will not erase these values. Try it and see.

Chapter Summary
The internal EEPROM can retain its data while power to the PIC is off. The 64
bytes of EEPROM data are accessed using the EEDATA and EEADR registers along
with EECON1 and EECON2. EECON1 contains control, flag and interrupt bits.
Writing 55h and AAh to EECON2 in the manner specified by microchip (pg. 34 of
the PIC16F8X data sheets) performs EEPROM writes.
Chapter 13
©1998 Sirius microSystems Microchip Code 137 Using the PIC16F84
Data EEPROM
Questions
1. Examine the PIC16F8x data sheets to determine how long data will remain in
the Data EEPROM.

2. List three applications that would benefit from the use of the Data EEPROM.

3. How much time, and how many clock cycles, does it take to store one byte in
the Data EEPROM? Assume a clock speed of 4 MHz.

Assignment
1. Using pseudo-code or a flow chart, describe the operation of an interrupt serv-
ice routine that stores successive bytes of data after waiting for the previous
write to finish.

2. Write the program for a programmable combination lock that stores the pass
code in the Data EEPROM. Use a 5-digit pass code to open or close the lock.
Assign one key on the keypad to change the pass code only when the lock is
unlocked. Display the state of the lock using either an LED or the LCD.

Questions
138 Microchip Code ©1998 Sirius microSystems
Troubleshooting
14

By this time you probably have the necessary skills to write reasonably complex
programs. This chapter will help you develop the skills needed to troubleshoot them.

Identifying and Isolating Faults


The key to troubleshooting your software is identifying and isolating faulty sec-
tions of code. There are a number of techniques useful for identifying, narrowing
down and isolating faults. However, no one technique works all of the time. Each of
the techniques explained below will help you to identify and isolate faults.

Validating Your Hardware


It makes no sense to troubleshoot software if your problem is in hardware. Using
a development system such as the PIC-MDS gives you the advantage of knowing
that the built-in hardware is at the very least wired correctly (really, we’ve tested it!).
What’s more, the included software routines will let you verify the operation of the
PIC-MDS hardware.

There comes a time, however, when you must strike out into uncharted territory
and interface your PIC-MDS to new hardware. Before connecting new hardware to
the PIC-MDS, there are a number of points to keep in mind.

I/O Requirements
Before starting to troubleshoot software, make sure that input devices provide
signals at the proper level—a logic 0 should be from 0 V to approximately 0.8 V, and
a logic 1 should be from approximately 2 V to 5 V. At the very least confirm the
presence of signals by monitoring the LEDs on the PIC-MDS. Better still, confirm
signal presence, amplitude and waveform using a voltmeter, logic analyser, or oscil-
loscope.

Chapter 14
©1998 Sirius MicroSystems Microchip Code 139 Troubleshooting
Test and examine all output circuitry to ensure that each PIC pin is not sinking
more than 25 mA or sourcing more than 20 mA. Also, keep in mind that Port A can
sink a maximum of 80 mA and can source a maximum of 50 mA. Likewise, Port B
can sink a maximum of 150 mA and source a maximum of 100 mA. Lastly, the
overall power dissipated by the PIC16F84 cannot exceed 800 mW.

Shared I/O Lines


Refer to the schematic in On the PIC-MDS, RA.2 and RA.3 are used to enable the LCD and Serial
chapter 4 for details. EEPROM, respectively. Any external devices that enable either one of these two
lines will cause unpredictable results on any of the lines connected to the LCD or
Serial EEPROM. Since the LCD connects to all of Port B as well as three out of the
five Port A pins, enabling it inadvertently can cause problems. Always disable the
LCD and serial EEPROM if you’re not using them.

Since the keypad keys are normally open, they are, in essence, disconnected from
the PIC-MDS, if not pressed. If pressed, a key will short one of the four row lines to
one of the column lines on Port B. Resistors have been added to ensure that short
circuit conditions do not occur. Nevertheless, your code might fail if someone were to
press a key and inadvertently supply an input from a keypad row line to a keypad
column line rather than obtaining its input from an external source. If you’re going to
obtain input from Port B, make sure users are not prompted to use the keypad. If you
wish to use the keypad and need to obtain external input, you may use only Port A.0,
1, or 4. Or, use half of the keypad thereby freeing up half of the Port B lines.

Similarly, while scanning for a key press, half of Port B is set to output and half
to input. Make sure that devices connected to Port B outputs can have their lines
temporarily scanned and that Port B inputs are disconnected (i.e. placed into high
impedance or disabled). Again, if this presents a problem, use Port A.0, 1, or 4. For
an example of how to share the keypad and LCD on Port B see ASCII.ASM as
discussed in Chapter 12.

All owners of the PIC-MDS If your application requires you to use your own hardware design, use a design
are permitted to use the similar to that of the PIC-MDS whenever possible—you know it works, and the
PIC-MDS circuitry shown library routines will save you a lot of time in developing software.
in Chapter 4 and the
library routines included
on disk in their microcon-
troller designs. “Playing” the Computer
Once you are certain that your faults lie in software, you can begin to examine
your code line by line. “Playing” the computer involves recording the state of each
register as you determine the results of each instruction. Start with a print out of your
source code and a blank piece of paper. Use the paper to record register contents
before and after each instruction. Don’t take anything for granted—use the instruc-
tion descriptions in the Data Sheets to determine the result of each instruction and the
state of any affected flags.

As you can imagine, playing the computer is very time consuming. You would
never want to simulate the execution of your entire program, only those sections that
you believe may be faulty. Use some of the techniques which follow to narrow your
troubleshooting to specific sections of code.

Validating Your
Hardware 140 Microchip Code ©1998 Sirius MicroSystems
Displaying Intermediate Values
If at all possible, use the built-in LEDs or LCD display on the PIC-MDS to
monitor relevant register, port or bit values. Often, faulty code produces unexpected
register values and program branches. One method to verify that your program is
operating correctly up to a specific point is to insert code which writes the contents of
a register out to the LEDs and then puts the microcontroller to SLEEP.

Using the LEDs is simple and quick. Make sure that you set Port B to output (if
necessary), move the contents of the register that you are interested in examining to
W, then copy them to Port B before issuing a SLEEP instruction to halt execution at
this point. If the LEDs display the expected result, the program is functioning cor-
rectly up to this point. You can then remove or comment out this code and place
similar display code further down in your program.

The LCD allows you to display the contents of many more registers than the
LEDs, but has the drawbacks of increased code complexity and the corruption of the
W and Status registers. If the contents of W, or for that matter any registers, are
important, save them in temporary file registers before accessing the LCD routines.
Also, remember that values sent to the LCD are displayed as their equivalent ASCII
character. At the risk of further increasing code complexity, you can convert values In almost all cases, using
to decimal digits (using BIN2DEC.LIB), and add 30h to each digit to convert them to the LEDs will be simpler.
ASCII digits.

External Triggers
Monitoring an unused I/O pin configured as a hardware flag or trigger can tell
you two things. By setting an output pin high at the start of a subroutine and clearing
it at the end of the subroutine you have a way of determining not only that the subrou-
tine executes, but also how long it takes to execute, and whether execution is consist-
ent. For long subroutines you can see this by using an LED connected to a port pin,
but for short subroutines you will obviously need an oscilloscope or logic analyser.

These external flags or triggers can also be used to provide a reference by which
to monitor other signals. This is especially useful for triggering oscilloscopes or logic
analysers when monitoring external signals like serial data streams.

Commenting Out Code


When a program appears to do nothing, a common cause is an undesired branch
out of the main program flow. This may be caused by an error in your branch logic,
or a computed GOTO over a memory page boundary—this is explained later in this
Chapter. If you comment out or branch over suspect code and program flow returns,
then the bypassed code is most likely at fault.

Commenting out existing routines and placing alternative routines after them is Some people like to use
an easy way to evaluate the effects of program modifications. different cases or tab stops
to indicate modified code.

Chapter 14
©1998 Sirius MicroSystems Microchip Code 141 Troubleshooting
Isolating Faults within Subroutines
Once you have an indication that a particular subroutine is faulty, much of the
work of troubleshooting is already finished, although you’ll find that isolating and
fixing the fault within a subroutine will take the majority of your time. To isolate the
fault within a subroutine, use the techniques already discussed. Playing the computer
is much easier when you’re not trying to simulate the operation of your entire pro-
gram. Similarly, commenting out code, displaying intermediate values, and setting
external triggers will all help you in debugging your routine.

Another item to bear in mind is the validity of the data being fed to the subrou-
tine. If a subroutine is being fed erroneous data by a previous routine, its results will
also be in error. To determine if this is occurring, temporarily force load any variable
registers used by the subroutine before the subroutine executes. This way, you know
that at the very least the starting data is valid.

Taking Breaks and New Approaches


Never underestimate the benefit of a good stretch, coffee break, lunch break, nap
or vacation as a troubleshooting tool. You may find that your subconscious mind will
come up with the solution if given a bit of time. More often, looking at your problem
in a new way will lead you to the correct solution.

One of the best ways of uncovering bugs is to try to explain the operation of your
software to a colleague. This approach forces you to systematically break down and
justify your code and logic. If your unfortunate victim is still paying attention, they
may question your logic and assumptions to reveal your error. Most often, simply
explaining your code (and the errors within) will allow you to recognize the fault.

Memory Page Boundaries


The mid-range PIC microcontrollers use a 13-bit address space capable of ad-
dressing 8k X 14 bits of program memory. Since the PIC uses 8-bit wide data regis-
ters, the program counter is divided into two parts, PCLATH and PCL. PCL, or the
program counter low byte, specifies a range of 256 memory addresses representing
one memory page. PCLATH, or the program counter high latch, is a 5-bit register
controlling the active memory page. The actual address specified by the program
counter is written as PCLATH:PCL and is the combined 13 bit address of PCLATH
and PCL. For example, if PCLATH contained 03h, and PCL contained 10h, the
resultant program counter value would be 310h. On the PIC16C711 and PIC16F84,
only the first 1k addresses are implemented—equivalent to 4 memory pages.

Memory page boundaries occur whenever PCL rolls over from FFh to 00h and
can present a problem during a table read when using the ADDWF PCL instruction.
ADDWF is known as a computed GOTO and is used by the data table read code in
previous chapters. The problem occurs only when the ADDWF PCL instruction is in
one memory page, and the result of the computed GOTO lies in the next memory
page. Adding an 8-bit value to PCL will not cause PCLATH to increment if PCL

Isolating Faults
within Subroutines 142 Microchip Code ©1998 Sirius MicroSystems
rolls over. The result is that the computed GOTO still points within the current memory
page, and not to the next page as it should. Fortunately, all other GOTOs and branches
correctly modify PCLATH so that the correct address is selected.

This precise problem occurs in the NVMEM.ASM program within the


Disp_Done subroutine. Disp_Done uses a table read to display the message “Power
down now.” on the LCD.

238 00E7- Disp_Done ;Writes ‘Power down now.’ to the first line of the LCD
239 ;display using LCD display library (LCD.LIB).
240
241 00E7- 018C CLRF Counter ;Reset character counter
242 00E8- 3000 :Get_Char MOVLW HI Message3 ;Move the High Byte of Message3
243 ;location into W
244 00E9- 008A MOVWF PCLATH ;and Move it into PCLATH
245 00EA- 30F6 MOVLW Message3+1 ;Move message address + 1 into W
246 00EB- 070C ADDWF Counter,0 ;Calculate offset address and
247 00EC- 1803 BTFSC C ;see if it overflows
248 00ED- 0A8A INCF PCLATH ;If so, increment PCLATH
249 00EE- 20F5 CALL Message3 ;Jump to the data table
250
251 00EF- 3800 IORLW 00h ;RETLW won’t affect flags so use O
252 00F0- 1903 BTFSC Z ;check for end of message This table read code allows
253 00F1- 0008 RETURN ;and finish if done
254 00F2- 205A CALL LCD_Data ;If not done, send character to LC data tables to be placed
255 00F3- 0A8C INCF Counter,1 ;Add 1 to Counter
256 00F4- 28E8 GOTO :Get_Char ;Do it again for the next characte
anywhere in memory, even
257 across page boundaries.
258 00F5- 0082 Message3 MOVWF PCL ;W contains low program counter
259 ;byte and points to next location
260 ;plus Counter offset
261 00F6- 3450 RETLW ‘P’
262 00F7- 346F RETLW ‘o’
263 00F8- 3477 RETLW ‘w’
264 00F9- 3465 RETLW ‘e’
265 00FA- 3472 RETLW ‘r’
266 00FB- 3420 RETLW ‘ ‘
267 00FC- 3464 RETLW ‘d’
268 00FD- 346F RETLW ‘o’
269 00FE- 3477 RETLW ‘w’
270 00FF- 346E RETLW ‘n’
271 0100- 3420 RETLW ‘ ‘
272 0101- 346E RETLW ‘n’
273 0102- 346F RETLW ‘o’
274 0103- 3477 RETLW ‘w’
275 0104- 342E RETLW ‘.’
276 0105- 3420 RETLW ‘ ‘
277 0106- 3400 RETLW 0 ;End of message

Notice in the list file generated by the assembler that the Message3 data table
straddles a page boundary—addresses 00FF - 0100h. Compare this code with
Disp_Line1 or Disp_Line2 in NVMEM.ASM and you will see that this table does
not use the ADDWF PCL instruction to compute the GOTO. Instead, this subroutine
determines whether or not to increment PCLATH by adding the offset to the table’s
starting PCL value and checking for an overflow via the Carry bit. If an overflow
occurs, then a page boundary has been crossed within the table and the PCLATH
register must be incremented.

Notice that the above table read code will work in any memory page because the
upper five bits of the table address are loaded into PCLATH before computing the
GOTO. In contrast, an ADDWF PCL instruction that results in PCL rolling over
leaves PCLATH unchanged. Therefore, a computed GOTO using ADDWF PCL
across a page boundary results in the execution of instructions within the same page
as the ADDWF PCL instruction—not the next page as expected.

To overcome memory page boundary problems with data tables, either use code
that checks for and corrects page crossings (as in the example above), or make sure
that your data tables and ADDWF instructions are in the same memory page—check
the .LST file and use NOP instructions or rearrange code as necessary.
Chapter 14
©1998 Sirius MicroSystems Microchip Code 143 Troubleshooting
A/D Converter Troubleshooting
The PIC16C711 Port A.0-3 lines can be set as digital I/O or analog inputs for the
internal A/D converter. When using a Port A pin as both an analog input and a digital
output, you must keep the following points in mind. Enabling A/D operation on a
Port A pin does not configure the pin as an input. Before using a Port A output pin as
an A/D input, the pin must first be configured as an input, then an A/D input. Your
code may sometimes work without first configuring Port A pins as inputs because at
power up all PIC I/O lines are set to input.

Simulators and Emulators


There are programs available that will simulate the operation of your program.
Simulators are computer programs that can step through code, instruction by in-
struction, while displaying the contents of registers, I/O latches, and memory. Obvi-
ously, simulators are extremely useful in debugging as they can play the computer
Some simulators use far better and faster than you could. The disadvantage of simulators is that they do
stimulus files to emulate not run your code in real time, and, being inside your computer, have no way of
external hardware signals. interacting with I/O devices that you may want to use with your microcontroller.

Emulators, on the other hand, do not suffer the limitations of simulators. Emula-
tors incorporate circuitry that replaces the PIC in your target system. They run your
software program in your hardware in real time. Furthermore, they allow you to stop
the execution of your program and examine registers and memory at any point. Their
only disadvantage is high cost.

Programming for Easy Troubleshooting


There are a number of programming techniques that make troubleshooting easier.
By now, the benefit of using and reusing tested and proven subroutine libraries should
be apparent. Why keep reinventing the wheel when simply adapting existing code to
fit your application is a better alternative. The following suggestions will help you in
developing your software.

Plan, Plan, and Plan


Before you begin any programming task, make sure that you understand exactly
what the program needs to do. Pay particular attention to any hardware devices that
the microcontroller will need to interact with. Having specification sheets for any
devices that you will be interfacing to is very useful.

Use pseudo-code and flowcharts to outline the program’s structure and break the
program into identifiable and manageable tasks.

Code and Debug Individual Program Tasks


After identifying program tasks, write the code for each individual task and verify
that it works as expected. Then, join interdependent tasks into larger code segments.
A psychological benefit of this approach is that you meet with small successes often.
Bringing small successes together ensures larger successes.
A/D Converter
Troubleshooting 144 Microchip Code ©1998 Sirius MicroSystems
Modularize Your Code
When writing your software routines, keep in mind that you may wish to use
them in other programs or with similar hardware. Writing program subroutines to
incorporate similar structures, as well as using similar entry and exit parameters
helps to improve the understanding of your programs. Easily changeable variables,
defines in the equates at the beginning of the program, make for minor code changes
when adapting your subroutines for different hardware.

Comments
Good comments do not explain what the instructions are doing as much as they
explain how and why the instructions in a routine are being used together. Subrou-
tines are often preceded by extensive comments that explain the purpose of the sub-
routine, important registers, registers modified, calling protocols and variables.

Another good use of comments is to record the revision history of your program.
Use comments to keep track of which routines are working and debugged, any rou-
tines that were modified to accommodate hardware changes, and work yet to be
done. Heed this advice and your successors will profusely praise your programming
prowess!

Chapter Summary
Effective troubleshooting entails systematically isolating and identifying pro-
gram or hardware faults. Various techniques such as validating your I/O hardware,
simulating program execution, halting program operation at specific points and dis-
playing intermediate values help in uncovering program flaws.

Writing code in a manner that simplifies testing and debugging lessens the need
for troubleshooting. Planning ahead, and writing code in manageable sections helps
to ensure working code.

Be aware of unique hardware dependencies that may affect the operation of


your software—the memory page boundary and A/D configuration are examples.

Chapter 14
©1998 Sirius MicroSystems Microchip Code 145 Troubleshooting
Questions
1. What is the central philosophy of troubleshooting?

2. Why halt the program when displaying intermediate values?

3. When would it be desirable to use the LCD to display intermediate values?

Assignment
1. Take any existing program of your own (working or not) and add code to
display intermediate values in at least three different places.

2. Use an external trigger and an oscilloscope to time the execution of a subrou-


tine in one of your programs.

Mr. Bugs Quasher was particularly good at


debugging code using the “playing the computer”
troubleshooting technique.

Questions
146 Microchip Code ©1998 Sirius MicroSystems
RS-232 Serial
15 Communication

The RS-232 serial communication standard has attained widespread use and
many devices can transfer data or be controlled using RS-232 signals. Typical de-
vices include: computers, printers, plotters, modems, bar-code readers, operator in-
terface terminals, motor controllers, data loggers, LCDs, GPS receivers, milling
machines, PLCs and many more. This chapter will demonstrate how to send and
receive RS-232 serial data.

RS-232 Basics
The RS-232 standard specifies the connector type, handshaking protocols and
electrical characteristics for a serial communications link. The traditional RS-232
connector is a 25-pin DB-25, although recently the 9-pin DB-9 connector has be-
come common on PCs. The PIC-MDS has a 3-pin header that you can connect to
either a DB-9 or DB-25 connector as required. One pin transmits serial data, another
pin receives serial data, and the third pin is a signal ground. Most RS-232 devices
can be configured to communicate using only these three lines. Below is a diagram
showing how to connect a DB-25 or DB-9 connector to the PIC-MDS 3-pin header.

Depending on the device or


communication software
used, you may only need to
connect Transmit Data,
Receive Data and Signal
Ground. The other wires
simulate hardware
handshaking for devices
that require it.

Chapter 15 RS-232
©1998 Sirius MicroSystems Microchip Code 147 Serial Communication
Handshaking can be used to start or stops the flow of data. Handshaking is
necessary if a device cannot finish processing a character before the next character
arrives. The RS-232 standard specifies hardware handshaking, but handshaking can
be implemented using either hardware or software techniques. Hardware handshaking
uses a number of the signal lines on the previous page to coordinate data flow and is
UART stands for Universal usually implemented using a dedicated UART or serial communications interface.
Asynchronous Receiver
Transmitter, and is an IC Software handshaking relies on the transmission of special XON (Transmit on)
dedicated to serial I/O. and XOFF (Transmit off) characters, which are sent and received using just the
transmit and receive data lines. Therefore, a full-duplex, controlled serial communi-
cations link can be established using only three lines—transmit, receive and ground.
This makes software handshaking relatively easy to implement.

The RS-232 transmit and receive examples in this Chapter demonstrate serial
communication without handshaking. Handshaking is usually not necessary when
transmitting small amounts of data, or when the data can be processed at high speeds.

The RS-232 electrical signal is bipolar, unlike the unipolar 5 V TTL level sig-
nals used by most computer systems. RS-232 voltage levels are also opposite to
their equivalent TTL logic levels. For this reason, the PIC-MDS is equipped with a
MAX232 level translator (see the schematic in Chapter 4). The diagram below shows
the same RS-232 data frame as both TTL and RS-232 signal levels.

The serial ports on some


PC’s will accept 5 V as a
space, and 0V as a mark,
eliminating the need for a
dedicated level translator
such as the MAX232. The
clamping diodes on the
PIC I/O pins allow RS-232
levels to be input directly
as long as a series limiting
resistor is used, again
eliminating the need for a
level translator. However,
in both cases, the logic of
the TTL waveform must be
reversed.

An RS-232 data frame consists of a start bit, a number of data bits, an optional
parity bit, and a stop bit. Most modern RS-232 devices communicate using eight
data bits, no parity, and one stop bit—otherwise known as 8n1.

Note that the TTL logic level during the idle time between frames is 5 V. The
start bit is always a logic 0, making it easy to determine when a frame begins. Even
when frames follow one another, with no idle time, the logic 1 stop bit ensures there
will be a high to low transition to mark the start of the next frame. After the start bit,
the data bits are sent in least-significant to most-significant bit order.
RS-232 Basics
148 Microchip Code ©1998 Sirius MicroSystems
Receiving RS-232 Data
Since serial data bits are sent sequentially, receiving the data correctly is a matter
of sampling the data bits at the correct times. The serial signal’s bit per second (bps)
rate can be used to calculate the bit time, or the duration of each bit. The default data
rate used by the RS-232 library programs is 9600 bps. We can calculate the bit time
as follows:

The RS-232 receive and


transmit library files
support all common bps
rates.

Once the bit time is known, receiving RS-232 data can be described by the fol-
lowing pseudo-code:

Wait for the receive data line to drop low


Wait ½ bit time
Is receive data line still low? (Is it a Start bit or noise?)
If not, low pulse was noise
If low, wait 1 bit time
Sample data bit 0
Wait 1 bit time
Sample data bit 1
:
Wait 1 bit time
Sample data bit 7
Wait 1 bit time
Is receive data line high? (Stop bit)
If not, a framing error has occurred
If high, data received

Examine the timing diagram, below, for a visual representation of the sample
points used to receive RS-232 data: (Shown in postive logic or TTL form.)

The transmitted character


shown here is 41h, or the
ASCII character ‘A’.

Chapter 15 RS-232
©1998 Sirius MicroSystems Microchip Code 149 Serial Communication
The RECV232.ASM program uses RS232RX.LIB to receive serial characters
and display them on the first line of the LCD. To test this program, use a terminal
Make sure your terminal program on a personal computer connected to the PIC-MDS by a cable as described
program is transmitting at earlier. Also, ensure that JU5 is on the Rx setting.We’ll examine the program begin-
9600 bps, 8 data bits, no ning with the hardware equates.
parity and 1 stop bit—8n1.
;Hardware Equates

ORG 0Ch ;Start of File register area

;Counter equates
CharAddress DS 1 ;Holds current LCD DDRAM address
CharCounter DS 1 ;Counts characters before scroll
Counter1 DS 1 ;Delay counter for Delay_5ms
Counter2 DS 1 ;Delay counter for Delay_5ms

;Equates required by RS232RX.LIB


Counter DS 1 ;Bit delay counter
BitCounter DS 1 ;RS232 bit counter register
Receive DS 1 ;Received byte storage register

;Other equates
LCD_Length EQU 16 ;Number of characters per LCD line

The CharAddress, CharCounter and LCD_Length variables are used by the LCD
scrolling routines. These variables, described later, allow the first 16 characters re-
ceived to fill the LCD. Subsequent serial characters cause the previously received
characters to scroll across the display from right to left. Counter1 and Counter2 are
used by LCD.LIB to provide the 5 ms LCD initialization delay.

The RS232RX.LIB subroutine library requires the Counter, BitCounter and


Receive variables. Counter is used to generate bit time delays and BitCounter keeps
track of the number of received bits. Received data bits are shifted through the Re-
ceive register. After eight bits are received, the Receive register contains the trans-
mitted character.

ORG 00h ;Start program at Reset Vector

CALL LCD_Port ;Set up ports for LCD use


CALL LCD_Init ;Initialize LCD and clear screen
CALL Receive_Port ;Set RA.4 for serial input

At the start of the program, the LCD is initialized and cleared. The CALL to
Receive_Port uses RS232RX.LIB to set RA.4 for serial input.

Receive_Port ;Sets PORTA.4 to input. Make sure PIC-MDS JU5 is set to Rx

BSF RP0 ;Select memory register page 1


MOVLW 00010000b ;Load W with bit to make RA.4 input
IORWF TRISA ;and OR with Port A tristate reg.
BCF RP0 ;Return to memory register page 0
From RS232RX.LIB RETURN

The Receive_Port subroutine sets TRISA.4 using an OR operation that leaves


the other TRISA bits unchanged.

Receiving RS-232
Data 150 Microchip Code ©1998 Sirius MicroSystems
GOTO Initialize ;Jump over interrupt vector

ORG 05h ;Program starts after interrupt vec

Include ‘LCD.LIB’ ;LCD subroutine library


Include ‘RS232RX.LIB’ ;RS-232 receive library

Initialize ;Prepare character counters and LCD for data

MOVLW LCD_Length ;Load W with number of LCD characte


MOVWF CharCounter ;and save in CharCounter then subtr
DECF CharCounter ;1 to account for 0 position

MOVLW CursBlink ;Load W with constant to blink curs


CALL LCD_Reg ;and write to LCD as a command

MOVLW LCDLine1 ;Load W with DDRAM address of line


MOVWF CharAddress ;and save in CharAddress variable
CALL LCD_Reg ;before writing it to the LCD

After the include statements for the LCD and RS232RX library files, the Initial-
ize routine begins. Initialize loads the CharCounter variable with LCD_Length (16
in this case) and then decrements CharCounter by 1 so that display scrolling begins
after 15 characters have been received.

Next, the LCD cursor is enabled in blinking mode, and the LCD DDRAM ad-
dress is set to the first character of line 1. The CharAddress variable also holds the
current LCD address, so that it can be used to reset the DDRAM address after forty
characters have been received. Saving CharAddress in a memory register frees the Forty characters is the
program from having to interrogate the LCD to determine the current character ad- length of the LCD DDRAM
dress. buffer. See Chapter 12 for
more information.

Main ;Receive serial characters in Receive buffer

CALL Receive_Wait ;Wait for and receive one serial by

MOVF Receive,0 ;After receiving, check character f


BTFSC Z ;an error (Receive=00h)
GOTO Main ;If no character, wait again

The Main subroutine calls Receive_Wait in RS232RX.LIB. Receive_Wait waits


for a start bit and attempts to grab one serial character. It is important to note that
Receive_Wait does not return to the calling program until either a serial character is
received, or a false Start bit occurs—indicating a glitch on the RS-232 line. If a
serial error occurs, the Receive register is reset. The MOVF Receive,0 and BTFSC
Z instructions checks for this zero condition and a return to Main executes if the
receive register is zero.

Receive_Wait ;Wait for PortA.4 to change from high to low indicating th


;start of serial data.

BTFSC Serial_Input ;Check serial input pin


GOTO Receive_Wait ;If high, wait for low
From RS232RX.LIB

The two instructions of Receive_Wait simply wait for the RS-232 signal line
drop low. Receive_Data, which follows on the next page, samples the RS-232 data.

Chapter 15 RS-232
©1998 Sirius MicroSystems Microchip Code 151 Serial Communication
Receive_Data ;After PortA.4 drops low, test for a start bit by delaying
;for half the Bit_Time and then checking PortA.4 for the lo
;start bit. Then wait for the Bit_Time and read each bit in
;Carry. Rotate Carry into the Receive byte and repeat the
;delay, Carry and rotate until eight DataBits have been
;received. The Receive register stores the received byte. I
;framing error occurs (only a simple check for a stop bit i
;done) the contents of the Receive regsiter will be 00h and
;the Receive_Data routine will return with 00h in W.
Assigning the label
Receive_Data to a section MOVLW DataBits ;Load W with number of data bits
MOVWF BitCounter ;and save in BitCounter register
of the Receive_Wait MOVLW Half_Bit ;Load W with half of bit delay time
subroutine makes it easier CALL BitDelay ;and wait for 1/2 bit
to adapt the RS232RX.LIB BTFSC Serial_Input ;Check for low start bit again
subroutines for interrupts. GOTO Receive_Error ;If high, error occurred-exit with
The serial input pin RA.4 :Next_Bit MOVLW Bit_Time ;Load W with bit delay time
can be configured to CALL BitDelay ;and wait until middle of next bit
generate an interrupt on BTFSS Serial_Input ;Check serial input pin for 1
the falling edge of the RS- BCF C ;If serial input is 0, clear Carry
BTFSC Serial_Input ;Check serial input pin for 0
232 Start bit. BSF C ;If serial input is 1, set Carry
RRF Receive ;Rotate Carry into received data by
DECFSZ BitCounter ;Decrement bit counter & check for
GOTO :Next_Bit ;If not 0, get the next bit

MOVLW Bit_Time ;Load W with bit delay time


CALL BitDelay ;and wait until middle of stop bit
BTFSS Serial_Input ;Check for high stop bit
GOTO Receive_Error ;If low, we have a framing error
RETURN ;Otherwise return
From RS232RX.LIB
The first two instructions load the BitCounter variable with the number of data
bits that will be received—typically 8. Then, the BitDelay subroutine is called to
provide a delay of ½ bit time. The variable Half_Bit is defined in the Software Equates
See Appendix C - PIC
Macro Assembler Refer-
section of RS-232RX.LIB. The PM assembler supports in-line math operators, mak-
ence, Section 9, for more ing it easy to define Half_Bit from Bit_Time:
math operators.
Bit_Time EQU 01Eh ;Serial Bit delay from table above
Half_Bit EQU Bit_Time/2 ;Half of the Bit delay
From RS232RX.LIB

After returning from the BitDelay subroutine, the serial input pin is checked
again to ensure that it is still low, signifying a valid Start bit. If not, the program goes
to the Receive_Error subroutine.

Once a valid Start bit is received, BitDelay is called again with a full Bit_Time
value in W. When BitDelay finishes, the PIC is ready to sample bit 0. The next four
lines sample Serial_Input and set or clear the Carry flag depending on the state of the
pin defined by Serial_Input. These four lines always take four clock cycles to ex-
ecute, regardless of the state of Serial_Input. This coding prevents cumulative timing
errors.

After the Carry flag has been set or cleared according to value sampled, RRF
Receive rotates the Carry bit into the upper bit of the Receive register.

BitCounter keeps track of the bits remaining to be received. The process repeats
in a loop until BitCounter is zero and all eight bits have been received. After another
Bit_Time delay the Stop bit is sampled. The Receive_Wait subroutine returns unless
a Stop bit does not occur, in which case a receive error is generated.
Receiving RS-232
Data 152 Microchip Code ©1998 Sirius MicroSystems
The Receive_Error section of the subroutine will execute if either the Start bit is
not low during its mid-point sample, or if the Stop bit is not high during its mid-point
sample. An invalid Start bit is probably due to induced noise on the RS-232 line,
whereas an invalid Stop bit is probably due to incorrect baud rate or data length
settings. Either of these two conditions indicate that a framing error has occured and
that the received data is suspect. If this is the case, the receive buffer is cleared. To We chose to return 00h
check for an error, your program can check the Receive character for a zero on because it’s easy to check.
return. See the Main routine for
the error checking code.
After the Receive_Wait subroutine has received all eight bits of an RS-232 char-
acter it places the received value into the Receive register. The LCD_Write section of
RECV232.ASM will display the character.

LCD_Write ;Write the character in Receive buffer to LCD display

MOVF Receive,0 ;Move received character into W &


CALL LCD_Data ;write to current DDRAM address
INCF CharAddress ;Add 1 to DDRAM address counter
MOVLW 0A8h ;Load W with last DDRAM address +1
SUBWF CharAddress,0 ;and subract from CharAddress
BTFSC Z ;to see if 40 characters are full
GOTO Line_Reset ;If so, reset LCD to start of line

MOVF CharCounter,1 ;Check Character counter for end


BTFSC Z ;of visible screen by checking Z
GOTO Scroll ;If at end, scroll display left
DECF CharCounter ;If not, decrement CharCounter
GOTO Main ;and wait for next character

The first fifteen characters fill line one of the LCD. After the first fifteen charac-
ters are sent to the LCD, each new character is followed by a command to scroll the
LCD left so that the oldest characters scroll off the visible display. After forty char-
acters, the LCD DDRAM buffer is full and must be reset to its starting value of 80h.
The LCD_Write, Scroll, and Line_Reset subroutines perform these tasks.

LCD_Write moves the character from Receive to the W register and displays the
character by calling LCD_Data. INCF CharAddress keeps track of how many char-
acters have been placed into the LCD DDRAM. Each line of the LCD has forty
DDRAM addresses and can hold forty characters. Remember from Chapter 12 that
the first DDRAM location is 80h. After forty characters have been received and
displayed, CharAddress will equal A8h. MOVLW 0A8h and SUBWF CharAddress,0
checks that the DDRAM address is forty characters past 80h, at which point the
LCD is reset to the start of DDRAM by GOTO Line_Reset.

Line_Reset ;If 40 characters have been written to DDRAM, scroll the


;display contents left and reset DDRAM to line 1.

MOVLW LCDLeft ;Load W with LCD shift left command


CALL LCD_Reg ;and write to LCD
MOVLW LCDLine1 ;Load W with first DDRAM address
MOVWF CharAddress ;and save in CharAddress register
CALL LCD_Reg ;before writing it to LCD
GOTO Main ;Wait for more serial data

Line_Reset scrolls the contents of the LCD left, and resets the DDRAM address
to 80h, so that it can again be filled with forty new characters.
Chapter 15 RS-232
©1998 Sirius MicroSystems Microchip Code 153 Serial Communication
Scroll ;Scroll display left to keep new characters in LCD window

MOVLW LCDLeft ;Load W with LCD shift left command


CALL LCD_Reg ;and send to LCD
GOTO Main ;Wait for next character

If forty characters have not yet been displayed, the last five lines of LCD_Write
determine whether or not to scroll the display. CharCounter keeps track of the re-
maining character positions to be filled before scrolling is required. After the first 15
characters, scrolling is required, CharCounter is 0, and Scroll executes for all subse-
quent characters.

Transmitting RS-232 Data


Transmitting RS-232 data is relatively straightforward. As with RS-232 recep-
tion, the bit time needs to be calculated from the serial bits per second rate. As shown
in the diagram below, transmitting RS-232 signals involves setting a bit, waiting for
the bit time, sending the next bit, waiting, and so on until all bits have been sent:

The program XMIT232.ASM sends the message “Key XX Pressed” to the PIC-
MDS serial output each time a key is pressed. XX is replaced by a number represent-
Make sure your terminal ing the key pressed on the keypad. To test this program, connect the PIC-MDS to a
program is set to receive at personal computer running a terminal program and make sure that JU5 is set to Tx.
9600 bps, 8 data bits, no Use one of the serial cables described at the start of the chapter.
parity and 1 stop bit—8n1.
;Equates required by BIN2DEC.LIB:
Hundreds DS 1 ;Hundreds digit
Tens DS 1 ;Tens digit
Ones DS 1 ;Ones digit

;Equates required by KEYPAD.LIB:


Key DS 1 ;Key return code register

;Equates required by RS232TX.LIB:


Counter DS 1 ;Serial bit delay counter
BitCounter DS 1 ;RS232 bit counter register
Transmit DS 1 ;Transmit byte storage register

See Chapter 9 for more XMIT232.ASM uses three library files. KEYPAD.LIB scans the keypad and
details on KEYPAD.LIB returns a value from 1 to 16 representing which key was pressed—or 0 if no key was
and BIN2DEC.LIB. pressed. BIN2DEC.LIB is used to convert the value returned by KEYPAD.LIB to
three decimal digits.
Transmitting RS-232
Data 154 Microchip Code ©1998 Sirius MicroSystems
RS232TX.LIB requires three variables. Counter is used to generate bit time
delays, BitCounter counts tranmitted bits, and Transmit is a register that holds the
byte to be transmitted.

CALL Transmit_Port ;Configure PortA.4 as serial output


CALL KB_Port ;Configure Port B for keypad scanni
GOTO Get_Key ;Jump over interrupt vector

XMIT232.ASM begins by calling Transmit_Port in the RS232TX.LIB library


to initialize RA.4 as an output. Next, the call to KB_Port in KEYPAD.LIB initializes
Port B to scan the keypad. GOTO Get_Key jumps over the interrupt vector and the
library include statements.

Transmit_Port ;Sets PORTA.4 to output. Make sure PIC-MDS JU5 is set to T

BSF RP0 ;Select memory register page 1


MOVLW 00001111b ;AND configuration byte with Port A
ANDWF TRISA ;tristate reg. to make RA.4 an outp
BCF RP0 ;Return to memory register page 0
BSF Serial_Output ;Set serial line high
RETURN From RS232TX.LIB

Similar to Receive_Port in RS232RX.LIB, Transmit_Port sets PortA.4 to out-


put without modifying the settings of the other Port A pins. This is accomplished by
ANDing Port A with 00001111b.

Get_Key ;Wait for a key stroke, debounce it and convert it to thre


;decimal digits.

CALL KB_Scan ;Get Key return code


MOVF Key,0 ;Check Key return code
BTFSC Z ;for no key press (0=no key)
GOTO Get_Key ;If no key pressed, try again

CALL Delay ;Wait for key to settle


CALL KB_Scan ;Read Key code after settling
MOVF Key,0 ;Read Key code into W
CALL Bin_Dec ;and convert to decimal

The Get_Key routine uses KB_Scan to scan the keypad until a key is pressed.
Once a key has been pressed, CALL Delay waits for the key to settle before another
call to KB_Scan captures the key value. Since KB_Scan returns the key pressed
value in the Key register, MOVF Key,0 copies the key code into W. The call to
Bin_Dec converts the binary key code into three decimal digits which are stored in
the registers Hundreds, Tens and Ones.

Convert_ASCII ;Add 30h to offset the BCD numbers into ASCII.

MOVLW 30h ;Load ASCII offset into W and


ADDWF Tens ;add to Tens and
ADDWF Ones ;Ones registers to make ASCII numbe

By adding 30h to the Tens and Ones registers, the numeric values stored in them
are converted to their corresponding ASCII characters. This is done so that ASCII
characters, not binary numbers, are transmitted to the receiving serial terminal.

Chapter 15 RS-232
©1998 Sirius MicroSystems Microchip Code 155 Serial Communication
Transmit_Key ;Transmit the word ‘Key ‘

MOVLW ‘K’ ;Load W with ASCII code for ‘K’ and


CALL Transmit_Data ;send out of serial port
MOVLW ‘e’ ;Load W with ASCII code for ‘e’ and
CALL Transmit_Data ;send out of serial port
MOVLW ‘y’ ;Load W with ASCII code for ‘y’ and
CALL Transmit_Data ;send out of serial port
MOVLW ‘ ‘ ;Load W with ASCII code for ‘ ‘ and
CALL Transmit_Data ;send out of serial port

The Transmit_Key routine relies on Transmit_Data in RS232TX.LIB to send


characters for the word “Key ”. The ASCII value for each letter is generated by the
assembler when the letter is enclosed in quote marks.

Transmit_Data Drop PortA.4 from high to low to indicate the Start Bit a
;delay for one Bit_Time. Rotate the Transmit buffer right
;into Carry and set or clear the serial output pin based on
;Carry. Wait for another bit time and continue rotating and
;transmitting until all eight bits have been sent. Finally,
;send a stop bit.

MOVWF Transmit ;Save character in W to buffer


MOVLW DataBits ;Load W with number of data bits
MOVWF BitCounter ;and save in BitCounter regsiter
BCF Serial_Output ;Send Start bit
NOP ;and pad routine to be same length
NOP ;as :Next_Bit code so Bit_Time is
NOP ;accurate
NOP
NOP
NOP
NOP

:Next_Bit MOVLW Bit_Time ;Load W with bit delay time


CALL BitDelay ;and wait one bit duration
RRF Transmit ;Rotate Transmit byte into C
BTFSS C ;Check Carry for a 1
BCF Serial_Output ;If C=0, clear serial output
BTFSC C ;Check Carry for a 0
BSF Serial_Output ;If C=1, set serial output
DECFSZ BitCounter ;Decrement bit counter & check for
GOTO :Next_Bit ;If not 0, get the next bit

MOVLW Bit_Time ;Load W with bit delay time


CALL BitDelay ;and wait until end of last bit
BSF Serial_Output ;Set serial line high for Stop bit
MOVLW Bit_Time ;Load W with bit delay time
CALL BitDelay ;and wait a bit
RETURN

Transmit_Data begins by moving the character in W to the Transmit register.


Next, the number of data bits to be transmitted is saved in the BitCounter register and
the serial output pin is set low to initiate the Start bit. The seven NOP instructions
add a short time delay and are followed by a call to BitDelay in the :Next_Bit subrou-
tine. BitDelay holds the Start bit low for one bit time. These NOPs plus the BitDelay
subroutine form the exact delay required for one bit.

The remainder of the :Next_Bit subroutine rotates the Transmit register right,
cycling each bit into the Carry flag. The next four lines check Carry and set or clear
the Serial_Output pin depending on the state of Carry. These four lines always take
four clock cycles to execute, regardless of the state of Serial_Input. This coding
prevents cumulative timing errors.
Transmitting RS-232
Data 156 Microchip Code ©1998 Sirius MicroSystems
DECFSZ BitCounter keeps track of how many bits have been transmitted and Remember, Databits is used
repeats the :Next_Bit routine until BitCounter is zero. The next call to BitDelay to set BitCounter to the
holds the last data bit for one bit time. BSF Serial_Output sets the output pin high to number of bits to be
generate the Stop bit and the final call to BitDelay holds the Stop bit for just under transmitted —typically 8.
one bit time.

Notice that NOPs are not needed to pad the Stop bit. Returning from the
Transmit_Data routine, loading a new character into W, and calling Transmit_Data
again takes five processor clock cycles—equivalent to 5 NOPs—and the Start bit is
not sent until after the fourth instruction in Transmit_Data. In total, this adds a nine
clock delay to the BitDelay routine. When sending characters sequentially this pro-
duces a Stop bit slightly longer than one bit time, allowing close to the maximum
possible serial throughput.

Transmit_Num ;Transmit the two key return code ASCII digits.

MOVF Tens,0 ;Load W with ASCII Tens digit and


CALL Transmit_Data ;send out of serial port
MOVF Ones,0 ;Load W with ASCII Ones digit and
CALL Transmit_Data ;send out of serial port

Once the letters “Key ” have been sent to your serial terminal, Transmit_Num
sends the key code previously saved in the Tens and Ones registers.

Transmit_Mesg ;Transmit the word ‘ Pressed’, followed by the character


;codes for carriage return (13) and line feed (10).

CLRF CharCounter ;Clear message character counter


Get_Char MOVF CharCounter,0 ;Get current character count in W
CALL Message ;and retrieve message character
MOVWF Transmit ;Store returned character in Transm
MOVF Transmit,1 ;and check transmit for end of
BTFSC Z ;message marker by checking Z
GOTO Wait ;If message done, wait for key rele
CALL Transmit_Data ;If not, send current character
INCF CharCounter ;Increment the character counter
GOTO Get_Char ;and get the next character

Finally, Transmit_Mesg reads the Message data table to send the word “ Pressed” Data table reads were first
as well as a carriage return and line feed to the serial device attached to the PIC- described in Chapter 12.
MDS. CharCounter keeps track of the data table offset, and the end of Message is
marked by a zero byte. When the end of message zero byte is read from the data
table, BTFSC Z causes GOTO Wait to execute instead of being skipped.

Wait ;Wait until the user releases the pressed key.

CALL KB_Scan ;Scan keypad


MOVF Key,0 ;Check key for 0
BTFSS Z ;And if Z=1 key has been released
GOTO Wait ;Otherwise, wait for release
CALL Delay ;Wait for key to settle
GOTO Get_Key ;Wait for next key

The Wait routine loops until the key is released, indicated by Key being returned
as zero, and the subsequent delay ensures that any bounces on key release are ig-
nored. After the delay, the program is ready to transmit the next key press.

Chapter 15 RS-232
©1998 Sirius MicroSystems Microchip Code 157 Serial Communication
Chapter Summary
RS-232 serial communication is a common way to transmit data between de-
vices. Serial data is assembled into data frames consisting of one Start bit, the data,
and one or more Stop bits. Serial data is transmitted sequentially at one of a number
of common bit rates, and usually as a reverse-logic, bipolar signal. Serial transcievers
such as the MAX232 on the PIC-MDS automatically convert these signals to and
from TTL logic levels.

The RS232RX.LIB and RS232TX.LIB progams implement simple serial recep-


tion and transmission without handshaking. For a complete discussion of RS-232
communications refer to the latest EIA RS-232 standard publication, or textbooks
dealing with serial communication systems.

Chapter Summary
158 Microchip Code ©1998 Sirius MicroSystems
Questions
1. What are the common serial bps rates?

2. In TTL levels, why is the Start bit always low?

3. Why does RS232RX.LIB sample the RS-232 input in the middle of a bit time?

4. You have designed a pressure monitoring sensor which must transmit 8 bits of
pressure data to a computer every 1 ms. What is the minimum common bps
rate needed.

5. How does RS232RX.LIB need to be modified if the MAX232 transciever is


not used. That is, assume the PIC is directly connected to the transmitting RS-
232 device through a series resistor.

Assignment
1. Write a program to transmit a message repeatedly to a serial terminal at a bps
rate other than 9600 bps. Make sure that your message begins on a new line
each time it is transmitted.

2. Write a program that will illuminate each of the eight LEDs in response to a
unique ASCII character. For example, sending a “1” could light the LED on
RB0.

3. Create a program that uses interrupts to receive RS-232 data. Use the negative
going edge of the Start bit to initiate the interrupt.

4. Wire a 10kW ohm resistor in series with the serial output wire of a terminal to
an available port pin on the PIC. Write a program that will use this pin to
receive serial characters, modify them by adding 1, and retransmit the modi-
fied character back to the terminal forming a simple data encryption system.

Chapter 15 RS-232
©1998 Sirius MicroSystems Microchip Code 159 Serial Communication
Notes
160 Microchip Code ©1998 Sirius MicroSystems
16 A/D Conversion

Up until this chapter, we’ve dealt with interfacing to binary digital devices. Our
world, however, is an analog place where quantities such as voltage, liquid-level, or
temperature don’t have clearly defined points. In order to measure and work with
analog quantities in the PIC, they must first be converted to digital numbers. Ana-
log-to-digital (A/D) conversion circuits add a whole new dimension to microcontroller
applications. A microcontroller with an internal A/D converter can sense heat, light,
sound level, position, resistance, voltage, current, or many other real-world signals.

The PIC16C711 is equipped with an internal 8-bit, 4-channel A/D converter


that allows it to convert an externally applied voltage between 0V and 5V into an One of the four analog
eight-bit number from 00h to FFh. Using the PIC16C711 costs less than interfacing inputs can be used as an
an external A/D converter to a microcontroller without an A/D such as the PIC16F84. external reference voltage
The PIC16C711 with its built-in A/D converter also provides savings in code size, (Vref), changing the
conversion range to 0V and
circuit board real-estate, and assembly costs.
Vref instead of 0V and 5V,
effectively scaling the
This chapter will explore how to read, scale and display multiple analog voltages analog conversion.
set via the trim pots RA0 and RA1. Analog voltages received from these pots will be
displayed on the LCD as numbers from 0 to 255. One channel will be converted to a
numeric voltage and the other will be displayed as a bar graph on the LED display.

The PIC16C711 A/D Converter


The PIC16C711 has only one A/D converter that is multiplexed to four I/O lines
on Port A as shown below:

The channel select bits


(CHS[1:0]) are part of the
ADCON0 (08h) register,
and the port configuration
bits (PCFG[1:0]) are part
of the ADCON1 (88h)
register.

Chapter 16
©1998 Sirius microSystems Microchip Code 161 A/D Conversion
ADCON0 Register

The two channel select bits CHS1 and CHS0 are part of the ADCON0 (A/D
control 0, address 08h) register and control which PIC I/O pin is connected to the
internal A/D converter. The other bits of the ADCON0 register are shown below:

The input sample is held on The A/D converter is a successive approximation type and uses 10 clock cycles
an internal hold capacitor to complete one conversion. Each conversion clock must take at least 2.0 ms and
during conversion. The should take no more than about 8 ms for best accuracy. The A/D converter clock
minimum and maximum select bits (ADCS1 and ADCS0) select clock rate fed to the A/D converter. The
conversion clock times clock rate can be divided from the oscillator clock in increments of 2, 8 or 32, or be
ensure that the hold
fed from an internal RC oscillator as shown in the chart below:
capacitor has had sufficient
time to fully charge before
conversion and that the Clock Source ADCS1,0
charge does not leak off
2 TOSC 00
during conversion.
8 TOSC 01
32 TOSC 10
RC OSC 11

In our example program, ADCS1 and ADCS0 are set to 10, providing a clock
divider of 32. Using a 10 MHz clock oscillator, we can calculate an appropriate
clock source as shown:

The ADON bit can be used turn the A/D converter on or off. When the A/D
converter is off, power is removed from the A/D converter circuitry, lowering the
PIC’s current consumption. The A/D converter must be turned on, by setting ADON,
before initiating a conversion.

Do not set the GO/~DONE The GO/~DONE bit start the conversion process and also indicates its comple-
bit in the same instruction tion. Setting GO/~DONE starts the conversion, and this bit will remain high during
that sets ADON. conversion. When the conversion is complete, GO/~DONE drops to zero.

ADIF is the A/D conversion complete interrupt flag bit. It gets set when the
conversion is finished and must be cleared in software. Interrupt-driven operation
allows the A/D conversion to take place in the background, or while the processor is
asleep if RCOSC is set as the clock source. The A/D interrupt caused by the comple-
tion of the A/D conversion will wake the processor from sleep.
ADCON0 Register
162 Microchip Code ©1998 Sirius microSystems
ADCON1 Register

ADCON1 contains the two port configuration bits which select not only the
internal or external reference voltage, but also whether Port A inputs are analog or
digital. By default, Port A.0-3 pins are set to analog input on power-up. When using
the LCD or Serial EEPROM library routines with the PIC16C711 it is important to
explicitly set the port configuration bits to digital mode. Note that this is not neces-
sary when using the PIC16F84, as Port A can only be digital. The table below shows
how PCFG1,0 set Port A pins to analog or digital and select the analog reference as
either VDD or an external reference applied to RA.3.

PCFG1,0 RA.0 RA.1 RA.2 RA.3 REF


00 Analog Analog Analog Analog VDD
01 Analog Analog Analog VREF RA.3 The external reference
voltage applied to VREF
10 Analog Analog Digital Digital VDD should be within 3V and 5V.
11 Digital Digital Digital Digital VDD For best accuracy, connect
a dedicated voltage
reference to this pin, not
just a resistor voltage
Measuring Voltage using the A/D Converter divider.

The VMETER.ASM program uses the PIC16C711 as a voltmeter to measure


and display the voltage supplied by potentiometers RA.0 and RA.1. VDD is used as
VREF, the analog reference voltage.

For any voltage from 0V to 5V the binary value will be a corresponding number
from 00h to FFh, or from 0 to 255. VMETER.ASM displays the raw binary data A voltmeter to connected to
measured from each channel on line 1 of the LCD. Since most applications require measure the voltage of
more than just a raw number, VMETER.ASM demonstrates two methods of scaling. RA.0 or RA.1 will not show
the same value as on the
First, the RA.0 voltage is scaled in software from 0.00 to 5.00 and displayed on the
LCD, representing the actual voltage from 0V to 5V. Second, the RA.1 voltage is display. RA.0 and RA.1
serve double-duty as both
scaled and is displayed as an 8-step bar graph on the LEDs.
analog inputs and as
digital outputs for the LCD.
Pull out the VMETER.ASM code as we examine it in detail. The meter will measure the
average of the analog and
The Hardware Equates section begins by setting aside memory locations needed digital signals on these
by the included libraries and variables in VMETER.ASM. Of note are the equates pins.
for BIN2BCD.LIB.
;Equates used by BIN2BCD.LIB

HighByte DS 1 ;High byte of number


LowByte DS 1 ;Low byte of number

TenThous DS 1 ;Ten thousands BCD digit


ThouHund DS 1 ;Thousands & Hundreds BCD digit
TensOnes DS 1 ;Tens and Ones BCD digit
ShiftCounter DS 1 ;Counter for BCD conversion shifts

Chapter 16
©1998 Sirius microSystems Microchip Code 163 A/D Conversion
BIN2DEC.LIB converted BIN2BCD.LIB converts a 16-bit binary number (stored in the two registers
an 8-bit binary number into HIGHBYTE and LOWBYTE) into a 5-digit BCD number. This 5-digit number is
three separate BCD digits. stored in three locations: TenThous, ThouHund, and TensOnes. The lower 4 bits
BIN2BCD.LIB converts a (lower nybble) of TensOnes contains the least significant BCD digit, the upper nybble
16-bit number into five
contains the next most significant digit, and so on for ThouHund, and TenThous.
BCD digits. BIN2BCD.LIB
is used here because
VMETER.SRC works with The Software Equates section defines constants that are used in the program.
values larger than 8 bits
when scaling voltages. Initialization begins at address 0000h and continues after the included library
files. The LCD71.LIB subroutine library makes its first appearance here. Remember
that the PIC16C711 powers up with Port A in analog input mode. LCD71.LIB is a
variant of LCD.LIB where the LCD_Port subroutine configures Port A for digital
output. The Initialize routine continues by displaying static text on the LCD.

Main ;Configures A-D converter by initializing Port A to be


;analogue intsead of digital, setting the clock divider,
;and selecting the A-D channel.

CALL AD_Port ;Initialize A-D converter & Port A

Main begins by calling the AD_Port initialization subroutine in ATOD.LIB.

AD_Port ;Initializes ADCON1 for analog input on RA0 and RA1 with
;VDD as the voltage reference and turns A/D converter on.

BSF RP0 ;Select memory page 1


MOVLW 00000011b ;OR this byte with TRISA to enable
IORWF TRISA ;required analog pins as inputs
MOVLW 02h ;Make RA0 and RA1 analog inputs by
MOVWF ADCON1 ;writing this byte to ADCON1 (88h)
BCF RP0 ;Back to page 0
BSF ADON ;Turn A/D converter on
RETURN
From ATOD.LIB
AD_Port first sets RA.0 and RA.1 as input pins by ORing the literal 00000011b
with TRISA. Now that RA.0 and RA.1 are inputs, the MOVLW 02h into ADCON1
sets RA.0 and RA.1 as analog inputs. Notice that these two steps set only RA.0 and
RA.1 as analog inputs—the other Port A bits are left unchanged in case they were
ATOD.LIB does not turn off previously set as digital I/O. Finally, BSF ADON turns on the A/D converter in
the A/D converter. For low preparation for a conversion.
current consumption you
may wish to turn the A/D
MOVLW ADCLK32 ;Get clock divider for high speed
off after the conversion is CALL AD_Clock ;from ATOD.lib and set A-D
complete (just remember to
turn it on again for the next
conversion).
The MOVLW ADLCK32 and CALL AD_Clock instructions load the clock di-
vider selection bits ADCS0 and ADCS1. ATOD.LIB equates ADCLK2, ADCLK8,
ADCLK32 and ADCLKRC to 2TOSC, 8TOSC, 32TOSC and RCOSC, respectively.

AD_Clock ;Sets ACDS0 and ADCS1 bits in ADCON0 based on the number
;in W. Load W with a clock divider constant from the
;list, above. Read ADRES before calling AD_Clock.

MOVWF ADRES ;Use ADRES as temporary storage


MOVLW 3Fh ;Load W with 0011 1111
ANDWF ADCON0,1 ;AND with ADCON0 to clear high bits
MOVF ADRES,0 ;Get clock divider bits from ADRES
IORWF ADCON0,1 ;OR with ADCON0 to set clock bits
RETURN
From ATOD.LIB
Measuring Voltage
using the A/D 164 Microchip Code ©1998 Sirius microSystems
The AD_Clock subroutine uses the A/D conversion result register, ADRES (09h), ADRES in the ’711 along
as a temporary register to store the clock divisor constant that was held in W when with EEDATA and EEADR
AD_Clock subroutine was called. The W register is then available for the ANDLW in the ’84 can be used as
3Fh operation that is needed to clear the ADCS0 and ADCS1 bits without affecting general purpose RAM
registers.
the lower six bits. After clearing the two ADCS bits W is reloaded with the clock
divisor from ADRES before the IORWF ADCON0,1 operation which copies the
ADCLK32 constant into the ADCS0 and ADCS1 bits without corrupting the bottom
six bits in ADCON0. By using ADRES for temporary storage, the ATOD.LIB rou- When the conversion is
tines use none of the standard RAM registers (0Ch to 2Fh) as variables. finished, be sure to read the
contents of ADRES before
calling the AD_Clock or
MOVLW ADCH0 ;Get channel 0 constant and
CALL AD_Channel ;set A-D channel AD_Channel subroutines.
Both of these subroutines
use ADRES for temporary
Since we would like the first A/D conversion to retrieve the voltage supplied by
storage and will wipe out
RA.0, MOVLW ADCH0 and CALL AD_Channel select channel 0 as the A/D input. your conversion result.

AD_Channel ;Sets CHS0 and CHS1 bits in ADCON0 based on the number in
;W when AD_Channel was called. Load W from channel constants
;list, above. Read ADRES before calling AD_Channel.

MOVWF ADRES ;Use ADRES as temporary storage


MOVLW 11100111b ;Load W with 1110 0111 and
ANDWF ADCON0,1 ;AND with ADCON0 to clear CHS0/1
MOVF ADRES,0 ;Get channel select bits from ADRES
IORWF ADCON0,1 ;OR with ADCON0 to set channel bits
RETURN From ATOD.LIB

Once again, ADRES is used to store W while an AND operation clears the
CHS0 and CHS1 bits in ADCON0. After the contents of ADRES are reloaded into
W, they are ORed with ADCON0 to set the requested A/D channel. ATOD.LIB
predefines ADCH0, ADCH1, ADCH2 and ADCH3 as valid A/D inputs.

MOVF Bargraph,W ;Display Bargraph value on LEDs while


MOVWF PORTB ;waiting for next conversion

Call Delay_5ms ;Wait for track & hold to settle


CALL AD_Poll ;Start conversion, & wait until done
MOVF ADRES,W ;Load conversion result into W and
MOVWF Analog0 ;save in Analog0 for voltage display

By this point, the A/D inputs have been configured, the A/D clock divisor has
been selected and the A/D channel has been chosen. Instead of initiating an A/D
conversion, the program first moves the contents of the Bargraph register to Port B
and then calls a 5 ms delay routine. There are two reasons that this was done.

First, since Port B is shared with the LCD, LED flicker occurs whenever the The first time the Main
LCD is accessed. In order to minimize LED flicker, writing the Bargraph value to routine runs, Bargraph
the LED before the CALL to Delay_5ms ensures that the LEDs will display undis- contains 00h. Subsequent
turbed for 5 ms. Second, the PIC-MDS has a 1kW resistor in series with the loops through main will
potentiometers connected to RA.0 and RA.1. These resistors reduce the effects of display the bargraph value
equivalent to RA.1’s
the potentiometers RA0 and RA1 on Port A when it is used as a digital I/O port.
setting.
Unfortunately, the resistors also increase the time constant of the internal hold ca-
pacitor, increasing the time required to charge the capacitor to the input voltage. The
5 ms delay (part of LCD71.LIB) provides more than enough time to charge the hold
capacitor, and is a convenient delay.
Chapter 16
©1998 Sirius microSystems Microchip Code 165 A/D Conversion
Once the 5 ms delay finishes, the CALL to AD_Poll initiates the conversion.

AD_Poll ;Sets GO_DONE bit in ADCON0 to start the A/D conversion


;and keeps polling the bit until the conversion is
;complete. Get the result of the conversion from ADRES.

BSF GO_DONE ;Start A/D conversion


:Loop BTFSC GO_DONE ;Check GO_DONE for end of conversion
GOTO :Loop ;and keep checking until done
From ATOD.LIB RETURN

AD_Poll sets the GO/~DONE bit in ADCON0, and repeatedly loops until it
goes low approximately 3.2 ms later. When GO/~DONE goes low, the conversion
result is available in ADRES (09h).

For interrupt-driven operation you would only need to set the GO/~DONE bit
after enabling A/D interrupts (see Chapter 11). When the conversion is done, the
ADIF flag in ADCON0 is set, and your interrupt service routine can take over.

On return to VMETER.ASM, the result in ADRES is immediately stored in


Analog0 for later processing. Then channel 1 is sampled in the same way as channel
0 using the following code.

MOVLW ADCH1 ;Get channel 1 constant and


CALL AD_Channel ;set A-D channel
MOVF Bargraph,W ;Display Bargraph value on LEDs while
MOVWF PORTB ;waiting for next conversion

CALL Delay_5ms ;Wait for track & hold to settle


CALL AD_Poll ;Start conversion, & wait until done
MOVF ADRES,W ;Load conversion result into W and
MOVWF Analog1 ;save in Analog1

After both channels have been sampled, the following code displays the raw
value of channel 0 on the LCD.

CALL LCD_Port ;Reconfigure Ports for LCD use


MOVLW LCDLine1+Ch0_Data ;Send channel 0 data starting
CALL LCD_Reg ;address to LCD as a command
MOVF Bargraph,W ;Display Bargraph value on LEDs while
MOVWF PORTB ;waiting for bcd conversion
MOVF Analog0,W ;Load channel 0 result into W and
MOVWF LowByte ;save into LowByte register
CALL Display_Num ;Let Display_Num display BCD digits

First, the CALL to LCD_Port (in LCD71.LIB) reconfigures the analog input
pins on Port A to digital output pins in order to provide the LCD control signals.
MOVLW LCDLine1+Ch0_Data loads W with the LCD line 1 starting DDRAM
location and offsets it by the Ch0_Data software equate at the start of this program.
This ensures that any LCD data is displayed after the “Ch0:” text.

After the CALL to LCD_Reg, the LED bar graph on Port B reflects the last
number sent to the LCD. The subsequent MOVF Bargraph,W and MOVWF PORTB
rewrites the last Bargraph value to the LEDs.

Next, the value in Analog0 needs to be converted to three ASCII digits for dis-
play. After moving Analog0 to the LowByte register, the CALL to Display_Num
converts the raw 8-bit result to ASCII and displays it on the LCD.
Measuring Voltage
using the A/D 166 Microchip Code ©1998 Sirius microSystems
Display_Num ;Converts the 8-bit A/D result to BCD and displays the
;hundreds, tens and ones digits on the LCD at the current
;LCD cursor address.

CLRF HighByte ;Clear HighByte before converting


CALL BIN_BCD ;result to BCD
MOVF ThouHund,W ;Load thousands & hundreds digits in
ANDLW 0Fh ;W and clear thousands nybble
ADDLW 30h ;Add ASCII offset to generate number
CALL LCD_Data ;and display on LCD
SWAPF TensOnes,W ;Load tens & ones digit in reverse
ANDLW 0Fh ;and clear ones nybble
ADDLW 30h ;Add ASCII offset to generate number
CALL LCD_Data ;and display on LCD
MOVF TensOnes,W ;Load tens and ones digits in
ANDLW 0Fh ;W and clear tens nybble
ADDLW 30h ;Add ASCII offset to generate number
CALL LCD_Data ;and display on LCD
RETURN ;Return when done

Before calling BIN_BCD (in BIN2BCD.LIB) the Display_Num subroutine clears


HighByte. As mentioned previously, BIN_BCD converts the 16-bit word stored in
the HighByte and LowByte registers into five BCD digits—necessary to represent
numbers up to 65,535. Since we only need 8-bit quantities to represent the A/D
result (0-255) we need to ensure that HighByte is clear. Later on, a call to BIN_BCD
does put numbers into HighByte.

Once the conversion to BCD is complete, each of the three least significant
digits—hundreds, tens and ones—is processed in the same way. First, the BCD digit
is extracted from the byte using an AND operation. For the Hundreds digit, stored in
the lower nybble of ThouHund, ANDLW 0Fh clears the upper nybble leaving just SWAPF TensOnes,W not
the number of hundreds. Next, ADDLW 30h adds the ASCII offset to the number to only swaps the high and
convert it to an ASCI code and finally, CALL LCD_Data displays the digit at the low nybbles, but also loads
current LCD DDRAM address. The routine returns control to Main once all three the result into W.
digits have been displayed.

MOVLW LCDLine1+Ch1_Data ;Send channel 1 data starting


CALL LCD_Reg ;address to LCD as a command
MOVF Bargraph,W ;Display Bargraph value on LEDs while
MOVWF PORTB ;waiting for bcd conversion
MOVF Analog1,W ;Load channel 1 result into W and
MOVWF LowByte ;save into LowByte register
CALL Display_Num ;Let Display_Num display BCD digits

The next section of Main repeats the above process to display the raw channel 1
conversion result on the LCD.

MOVLW LCDLine2+Ch0_Volts ;Send channel 0 voltage starting


CALL LCD_Reg ;address to LCD as a command
MOVF Bargraph,W ;Display Bargraph value on LEDs while
MOVWF PORTB ;waiting for scaling
CALL Scale_Voltage ;Convert Ch.0 result to voltage and
CALL Display_Volts ;display the result on the LCD

The code above displays the result of the channel 0 conversion as a voltage.
This subroutine is very much like the routines that prepare the LCD to display the
raw channel data. The LCD DDRAM address is loaded, and Bargraph updates the
LEDs to overwrite the LCD command that would otherwise remain displayed on the
LEDs. The CALL to Scale_Voltage converts the 0-255 result into a 0V - 5V value as
shown in the source code on the next page.
Chapter 16
©1998 Sirius microSystems Microchip Code 167 A/D Conversion
Scale_Voltage ;Scales the result of the A/D conversion such that there are
;only 251 states instead of 256. This way the result can be
;multiplied by two to give a result from 0 to 500 representi
;a voltage of between 0.00 and 5.00 volts. For display, a
;decimal point is just inserted after the first digit by the
;Display_Volts subroutine.

MOVF Analog0,W ;Load W with the A/D result and


SUBLW 250 ;check if it’s greater than 225 by
BTFSS C ;testing the Carry flag
DECF Analog0 ;If so, subtract one from the result
MOVF Analog0,W ;Repeat the above process, comparing
SUBLW 200 ;the A/D result with successively
BTFSS C ;smaller values
DECF Analog0
MOVF Analog0,W
SUBLW 150
BTFSS C
DECF Analog0
MOVF Analog0,W
SUBLW 100
BTFSS C
DECF Analog0
MOVF Analog0,W
SUBLW 50
BTFSS C
DECF Analog0

CLRF HighByte ;Clear HighByte register for multiply


MOVF Analog0,W ;Reload W with scaled result and
MOVWF LowByte ;save result in LowByte register
BCF C ;Clear Carry before multiplying by 2
RLF LowByte ;Shift LowByte left to multiply
RLF HighByte ;Shift Carry into HighByte
CALL BIN_BCD ;and convert to BCD
RETURN ;Return when done

A value that varies from 0 to 250 is easier to work with than a value that varies
from 0 to 255. Simply subtracting 5 from any conversion result limits the maximum
value to 250, but introduces very large errors for small results. For example, for a
conversion result of 10, subtracting 5 results in a 50% error. Obviously, for results of
5 or less, the error would be unacceptably large. However, if we distribute the sub-
traction as five individual subtractions of 1, spread out over the range of possible
values, we can limit the error to no more than 2%. The Scale_Voltage routine
sequentially subtracts one from the conversion result for every multiple of 50 that
the result contains (see the flowchart in the left margin).

Scale_Voltage starts by moving the analog result into W. SUBLW 250 subtracts
W from 250 and clears C (the Carry/Borrow flag) if a borrow occurred. For exam-
This is one way to scale a ple, if W was 255, the subtraction would require a borrow, and C would be cleared.
voltage from a range of 0- BTFSS C checks the state of the Carry/Borrow flag and causes the DECF Analog0
255 to a range of 0-250. instruction to execute whenever a borrow occurs, subtracting one from Analog0.
For more accuracy, you MOVF Analog0,W starts the same process again but with W being compared to
can supply a calibrated 200. In this way, any result over a multiple of 50 has one subtraction performed for
reference voltage to RA.3
each multiple of 50. To see the subtraction take place, examine the LCD as you run
(VREF) and configure the
A/D to accept an external
VMETER.ASM. Turn the RA.0 potentiometer so that the raw data is less than 50,
VREF. and slowly increase the potential on RA.0 watching the voltage on the LCD. For
each increase in the raw data, the voltage increases by 0.02V. As you reach 50, the
voltage display is 1.00V. Increasing RA.0 to 51, the voltage still reads 1.00V, since
a subtraction has taken place. By further increasing RA.0 and you will be able to see
the subtraction take place at result values of 100, 150, 200 and 250.
Measuring Voltage
using the A/D 168 Microchip Code ©1998 Sirius microSystems
To complete the scaling to 5V, the analog result (0-250) is copied into LowByte
and multiplied by two using the RLF LowByte instruction. The following RLF
HighByte instruction rotates the C flag—containing LowByte’s most significant bit
before its rotate—into HighByte in preparation for the conversion to BCD. The
contents of HighByte and Lowbyte now hold a 9-bit number that ranges from 0 to
500. To display the calculated voltage, the Display_Volts routine inserts a decimal
point after the hundreds digit of the BCD result.

Display_Volts ;Displays the result of the BCD scaled voltage as a decimal


;number at the current LCD cursor address.

MOVF ThouHund,W ;Load thousands & hundreds digits in


ANDLW 0Fh ;W and clear thousands nybble
ADDLW 30h ;Add ASCII offset to generate number
CALL LCD_Data ;and display on LCD
MOVLW ‘.’ ;Load W with ASCII code for “.”
CALL LCD_Data ;and display on LCD
SWAPF TensOnes,W ;Load tens & ones digit in reverse
ANDLW 0Fh ;and clear ones nybble
ADDLW 30h ;Add ASCII offset to generate number
CALL LCD_Data ;and display on LCD
MOVF TensOnes,W ;Load tens and ones digits in
ANDLW 0Fh ;W and clear tens nybble
ADDLW 30h ;Add ASCII offset to generate number
CALL LCD_Data ;and display on LCD
MOVLW ‘V’ ;Load W with ASCII code for “V”
CALL LCD_Data ;and display on LCD
RETURN ;Return when done

The Display_Volts routine works in the same way as Display_Num, other than
adding a decimal after the first number, and the letter ‘V’ after the last number.
Adding ASCII characters is as easy as enclosing them in quotation marks. The as-
sembler converts the letter within the quotes to its ASCII value for display.

RRF Analog1 ;Divide channel 1 result by 2


RRF Analog1 ;again = divide by 4
RRF Analog1 ;again = divide by 8
RRF Analog1 ;again = divide by 16
RRF Analog1 ;again = divide by 32
MOVLW 07h ;Clear upper 5 bits of result by
ANDWF Analog1,W ;ANDing with zero, leave 3 bit result
Like the Scale_Voltage
CALL Bar_Table ;in W to look up 1 of 8 patterns subroutine, the repeated
division by two results in a
decrease in conversion
The next part of the Main routine displays the RA.1 input as a bargraph. To do accuracy. In this case the
this, the 8-bit conversion result is repeatedly divided by two in order to produce a 3- accuracy decreases from 1
bit number. Since three bits corresponds to eight binary states, the three bit number part in 256 to 1 part in 8.
is used to light each of the eight LEDs according to a look-up table in Bar_Table.

The successive RRF Analog1 operations, above, perform the division by two.
Since rotate operations are circular, and rotate bits through C and back into the
register, MOVLW 07h and ANDWF Analog1,W are required to clear the upper five
bits of Analog 1 before calling Bar_Table. In Bar_Table, an ADDWF PCL instruc-
tion uses the 3-bit conversion result to offset the program counter, returning a con-
stant that illuminates the appropriate segments of the LED bar.

Bar_Table ADDWF PCL ;PCL=PCL+W to generate offset


RETLW 10000000b ;Bottom LED on
RETLW 11000000b ;Bottom 2 LEDs
...
Chapter 16
©1998 Sirius microSystems Microchip Code 169 A/D Conversion
MOVWF PORTB ;Output LED pattern to LED bar
MOVWF Bargraph ;and to Bargraph register for update

CALL AD_Delay ;Wait to minimize display flicker


GOTO Main ;and do it again

Finally, after copying the LED bar graph constant to Port B, the bar graph con-
stant is copied to the BarGraph register. As shown earlier, the BarGraph register
refreshes the LEDs with the correct LED pattern after the LCD routine writes to Port
B. Remember, the LEDs display all Port B activity and we try to minimize LED
flicker by overwriting the LCD commands as soon as possible.

Before the Main routine loops back to the beginning, there is a CALL to
AD_Delay. This extra 25 ms delay gives the LCD some time to settle, and helps to
minimize LED flicker.

Chapter Summary
Analog-to-digital conversion allows microcontrollers to measure and control
real-world applications that supply a varying voltage to the processor. The A/D con-
verter in the PIC16C711 will convert any voltage into an 8-bit number within two to
eight microseconds. Up to four analog sources can be connected to Port A of the
PIC16C711, and the single internal A/D converter can process the voltage on each
channel independently.

For many uses, scaling is required to convert the A/D result into a more useful
form. Scaling usually results in a loss of conversion accuracy, which is typically not
critical for simple control tasks. Supplying the A/D converter with an external preci-
sion reference voltage can eliminate the need for software scaling, improving con-
version accuracy.

In the PIC-MDS, the Port A pins are shared between digital and analog devices.
Resistors isolate the analog potentiometers from Port A, increasing the time con-
stant required to charge the internal A/D hold capacitor. For high speed conversions,
it is necessary to design a board that dedicates the Port A pins to the analog devices
connected to them.

Although this chapter certainly gives you a start on A/D conversion, many vari-
ables can affect the quality of a conversion result. Fortunately, there are many good
books and articles available that provide a more thorough look at A/D conversion.

Measuring Voltage
using the A/D 170 Microchip Code ©1998 Sirius microSystems
Questions
1. What is the percentage accuracy of an 8-bit conversion? How does this com-
pare to the percentage accuracy of a 4-bit conversion?

2. List the steps necessary to initialize the PIC16C711 for conversion with an
external VREF. If only one analog input is required, can the remaining Port A
pins be used as digital I/Os?

3. How would the use of a 4 MHz crystal affect the operation of the A/D con-
verter? What about a 1 MHz crystal?

4. Calculate the maximum possible sampling frequency for a software loop that
converts an input, compares the result with a threshold constant, and repeats
the loop until the threshold has been exceeded. Assume 4 MHz operation.

5. A liquid level sensor returns an analog voltage from 0V to 5V corresponding


to a liquid level from 0mm to 1000mm. Using the internal 8-bit A/D con-
verter, what is the minimum resolution we could hope to achieve? What is the
most likely practical resolution?

Poor Tony Spicuzzi spent 10 years and thousands of dollars refining “Spicuzzi’s Jacuzzi Temp-o-
matic” temperature controller only to find out it can now be replaced with a $5.00 PIC.

Chapter 16
©1998 Sirius microSystems Microchip Code 171 A/D Conversion
Assignment
1. Modify the VMETER.ASM program to update the bar graph and LCD only if
one of the analog voltages changes.

2. Write a program that displays the A/D result on the bar graph using 9 LEDs.

3. Create the flowchart for a program subroutine that would display the leading
zeros in the raw A/D result as blanks.

4. Write a program to display the voltage on one of the potentiometers as a per-


centage, where 0% equals 0V and 100% equals 5V.

5. Write a program that flashes an alarm LED when an input threshold is ex-
ceeded. Use one potentiometer to set the threshold value, and the other as the
input being checked.

Assignment
172 Microchip Code ©1998 Sirius microSystems
Interfacing to a
17 Serial EEPROM

The serial EEPROM, as its name suggests, is a nonvolatile electrically erasable


programmable memory that is accessed serially. Although interfacing to a serial
memory is slower and somewhat more complicated than interfacing to a conven-
tional memory, serial EEPROMs have the advantage of requiring very few signal
and control lines. For example, a non-serial 256 X 8-bit memory would require eight
address lines, eight data lines and a few control signals, easily exceeding the number
of I/O lines on a small microcontroller. The 93LC56 (256 X 8-bit) serial EEPROM SEEPROM.LIB also
on the PIC-MDS is an eight-pin chip that uses only three wires to interface to a supports the 512 X 8-bit
microcontroller. 93LC66 SEEPROM.

The 93LC56 Serial EEPROM


The 93LC56 is one of a family of serial EEPROMs (SEEPROMs) manufac-
tured by Microchip Technology, Inc. The 93LCxx family uses a 3/4-wire interface
known as Microwire®, and range in memory capacity from 128 X 8-bits to 512 X 8-
bits. The schematic segment below shows the interface connection more clearly.

The 3/4-wires used in


the interface are pins 1-4.
Chip select (CS) is brought
high to select the device.
Clock (CLK) is used to
synchronously clock data
in and out of the serial
EEPROM at a rate of up to
2 MHz. Data in (DI) and
During reads, a dummy 0
data out (DO) carry data in appears on DO while the
and out of the SEEPROM last address bit is being
and can be tied together, clocked into DI. R11
hence the name 3/4-wire in- ensures that DI remains
terface. Resistor R11 pre- valid. See the 93LC56 data
vents a short circuit condi- sheets for more informa-
tion during reads. tion.
Chapter 17
©1998 Sirius microSystems Microchip Code 173 Interfacting to a
Serial EEPROM
The Serial EEPROM Data Frame
Storing or retrieving SEEPROM data requires the transmission of a data frame
A READ operation obvi- of either twelve or twenty data bits based on the type of SEEPROM instruction.
ously involves receiving the
Data bits after transmitting
the first part of the frame.

The serial data frame begins with a start bit (S). Unlike RS-232 serial communi-
Timing is not critical in cation—asynchronous serial communication—the start bit does not signify the start
synchronous communica- of a timed data transmission. Instead, the SEEPROM uses synchronous communica-
tion. In fact, you can stop tion in which the start bit (applied to DI) must be held high during a rising clock pin
the clock in the middle of a (CLK) transition. The remaining frame bits are clocked in sequentially as shown.
transmission and continue
later—something that
would guarantee data loss
in asynchronous communi-
cation.

OP1 and OP0, the next two bits that are clocked in, are op-code bits that select
one of the SEEPROM instructions to be performed.

The X/A8 through A0 bits specify the address on which the instruction should
act, and make up the rest of the non-data instruction frame. The nine address bits
allow for 512 address locations. Since the 93LC56 SEEPROM only has 256 address
locations, the X/A8 bit holds a dummy value in order to keep the data frame size
constant.

Finally, D7 through D0 provide data if needed by the instruction, or represent


data clocked out of the SEEPROM during a Read.

Serial EEPROM Instructions


The 93LCxx family of SEEPROMs are controlled by seven instructions:

EWDS • Erase Write Disable, prevents any changes to the SEEPROM contents
WRAL, WRITE and READ and is the power-up default setting.
require a full instruction WRAL • Write All, fills all memory locations with the specified data.
frame to be transmitted. All ERAL • Erase All, erases all memory locations.
of the other instructions EWEN • Erase Write Enable, allows changes to the SEEPROM memory.
require a partial data WRITE • Writes the supplied data to the specified address.
frame, since no data is READ • Reads the data from the specified address.
required.
ERASE • Erases the contents of the specified address.

For data protection during power-up conditions, the default SEEPROM power-
up state is EWDS. Before writing or erasing any data in the SEEPROM, an EWEN
instruction must be issued. It’s highly recommended to finish a write with EWDS,
which prevents any data modification during power-down or brown-outs.
The 93LC56 Serial
EEPROM 174 Microchip Code ©1998 Sirius microSystems
Using The SEEPROM
SEETEST.ASM is a utility to test and program 93LC56/66 SEEPROMs. It dis-
plays a SEEPROM address and its contents on the top line of the LCD, and prompts
for the four buttons in the top row of the keypad on the bottom line of the LCD.
Using the buttons you can increment or decrement the SEEPROM address, select a
specific address, or change the contents of any address. Assemble, download and
run SEETEST.ASM to try it out for yourself.

Pull out SEETEST.ASM as we explain its operation. To begin, lets examine


some noteworthy equates.

Addrh DS 1 ;SEEPROM high address byte


Addrl DS 1 ;SEEPROM low address byte

;Equates required by SEEPROM.LIB

SEEAddrh DS 1 ;SEEPROM high address byte


SEEAddrl DS 1 ;SEEPROM low address byte
SEEClock DS 1 ;SEEPROM clock counter register
SEEData DS 1 ;SEEPROM data storage byte

Addrh and Addrl, as the comments suggest, are registers used to hold the high
and low address bytes of the current SEEPROM address. SEEPROM.LIB uses simi-
lar equates, namely SEEAddrh and SEEAddrl. During SEEPROM access, the con-
tents of the SEEAddrh and SEEAddrl registers are shifted out to the SEEPROM
with the result that after the shift, these registers no longer contain the original ad- After every SEEPROM
dresses. Since the SEETEST program needs to know the current SEEPROM ad- access, SEEAddrh and
dress (so that it can be incremented or decremented), and SEEAddrh and SEEAddrl SEEAddrl are cleared by
are lost in the shift, Addrh and Addrl maintain a pointer to the current SEEPROM SEEPROM.LIB
address.

The SEEClock register is used to count the number of data bits transmitted in
each serial frame. SEEData stores the data to be written to the SEEPROM or con-
tains the data after a READ instruction.

Update_Status ;Displays the current SEEPROM address and data on the top li The Update_Status routine
;of the LCD and the Menu options on the bottom line. is the main program
routine in SEETEST.ASM.
.
. It always displays the
MOVF Addrh,W ;Load W with high address byte address and the data
ANDLW 01h ;Clear upper seven bits stored in that address on
CALL Hex_Remap ;and convert to ASCII for LCD
line one of the LCD, and
CALL LCD_Data ;and display on LCD
displays the prompts on
line two of the LCD.
The first part of the Update_Status routine displays the words “Addr:” and “Data:”
on the top line of the LCD, and positions the LCD cursor after the word “Addr:” in
preparation for displaying the actual memory address. MOVF Addrh,W loads the
upper SEEPROM address byte (in this case, 0, as Addrh was cleared during initiali-
zation) into W. ANDLW 01h clears the upper seven bits of W, isolating the A8
address bit. The call to Hex_Remap converts the value in W to a single ASCII char-
acter code in preparation for the display of the first address digit on the LCD. The
CALL to LCD_Data displays the first digit of the SEEPROM address as a hexadeci-
mal digit on the LCD.
Chapter 17
©1998 Sirius microSystems Microchip Code 175 Interfacting to a
Serial EEPROM
SWAPF Addrl,W ;Switch Addrl nybbles and copy to W
ANDLW 0Fh ;Clear upper nybble before
CALL Hex_Remap ;converting to ASCII for
CALL LCD_Data ;display on LCD

The next lines of the program display the second hexadecimal address digit
contained in the upper nybble of Addrl. First, Addrl is copied into W with its upper
and lower nybbles exchanged. Next, ANDLW 0Fh wipes out the top four bits, pre-
paring the value for the call to Hex_Remap. Finally, CALL LCD_Data displays the
ASCII digit corresponding to the hexadecimal address’ second digit.

MOVF Addrl,W ;Load W with low address byte again


ANDLW 0Fh ;Clear upper nybble before
CALL Hex_Remap ;converting to ASCII for
CALL LCD_Data ;display on LCD

A similar process is used to display the last hexadecimal digit of the SEEPROM
address. After these lines execute, the three digits of the current SEEPROM address
have been displayed on the LCD. The next section of the code reads the SEEPROM
and displays the contents of the current address on the LCD after the word “Data:”.

CALL SEE_Port ;Set up Port A for SEEPROM use


MOVF Addrl,W ;Copy low address byte to
MOVWF SEEAddrl ;SEEPROM low address byte
MOVF Addrh,W ;Copy high address byte to
MOVWF SEEAddrh ;SEEPROM high address byte
MOVLW SEERead ;Send SEEPROM Read byte command
CALL SEE_Command ;to SEEPROM

CALL SEE_Port readies the three I/O lines the PIC will use to communicate
with the SEEPROM. The I/O lines connecting to the SEEPROM chip select and
clock are set to output, and the line connected to data is set to input.

As explained previously, Addrl and Addrh are copied into SEEAddrl and
SEEAddrh in preparation for the read command. The read is initiated by passing the
SEERead value (from the EQUates) through W to the SEE_Command subroutine.

If you find your brain The CALL to SEE_Command begins a process of parsing and shifting the serial
swelling as it did in Chap- data frame to the SEEPROM. Remember that the SEEPROM data frame contains a
ter 12, remember that you command op-code, address bits, and, if necessary, data bits. The SEEPROM re-
don’t need to know exactly sponds to seven command instructions, as shown in the chart on the next page.
how the subroutines work Notice that the serial data frame diagram shown earlier indicates that only two bits
in order to use them. It’s are used to encode SEEPROM commands. Clearly, two bits are insufficient to en-
when you need to interface
code seven commands. The way in which the extra commands are encoded, as shown
the PIC to a new peripheral
that you’ll need to figure
by the chart, is to extend the op-code bits whenever the op-code is 00. XOP0 and
out all of its idiosyncrasies. XOP1 represent the extended op-code bits.
For those of you still
interested, read on!
In extended instructions,
XOP1 and XOP0
overwrite the X/A8 and
A7 bits. Both instruc-
tions remain the same
overall length.
Using the SEEPROM
176 Microchip Code ©1998 Sirius microSystems
Although the op-code is sometimes extended with two extra bits, the data frame
itself cannot change in length. The extended op-code bits simply overwrite the ad-
dress bits X/A8 and A7. Fortunately, the four commands encoded by extended op-
code bits are global commands and do not require a specific address. The remaining
address bits are sent merely to maintain the required 12- or 20-bit data frame size.

SEEPROM instruction
formatting.

S - Start bit OPn - non-extended op-code bits XOPn - extended op-code bits
7B - 7-bit address flag X/A8 - dummy or A8 address bit A7-A0 - address bits

The 7B bit in the chart represents the 7-bit address flag used only within
SEEPROM.LIB. When this bit is set, it indicates that extended op-code bits are
present, and that only seven more dummy bits in the address field are needed to
complete the 12- or 20-bit data frame. The 7B flag was added to make command
parsing within SEEPROM.LIB easier and is not transmitted to the SEEPROM.

Now that we know how op-codes encode the instruction sent to the SEEPROM,
we’ll examine the SEEPROM.LIB code that assembles the data frame. The first
data that will be displayed by SEETEST.ASM resides at address 000h. The code on
the previous page would have loaded SEEAddrh and SEEAddrl as shown below:

Recall from the previous page, that just before the Call to SEE_Command, W
was loaded with the constant SEERead (C0h). The first instruction in SEE_Command
ORs the SEERead constant into SEEAddrh, and the result is shown below the code.
IORWF copies W into
SEE_Command ;This subroutine parses the SEEPROM command op-code, compl
.
SEEAddrh without chang-
. ing the A8 bit.
IORWF SEEAddrh ;Store command to top bits of SEEAd
From SEEPROM.LIB

Chapter 17
©1998 Sirius microSystems Microchip Code 177 Interfacting to a
Serial EEPROM
The reason for copying the SEEPROM command into the top of the SEEAddrh
register may not be immediately apparent. Since only the least significant bit of
SEEAddrh is required to hold A8, the remainder of the register is empty. We use the
upper four bits of SEEAddrh to build the first part of the serial data frame. Remem-
ber, a SEEPROM transmission must be either 12- or 20-bits. The upper 4 bits of
SEEAddrh, plus all 8-bits of SEEAddrl complete a 12-bit data frame. A 20-bit frame
adds eight more data bits, stored in SEEData. The only thing left to do, to make the
transmission of the start of the
There is actually another data frame easier, is to move ei-
reason for moving A8 ther A8 to the upper nybble of
instead of the other three SEEAddrh, or to move the Start
bits. For extended op- Bit, and op-code bits to the
codes, we can just add the
lower nybble so that they can
extended bits after the op-
code bits without worrying
easily be shifted in succession.
about whether to shift Since moving A8 requires only
three or five command bits the movement of one bit, not
down to beside A8. But three, we do just that. The end
then, having five command result is illustrated at left:
bits requires that only
seven address bits follow The flowchart below shows how commands are decoded by SEE_Command in
(to complete the 12-bit SEEPROM.LIB. In addition to decoding the instruction, SEE_Command also as-
frame), complicating things sembles the data in SEEAddrh and SEEAddrl in preparation for serially shifting the
even more. And, to confuse
data frame out to the SEEPROM. See the pull-out section for complete details.
you even further, none of
this is actually done in this
order. But, the flowchart
will give you an idea of
how we figure out what the
command is, and, since we
know the command, how
many bits to shift.

This flowchart shows the


process of SEEPROM
command decoding in
SEEPROM.LIB.

Using the SEEPROM


178 Microchip Code ©1998 Sirius microSystems
Calling SEE_Command not only parses the command and shifts out the serial
data frame, but also determines whether or not to use the SEEData register for Reads
and Writes. If a Write or Write All command is sent, the contents of SEEData are
also shifted out by SEE_Command. In this case, however, the Read command in-
structs SEE_Command to retrieve the data from the SEEPROM and shift it into
SEEDATA. Once the data from the requested address has been read into SEEData, You do remember that this
the code below displays the contents of SEEData on the LCD. whole discussion started
because of a SEEREAD
CALL LCD_Port ;Set up Ports for LCD use instruction about three
MOVLW LCDLine1+Data ;Set LCD character position to pages back, don’t you?
CALL LCD_Reg ;start of data display area
SWAPF SEEData,W ;Switch nybbles of SEEPROM data to W
ANDLW 0Fh ;Clear upper nybble before
CALL Hex_Remap ;converting to ASCII for
CALL LCD_Data ;display on LCD

MOVF SEEData,W ;Load W with SEEPROM data byte


ANDLW 0Fh ;Clear upper nybble before
CALL Hex_Remap ;converting to ASCII for
CALL LCD_Data ;display on LCD

Since the LCD and SEEPROM share some of the PIC’s PORT A lines it is
necessary to call LCD_Port before setting the LCD cursor position via the Call to
LCD_Reg. Next, the two Data nybbles are displayed in the same way as the address
digits were previously. Now, the line one address and data display is complete.

MOVLW LCDLine2 ;Send LCD line 2 character address


CALL LCD_Reg ;to LCD as a command
MOVLW Menu_Msg ;Load W with Menu message offset
CALL Disp_Message ;and call display message routine

CALL KB_Port ;Set Port B for keypad use


CALL KB_Scan ;and scan keys for key press
MOVF Key,W ;Load Key return code into W
MOVWF KeyTemp ;and save in temporary register

MOVLW 01h ;Copy short key repeat delay into


MOVWF Delay ;Delay register

The next section of code displays the soft function key prompts on line 2 of the
LCD by using a table read—the same manner in which messages have been dis-
played in previous example programs. Then Port B of the PIC is set up for keypad
scanning, and the returned key code is stored in the KeyTemp register. To finish the
Update_Status subroutine, the constant 01h is stored in the Delay register. Delay is
used to count loops for the pause between key repeats if a key is held down, and a
count of 01h represents the short delay between repeats, not the initial long delay.

The Wait_for_Key subroutine checks for a key press in the top row of the key-
pad. These are the keys corresponding to the soft-key prompts. If a key has been
pressed, Wait_for_Key first determines which key has been pressed. For the first Only the first two keys—
two keys, a check is made to determine if this is an initial press, or a key that has ”Dwn” and “Up”—
been held from the previous operation. When the key is first pressed, the Delay implement key repeat. The
counter is set to 20h from 01h. Next, the Repeat_Delay subroutine is called to im- action for the last two keys
plement the key delay. In this case, the delay between an initial key press and the is described in the next
paragraph.
first repeat is thirty-two times longer than the delay between successive repeats.
Following the key delay, the action corresponding to the key press—either
incrementing or decrementing the SEEPROM address—is performed.

Chapter 17
©1998 Sirius microSystems Microchip Code 179 Interfacting to a
Serial EEPROM
The actions resulting from an “Sel” or “Chg” key press are only slightly differ-
ent from the previously described key processing, with the difference being that
these two keys do not implement a key repeat. Instead, pressing the “Sel” key enters
a subroutine that allows a user to immediately enter an address by pressing three
keys, and pressing the “Chg” key allows a user to change the data at the current
address with the next two key presses. The program flow showing the process of key
determination is illustrated in the following flowchart.

Key decoding flowchart.

If the first key is pressed, the Addr_Down subroutine decrements the Addrl
register as long as its value is greater than zero. Likewise, the Addr_Up subroutine
allows the second key to increment the SEEPROM address up to 1FFh.

The “Sel” soft key calls the Addr_Set subroutine. Addr_Set first displays ques-
tion marks and a blinking cursor where the three address nybbles (about to be en-
tered) are displayed. Next, the keypad is configured to obtain the three nybbles needed
in order to define the new address. The subroutine then checks to see if the first
Remember, SEEPROM nybble is either a zero or a one, and loops until a zero or one is entered. Once the
addresses fall within the three nybbles have been read from the keypad, their values are placed in the Addrh
range of 000h to 1FFh. The and Addrl registers. After waiting for the last key to be released, the key 3 decoding
first digit can only be zero routine returns program control to Update_Status, which displays the newly entered
or one. address as well as the SEEPROM memory contents of this address on the display.
Using the SEEPROM
180 Microchip Code ©1998 Sirius microSystems
The Data_Set routine behaves similarly to Addr_Set. The difference is that only
two digits are entered, representing the two data nybbles. The two digits entered by
the user are saved in the SEEData register and are written to the SEEPROM by the
code, below.

CALL SEE_Port ;Configure Port A for SEEPROM


MOVLW SEEEWEN ;Send Erase/Write Enable command
CALL SEE_Command ;to SEEPROM
MOVF Addrl,W ;Copy Addrl byte to
MOVWF SEEAddrl ;SEEAddrl
MOVF Addrh,W ;Copy Addrh byte to
MOVWF SEEAddrh ;SEEAddrh
MOVLW SEEWrite ;Send data write command
CALL SEE_Command ;to SEEPROM
MOVLW SEEEWDS ;Send Erase/Write Disable command
CALL SEE_Command ;to SEEPROM

Writing data into the SEEPROM is just a bit more involved than reading data, if
only because the SEEPROM must be write-enabled first. CALL SEE_Port configures
the PIC to communicate with the SEEPROM. CALL SEE_Command transmits the
SEEEWEN (SEEprom Erase/Write ENable) command, which must precede any erase
or write. SEEAddrl and SEEAddrh are loaded with the current SEEPROM address
from Addrl and Addrh, respectively. Remember that the addresses stored in Addrl
and Addrh are copied to SEEAddrl and SEEAddrh because once the data frame is
shifted out, SEEAddrl and SEEAddrh no longer contain valid addresses. Since the
SEEPROM is now write-enabled, with SEEAddrh and SEEAddrl loaded with the
address to be written to, and with SEEData holding the data to be written, the
SEEWrite command can now be issued. After the write command is complete, the
final command to be sent is SEEEWDS (SEEprom Erase/Write DiSable). For maxi-
mum data integrity, Microchip recommends that SEEPROM erase and write be disa-
bled unless an erase or write is taking place.

After the write operation, program control is once again passed to the
Update_Status routine. When Update_Status displays the current SEEPROM ad-
dress and data, it actually re-reads the contents of the address just written in order to
provide verification that the data entered was correctly stored.

Chapter Summary
Serial EEPROMs are serially-accessed, non-volatile electrically erasable pro-
grammable memories. Their advantage is the use of few I/O lines (typically three or
four), at the expense of a more complex software interface. The PIC-MDS supports
the 93LC56 (256-byte) and 93LC66 (512-byte) Microwire® SEEPROMs.

93LCxx SEEPROMs are controlled by serially transmitting one of seven com-


mands in the form of 12- or 20-bit data frames. SEEPROM commands allow for:
• erase/write enable and disable,
• write, read and erase of specific addresses,
• global write and erase of the entire SEEPROM.

The SEETEST.ASM program allows you to enter and verify data in every memory
location of either the 256- or 512- byte SEEPROMs.
Chapter 17
©1998 Sirius microSystems Microchip Code 181 Interfacting to a
Serial EEPROM
Questions

1. What is the minimum amount of time in which a read can be performed?

2. Why are SEEPROMs said to use a 3/4-wire interface?

3. Examine the data sheets to find the typical length of time taken by an erase or
write command. What is the maximum length of time for a write command?

4. At a typical write cycle time, and assuming that you perform successive writes,
how long would it take to reach the specified endurance of the 93LC56?

Assignment
1. Modify CLOCK.ASM to store the current time whenever a key is pressed, or
an I/O line activates. Store the time that each event occurs in successive
SEEPROM registers. Use SEETEST.ASM to examine the stored times.

Interfacing devices like serial EEPROMs to the PIC can make you feel a bit like
you’re being buried in mounds of new information. Without a good guide or
data sheets, you’ll feel like there are a few crabs in the mound with you!

Questions and As-


signment 182 Microchip Code ©1998 Sirius microSystems
18 The Watch Dog Timer

Watch Dog Timers (WDT) are often a feature of microcontrollers used in real-
time control systems. The main purpose of the WDT is to improve the reliability of
the control software by providing a periodic time-out signal that is used to reset the
PIC—as if the PIC were just powered-up. Instead of allowing the WDT to reset the
processor, however, it is imperative that the software periodically resets the WDT in
order to continue normal program execution. If for some reason the program fails to
reset the WDT, then the WDT time-out signal issues a RESET, restarting program
execution from the power-up state. In the PICmicro family, the WDT can also wake
the PIC from SLEEP. Waking the PIC from sleep does not cause a power-up reset,
but rather operation continues from the instruction following the SLEEP instruc-
tion.

The WDT in the mid-range PICmicro family is a counter fed from a continu-
ously running, on-chip R/C oscillator, which issues a WDT time-out approximately Both Vdd level and tem-
every 18 ms. The WDT time-out signal can be fed to an 8-bit postscaler counter, perature affect the time-out
which can extend the time-out period to approximately 2.3 seconds. The WDT period of the R/C oscillator.
postscaler is also the TMR0 prescaler. Therefore, assigning the postscaler to WDT Because of this, don’t count
prevents TMR0 from using the prescaler, and vice-versa. For clarity, the diagram on the WDT for precise
timing.
below shows only the register bits required in setting the WDT. See Chapter 11 for
a diagram showing how these same bits can select TMR0 options.

In this chapter, we’ll demonstrate two WDT programs. One shows how to use
the WDT to perform a RESET during failed program execution, and the other shows
the use of WDT in waking the PIC from SLEEP.

Chapter 18
©1998 Sirius microSystems Microchip Code 183 Watch Dog Timer
Handling Software Faults using the WDT
The pseudo-code for a typical WDT-enabled program is shown below.

Initialize
Enable WDT

Main Code
.
.
Clear WDT

GOTO Main Code

All WDT-enabled programs must, as part of their regular execution, reset the
WDT periodically. Failure to do this, of course, will result in the WDT timing out
and resetting the PIC. Think of the WDT as a ticking time-bomb. Your program
needs to reset the counter before the counter expires, which would reset your pro-
gram. In a simple program, where all tasks can be completed before a time-out, a
single CLRWDT instruction at the end of your code is sufficient. Otherwise, your
code must ensure that the WDT is cleared before a time-out occurs by including
CLRWDT instructions within all of its subroutines.

The program TIMEOUT.ASM demonstrates not only how the PIC can be reset
by the WDT, but also how to determine whether the reset occurred because of a
WDT time-out or power-up/MCLR (depressing the RESET button). Being able to
distinguish the cause of a reset provides your program with the ability to be self-
monitoring—it can indicate to the user that a software or hardware fault triggered an
unintended reset. Pull out TIMEOUT.ASM as we examine the program flow.

Initialize ;Continue by initializing the LCD display.

CALL LCD_Port ;Set up Ports for LCD use

BTFSS TO ;Check WDT Time Out flag and


GOTO WDT_Message ;skip WDT and LCD init if reset by

After initializing a few registers and the setting up the ports for LCD use,
TIMEOUT.ASM begins execution by determining the cause of the last reset. It does
this by checking TO, the Status register Time Out bit. If TO is set, the PIC restarted
from a power-up or MCLR reset, and execution continues by initializing the WDT.
Of TO is low, a message indicating that the WDT generated the reset is displayed on
the LCD.

Init_WDT CLRWDT ;Clear Watchdog Timer


BSF RP0 ;Select register page 1
MOVLW 0FFh ;Set Option register for WDT with
MOVWF Option ;1:128 prescaler (maximum prescaler
BCF RP0 ;Return to register page 0

Assuming a power-up reset occurred, the program configures the WDT with the
maximum prescaler/postscaler value, which sets a time-out period of approximately
2.3 seconds. Before doing this, the CLRWDT instruction assures us that no unin-
tended resets will occur as the prescaler/postscaler is changed.

Handling Software
Faults using the WDT 184 Microchip Code ©1998 Sirius microSystems
After initializing the LCD and displaying the reset and power-up messages, the
Wait_for_Key subroutine checks for key strokes.

Wait_for_Key ;Checks for a key press. If no keys are pressed, WDT is res

CALL KB_Port ;Set up Ports for keypad scanning


CALL KB_Scan ;Get Key return code
MOVF Key,W ;Load Key code into W to set flags
BTFSC Z ;and check for 0 (0=no key)
GOTO Reset_WDT ;If no key pressed, reset WDT

If no keys are pressed, execution continues by resetting the WDT.

Reset_WDT ;Resets the WDT, setting the TO flag.

CLRWDT ;If no key pressed, clear Watchdog


GOTO Wait_for_Key ;and check for another key press

The Wait_for_Key and Reset_WDT routines form a tight program loop—check


for a key press, and if none, reset the WDT before checking for the next key press.
This loop takes far less time than the WDT time-out period to execute, demonstrat-
ing normal WDT operation.

Key_Release ;Waits for the key to be released. If a key is held for 2-3
;seconds, the WDT will time out since there is not CLRWDT
;instruction inside this wait loop.

CALL KB_Scan ;Scan keys for key press


MOVF Key,W ;Check Key return code for no key
BTFSS Z ;by checking for 0 (0=no key)
GOTO Key_Release ;If key is held, check again

If a key is pressed, program flow remains within the Key_Release subroutine


for the duration of the key press. Note that because there is no CLRWDT instruction
within the Key_Release subroutine, one of two things will happen. If the key is
pressed and released within the WDT time-out period, program operation continues
in the normal way by having the Reset_WDT subroutine reset the WDT, and
Wait_for_Key check for the next key press. If, however, a key is pressed and held
for the duration of the WDT period, the WDT will time-out, clear the Status TO bit,
and issue a device reset. When the PIC restarts program execution, the TO bit check
in the Initialize routine will cause the program to branch to the WDT_Message
routine, which changes the LCD to show the WDT as the cause of the last reset.

The importance of this program is that it demonstrates the additional level of


programming necessary to cope with the potential loss of control due to WDT op-
eration. Put simply, when and if the WDT times out, your program is no longer
doing what you programmed it to do. How gracefully your program recovers from
the unintended reset is now determined by the code that follows your TO bit check.
Complicating the whole matter is that you don’t know at which point your pro-
gram’s execution it was reset. If nothing else, this factor alone necessitates that you
carefully plan your program’s structure in order to accommodate the WDT and en-
sure that your initialization code configures the I/O to a known state, leaving noth-
ing to chance. For all of its benefits, you cannot just enable the WDT because you
think it’s a good idea—your code needs to be written for it!

Chapter 18
©1998 Sirius microSystems Microchip Code 185 Watch Dog Timer
Enabling the WDT
Before programming a PIC with TIMEOUT.ASM, let’s take a look at where the
WDT is enabled. PIC programs themselves have no control over the WDT. Enabling
or disabling the WDT is accomplished by the programmer or downloader when the
device configuration bits are programmed. The Device directive in the code controls
the configuration bits.

See Appendix C for more


Device PIC16F84,HS_OSC,WDT_ON,PROTECT_OFF,PWRT_ON
information on the Device
directive.
In the Device directive above, the
command WDT_ON instructs the assem-
bler to enable the WDT in the PIC’s con-
figuration bits. The EPIC downloading
software (at right) allows you to override
any of these settings at programming time.
Whenever programming a PIC with a
WDT-enabled program, it’s a good idea
to double-check the device settings to en-
sure that the WDT will indeed be turned
on. Alternatively, a single click can dis-
able the WDT in a WDT-enabled program
for debugging.

Waking the PIC using the WDT


If a WDT-enabled PICmicro™ processor is put to sleep, the WDT will wake the
PIC from sleep at the end of its time-out period. The WDT will not cause a device
reset when the PIC is asleep. Another simple WDT program illustrates this.

When WDTIMER.ASM is first started, a 16-bit wake-up counter is reset to zero


before the WDT is enabled. Then, the number of wake-up cycles is displayed on the
LCD. Next, the PIC goes to sleep. At the end of the WDT period, the PIC wakes up,
increments the wake-up count on the LCD, and goes back to sleep. Had a device
reset occurred, the wake-up counter which was initialized at the start of the program
would also be reset, and the wake-up count would never increment. Pull out
WDTIMER.ASM to examine it as we dissect the code.

Initialize ;Continue by initializing the LCD display.

CLRF Wake_UpH ;Continue clearing registers


CLRF Wake_UpL
CALL LCD_Port ;Set up Ports for LCD use

Init_WDT CLRWDT ;Clear Watchdog Timer


BSF RP0 ;Select register page 1
MOVLW 0FEh ;Set Option register for WDT with
MOVWF Option ;1:64 prescaler
BCF RP0 ;Return to register page 0

The Initialize subroutine clears the upper and lower bytes of the 16-bit wake-up
counter. Like the TIMEOUT.ASM program from earlier in the chapter, Init_WDT
Handling Software
Faults using the WDT 186 Microchip Code ©1998 Sirius microSystems
clears the WDT before setting a prescaler/postscaler in the Option register. This
time, the WDT time-out period is approximately 1.15 seconds.

MOVLW 1 ;Increment Wake-Up counter low byte


ADDWF Wake_UpL ;using Add instruction
BTFSC C ;Check Carry for roll-over
INCF Wake_UpH ;and increment high byte if set

MOVF Wake_UpL,W ;Copy Wake-Up counters to LowByte a


MOVWF LowByte ;HighByte for BCD conversion
MOVF Wake_UpH,W
MOVWF HighByte

CALL Bin_BCD ;Convert to BCD

After initializing the LCD and displaying the “Wake-up #:” message on the top
line, and the “Processing” message on the bottom line, the Main subroutine incre-
ments the Wake_UpL and Wake_UpH counters. Using ADDWF instead of INCF
allows us to check the C flag for the Wake_UpL roll-over. If Wake_UpL rolls over,
Wake_UpH is incremented. After the increment, the wake-up counters are copied to
LowByte and HighByte for conversion to BCD.

MOVLW Wake_Ups ;Send starting address of wake-up


CALL LCD_Reg ;counter to LCD
MOVF TenThous,W ;Load W with lower nybble of
ANDLW 0Fh ;Ten thousands digit
ADDLW 30h ;Convert it to ASCII and
CALL LCD_Data ;display it on the LCD

MOVLW Wake_Ups and CALL LCD_REG send the starting position of the
wake-up count to the LCD. The next four instructions isolate the first BCD nybble
of the 16-bit number, add 30h to convert it to an ASCII number, and display the
number on the LCD. Similar groups of instructions display the remaining four digits
of the wake-up count.

MOVLW LCDLine2 ;Send line 2 starting address


CALL LCD_Reg ;to LCD
CALL Delay_5ms ;Add a 20ms pause to see Processing
CALL Delay_5ms
CALL Delay_5ms
CALL Delay_5ms

After the wake-up count is displayed, a pause is added by calling the Delay_5ms
subroutine. The only purpose of the delay is to lengthen the amount of time that the
“Processing” message appears on the LCD. Otherwise the processing itself takes so
little time that the “Sleeping” message would never appear to change.

MOVLW Sleep_Msg ;Load W with Sleeping message offse


CALL Disp_Message ;and display it on line 2 of LCD

SLEEP ;Sleep until WDT expires


NOP ;
GOTO Main ;On WDT wake-up, display next count

Finally, the “Sleeping” message is displayed, and the PIC is put to SLEEP. After
the WDT time-out period expires, execution continues at the start of Main, where
the “Processing” message is displayed before updating the wake-up count.
Chapter 18
©1998 Sirius microSystems Microchip Code 187 Watch Dog Timer
Chapter Summary
The WDT is an independent timer that, when enabled, can reset the PIC or
periodically wake the PIC from sleep. Programs can use the WDT as a safety device
that will reset the PIC in case of a stuck code condition. If the CLRWDT instruction
is not issued by a program before the WDT time-out period expires, the WDT will
reset the PIC. WDT-enabled programs require greater planning on the part of the
programmer, since a method of handling both unintended resets as well as unknown
I/O states must be implemented to ensure proper code operation.

Using the TO bit, WDT-enabled programs can determine the cause of the device
reset and can respond appropriately. Programs should also be tested for the effect of
unanticipated I/O delays, such as a stuck key or sensor.

If the PIC is asleep, the WDT time-out merely wakes the PIC from sleep rather
than causing a device reset.

If you ignore it, the WDT will blow your program back to its start!

Chapter Summary
188 Microchip Code ©1998 Sirius microSystems
Questions
1. Why is it important that the WDT has its own internal R/C oscillator? Why
can’t the WDT use the PIC’s oscillator?

2. Using pseudo-code, show how to set up the WDT for use as an approximately
20 ms long switch debounce delay.

3. The WDT is not a bullet-proof method of ensuring a device reset during a


software failure. If a programming error leaves the PIC stuck in a loop, what
software conditions must have been met, both before and during the loop, to
ensure that the WDT resets the device?

Assignment
1. Modify the program TIMEOUT.ASM so that holding a key does not cause a
WDT time-out. This change would represent normal WDT operation, in which
there should never be a time-out.

2. Implement a long time period delay using the WDT. Compare the number of
registers required as counters for a five-minute delay timer using the WDT,
with that of a five-minute delay timer implemented in software delay loops.
Assume 10MHz operation.

Chapter 18
©1998 Sirius microSystems Microchip Code 189 Watch Dog Timer
Notes
190 Microchip Code ©1998 Sirius microSystems
PIC-MDS Installation
A and Setup

Appendix A
©1998 Sirius microSystems A-1 PIC-MDS Installation
and Setup
A-2 ©1998 Sirius microSystems
Congratulations on your purchase of the Sirius microSystems PIC-MDS. The
instructions in this chapter will guide you through the installation and setup of the
PIC-MDS hardware and software. First, ensure that you have everything in your
PIC-MDS package.

PIC-MDS Professional Package


• PIC-MDS circuit board with ZIF socket
• PIC16C711 microcontroller
• PIC16F84 microcontroller
• 10 Mhz crystal
• EPIC Programmer
• 6 ft., DB-25 m-f parallel port extension cable
• 6 in., 10-conductor in-circuit programming ribbon cable * Wall adapters are
• 2-120 VAC wall adapters * shipped with orders to
• PIC-MDS Programs and Software Libraries diskette North America only. The
• EPIC Programmer diskette EPIC Programmer requires
• PIC-MDS Microcontroller Development System Training Manual 12 VAC at 500 mA. The
PIC-MDS can operate on
9-12 VAC, 12-15 VDC, or
PIC-MDS Professional an external power supply
• PIC-MDS circuit board with ZIF socket at 300 mA. See Chapter 4.
• PIC16C711 microcontroller
• PIC16F84 microcontroller
• 10 MHz crystal
• 120 VAC wall adapter *
• PIC-MDS Programs and Software Libraries diskette
• PIC-MDS Microcontroller Development System Training Manual

PIC-MDS Hobbyist Package


• PIC-MDS circuit board kit
• Assembling and Testing Your PIC-MDS booklet (green)
• PIC16F84 microcontroller
• 10 MHz crystal
• EPIC Programmer
• 6 ft., DB-25 m-f parallel port extension cable
• 6 in., 10-conductor in-circuit programming ribbon cable
• 2-120 VAC wall adapters *
• PIC-MDS Programs and Software Libraries diskette
• EPIC Programmer diskette
• PIC-MDS Microcontroller Development System Training Manual

PIC-MDS Hobbyist
• PIC-MDS circuit board kit
• Assembling and Testing Your PIC-MDS booklet (green)
• PIC16F84 microcontroller
• 10 MHz crystal
• 120 VAC wall adapter *
• PIC-MDS Programs and Software Libraries diskette
• PIC-MDS Microcontroller Development System Training Manual

Appendix A
©1998 Sirius microSystems A-3 PIC-MDS Installation
and Setup
PIC-MDS Requirements
To use the PIC-MDS you will need and IBM PC or compatible computer with:
• Microsoft® MS-DOS
• a standard parallel port
• 1 MB of free hard disk space to install the software (recommended)

The EPIC Programmer software is designed to be run from MS-DOS only, us-
ing a standard parallel port. Some newer system boards with built-in ECP/EPP par-
allel ports may not work properly with the EPIC Programmer software. If the EPIC
Programmer software give repeated “Programmer not found” messages or had dif-
ficulty programming microcontrollers, try to disable the ECP/EPP parallel port fea-
tures in the system board BIOS setup utility or purchase a standard parallel port
card for your computer.

The EPIC Programmer software is dependent on accurate timing which can


only be guaranteed when it is run from MS-DOS. We do not recommend running
the EPIC Programmer software from within other multi-tasking operating systems.
Due to the wide variety of computer systems and the complexity of multi-tasking
operating systems we can support only those customers running the EPIC Program-
mer software from MS-DOS. However, below are some suggestions which may
help you to run the EPIC Programmer software from other operating systems:

Windows 3.x and Windows 3.11 for Workgroups


From the Main Group start an MS-DOS session in full-screen mode. Do not
attempt to run the EPIC Programmer software from within a DOS Window on the
See the appropriate Program Manager screen.
Microsoft or IBM manuals
or Help files for more Windows 95 and Windows 98
information on MS-DOS
sessions. Although not From the Start Button perform a Shut Down and select “Restart the computer in
recommended, we have MS-DOS mode” from the list of Shut Down choices. After the computer restarts,
been able to run the EPIC run the EPIC software from MS-DOS mode.
Programmer software from
each of the three operating OS/2 Warp v.3 and OS/2 Warp Connect
systems at right.
Start a DOS Full Screen session in which the HW_Timer setting has been set to
On and Video_Retrace_Emulation is set to OFF. Run the EPIC Programmer soft-
ware in full-screen mode.

Installing the Software


If you are using the PIC-MDS with the EPIC Programmer...
Insert the diskette labelled “PIC-MDS Programs and Subroutine Libraries” into
your floppy diskette drive. At the MS-DOS prompt type:

a:\install c: [Enter]

Where a: is the identifier of your floppy diskette drive and c: is the identifier of
the hard disk drive that you with to install the PIC-MDS software on to.
PIC-MDS Require-
ments A-4 ©1998 Sirius microSystems
The installation program creates a directory named “PIC-MDS” on the speci-
fied hard disk drive and copies the program source files (*.SRC) and library files
(*.LIB) into this directory. When this is complete, the installation program prompts
you to insert the “EPIC Programmer” diskette.

Remove the “PIC-MDS Programs and Subroutine Libraries” diskette from your
floppy disk drive and insert the “EPIC Programmer” diskette. Press any key to
continue the installation.

After inserting the “EPIC Programmer” diskette and pressing a key, the instal-
lation program copies the PIC Macro Assembler software (PM.EXE), EPIC Pro-
grammer software (EPIC.EXE) as well as a demonstration program and a number
of text files to the PIC-MDS directory. Finally, the installation program creates a
subdirectory named INC within the PICMDS directory and copies the microcon-
troller device type include files into it.

At this point the PIC-MDS software installation is complete. The diagram be-
low indicates the program directory structure:

Hard Disk Drive

PICMDS
*.ASM - Microchip source code files
#*.ASM - Parallax source code files
*.LIB - subroutine library files
PM.EXE - PIC Macro Assembler program
EPIC.EXE - EPIC Programmer
INC
P*.INC - PIC device type include files

If you are using the PIC-MDS with a third-party programmer...


Insert the “PIC-MDS Programs and Subroutine Libraries” diskette into your
floppy disk drive and copy all of the source files (*.ASM) and library files (*.LIB)
into the directory on you hard disk that contains your PIC assembler software or
you other PIC source code programs.

PIC-MDS Setup
Connecting the EPIC Programmer
To prepare the EPIC Programmer for use you will need:
• EPIC Programmer
• 6 ft., DB-25 m-f parallel port extension cable
• 12 VAC, 500 mA output wall adapter or two 9 V batteries

Remove the EPIC Programmer from is package and set it on a non-conductive


surface. Attach one end of the included 25-pin male to 25-pin female printer exten-
sion cable to the 25-pin connector on the EPIC Programmer.
Appendix A
©1998 Sirius microSystems A-5 PIC-MDS Installation
and Setup
Connect the other end of the 25-pin cable to the parallel printer port on your
computer.

CAUTION: Make sure that you connect the programmer to a parallel printer
port. Connecting the programmer to a serial port may result in damage to
the serial port or the programmer.

If you use a 12 VAC adapter to power the EPIC Programmer, remove the shorting
block from the jumper labelled “Batt ON”. Plug the AC adapter into a receptacle
and connect the round coaxial plug into the power jack on the top right of the EPIC
Programmer.

If you use two 9 V batteries to power the EPIC Programmer, connect the shorting
jumper across the “Batt ON” header and plug the batteries into the battery snaps.

WARNING: Never connect a battery across the centre snaps. This may
cause the battery to overheat and explode.

One or both of the LEDs on the EPIC Programmer may now be lit.

With your computer running, make sure that you are in the directory that con-
tains the PIC-MDS software by typing:

cd \picmds [Enter]

Start the EPIC Programmer software by typing:

epic [Enter]

If the EPIC Programmer is properly connected to your computer you should see
the EPIC Programmer screen appear on your computer. Both LEDs on the EPIC
Programmer board should now be off.

This is the EPIC Program-


mer screen that appears
when the EPIC Program-
mer is properly installed.

PIC-MDS Setup
A-6 ©1998 Sirius microSystems
If you see the “Programmer not found” message
make sure that the EPIC Programmer is connected to
your parallel printer port and that the cable is firmly
seated. Then check that the AC adapter is plugged in
and select “Retry”.

The EPIC Programmer software and hardware is fully installed and ready to
program a microcontroller.

Connecting the PIC-MDS


To prepare the PIC-MDS for use you will need:
• PIC-MDS
• 6 in., 10-conductor in-circuit programming ribbon cable
• wall adapter or power supply
• PIC16C711 or PIC16F84 microcontroller
• 10 MHz crystal

Remove the PIC-MDS from is package and set it on a non-conductive surface.


Attach the included 10-pin In-Circuit programming cable to the In-Circuit program-
ming header (H2) on the PIC-MDS. Note: The cable should extend away from the
PIC-MDS.

Position the EPIC Pro-


grammer and PIC-MDS as
The In-Circuit program-
shown in the picture and ming cable allows you to
connect the other end of program and erase a
the 10-pin In-Circuit pro- PIC16F84 microcontroller
gramming cable to the in the PIC-MDS circuit
connector labelled “J3” on board. You do not need to
the EPIC Programmer. plug the microcontroller
Note: The cable should into the programming
extend over the EPIC Pro- socket on the EPIC Pro-
grammer. In-Circuit Cable grammer and transfer it to
the PIC-MDS after pro-
gramming. PIC16C711
Before installing the microcontrollers can be
microcontroller into the programmed in the PIC-
Batt ON Jumper
PIC-MDS, make sure that MDS, but require UV light
both LEDs on the EPIC for erasure.
Programmer are off.

Now, carefully take the PIC16F84


processor out of its packaging and insert it
into the processor socket (U3) on the PIC- 10 MHz Crystal
MDS making sure that pin 1 of the
PIC16F84 is closest to the label U3. If you Pin 1
have a green ZIF socket, lift the handle to
the vertical position before inserting the
PIC16F84. Once the PIC16F84 is in the
socket, push the handle back down to the
horizontal position.
Appendix A
©1998 Sirius microSystems A-7 PIC-MDS Installation
and Setup
CAUTION: Make sure that the notch and the Microchip logo on the PIC16F84
are closest to the label U3 on the PIC-MDS circuit board. Inserting the
PIC16F84 into the PIC-MDS backwards may result in damage to the proc-
essor or the PIC-MDS.

Plug the 10 MHz crystal into the crystal socket labelled Y1 on the PIC-MDS.

At this time, connect the plug from the PIC-MDS AC adapter into the coaxial
power jack (J1) or connect a power supply to CON1 (see Chapter 4). The LED at
the top of the LED bar graph display (labelled PWR) should light up. Note: Some
or all of the other LEDs may also be lit. The LCD display may contain one line of
block characters. This is normal.

The PIC-MDS hardware is now connected to the EPIC Programmer and is ready
to program a PIC16F84 via the in-circuit programming cable, or to run the program
in a previously programmed PIC microcontroller.

Assembling and Downloading Programs


If you are familiar with programming microcontrollers, you may want to con-
tinue from step 3 of the Quick Start! sheet. Otherwise, chapters 5, 6 and 7 lead
you through writing, assembling and downloading your first program. Chapters 1
and 2 provide some background on how microcontrollers work. Chapters 3 and 4
describe the PIC family and the PIC-MDS in detail.

M DS inin
gM
anua
l

IC-
Tra
tem
Sys
ment
elop

P
PIC-MDS

Dev
PIC Microcontroller Development System Training Manual

ller
ntro
roco
Mic
PIC

Yes, it’s finally time to read the manual!


PIC-MDS Setup
A-8 ©1998 Sirius microSystems
Troubleshooting
B

Before resorting to incantations, rituals and spells, try the advice in this section. Then call the wizards
at Sirius microSystems.

Appendix B
©1998 Sirius microSystems B-1 Troubleshooting
B-2 ©1998 Sirius microSystems
Troubleshooting
If you should encounter a problem with your PIC-MDS, EPIC Programmer or
the included software, please look in this section for descriptions that most closely
resemble the symptoms you observe before contacting Sirius microSystems for tech-
nical support. Try the suggestions listed and if applicable re-read the section or
sections of the training manual that describe the operation you were trying to per-
form when you came across the problem.

Software Installation
If the installation program does not work correctly:

• Make sure the “PIC-MDS Programs and Subroutine Libraries” diskette is in


your floppy diskette drive and that your floppy diskette drive can read 3.5”
high-density diskettes.
• Start the installation program by typing:
a:\install c: [Enter]

where a: is the device descriptor of your floppy diskette drive and c: is the
directory on your hard disk to which you would like to install the PIC-MDS
software.
• Make sure that you insert the diskette labelled “EPIC Programmer” when re-
quested and press any key.
• Make sure that you are installing the program from MS-DOS and not an MS-
DOS session in Windows 3.x, Windows 95 or OS/2 Warp.

If the installed files are not in the volume or directory expected:

• Make sure that you specify a destination volume or directory name after the
install command (see above).

Assembling Programs with ASM


If you get a “Bad Command or File Name” message:

• Make sure that you start the PM software from within the PICMDS subdirectory
on you hard disk, or that you create a path to the PICMDS directory. Type:
cd \picmds [Enter]

to make the PICMDS directory the current directory. Then type:


asm filename [Enter]

where filename is the name of the source text file that you wish to assemble.
• You do not need to type the .ASM extension after filename .

Appendix B
©1998 Sirius microSystems B-3 Troubleshooting
If you get a “Fatal : [302] Unable to Open File” message:

• Make sure that the filename you typed following ASM exists and has a .ASM
filename extension.
• Make sure that any called subroutine files are in the PICMDS directory and that
the names of the subroutine files are spelled properly in the source code.

If you get a “Error filename.ASM 1 : [202] Illegal Character” message:

• make sure that the file specified as filename.ASM is an MS-DOS format text
file or has been saved as MS-DOS text by a Word Processing program.

Starting the EPIC Programmer Software


If you get a “Bad Command or File Name” message:

• Make sure that you start the EPIC software from within the PICMDS subdirectory
on your hard disk, or that you create a path to the PICMDS directory. Type:
cd \picmds [Enter]

to make the PICMDS directory the current directory. Then type:

epic [Enter] or epic filename.hex [Enter]

to start the EPIC Programmer software, or in the second case to start the EPIC
Programmer software with an object file to download.

If you get a “Programmer Not Found” message:

• If a previously programmed PIC microcontroller is in the microcontroller socket


on the PIC-MDS board, you may have to press and hold the “RESET” button
on the PIC-MDS while selecting “Retry” from the “Programmer not found”
message window.
• Check that the 25 pin male-female cable is properly seated into both the compu-
ter parallel printer port and the EPIC programmer connectors.
• Make sure that you are running the EPIC software from MS-DOS, and not from
an MS-DOS session in Windows 3.x, Windows 95 or OS/2 Warp.
• If you are using an AC wall adapter, check that the correct adapter (usually 12
VAC 500 mA) is plugged into a working receptacle and that its 2.1 mm coaxial
connector is plugged into the EPIC Programmer. Also make sure that the “Batt
ON” shorting jumper has been removed from the EPIC Programmer.
• If you are using two 9 V batteries, check that the batteries have sufficient charge
and that the shorting jumper connects the two pins of the “Batt ON” header on
the EPIC Programmer.
• If the EPIC Programmer is connected to the PIC-MDS via the In-Circuit pro-
gramming ribbon cable, make sure that the PIC-MDS is connected to an appro-
priate power supply and is operating. Also, make sure that the PIC-MDS has a
microcontroller in the microcontroller socket as well as a crystal in Y1.

Assembling
Programs with ASM B-4 ©1998 Sirius microSystems
If the object code of the file does not appear in the EPIC window:

• The ASM batch file assembles the source code file (*.ASM) to produce a list-
ing file (*.LST) and an object code file (*.HEX). Make sure that you specify
the object code filename with an .HEX extension. Note: EPIC also supports an
.OBJ extension.

Downloading Programs
If you get a “Verify Error at ” message:

• Make sure that you are programming a blank microcontroller, or a PIC16C84


which is electrically erasable, and that the microcontroller is properly plugged
into the microcontroller socket on the PIC-MDS or the programming socket on
the EPIC Programmer.
• If the microcontroller to be programmed is in the PIC-MDS, make sure that the
In-Circuit programming ribbon cable is correctly attached to both the PIC-MDS
and the EPIC Programmer. See the picture on the Quick Start! sheet.
• Check that the 25 pin male-female cable is properly seated into both the compu-
ter parallel printer port and the EPIC programmer connectors.
• If you are using an AC wall adapter, check that the correct adapter (usually 12
VAC 500 mA) is plugged into a working receptacle and that its 2.1 mm coaxial
connector is plugged into the EPIC Programmer. Also make sure that the “Batt
ON” shorting jumper has been removed from the EPIC Programmer.
• If you are using two 9 V batteries to power the EPIC Programmer, check that
the batteries have sufficient charge and that the shorting jumper connects the
two pins of the “Batt ON” header on the EPIC Programmer.
• Make sure that you are running the EPIC software from MS-DOS, and not from
an MS-DOS session in Windows 3.x, Windows95 or OS/2 Warp.

Assembling, Downloading and Running Programs


If the PIC-MDS Chapter examples don’t work:

• Make sure that power is applied to the PIC-MDS. The top LED in the LED bar
graph display lights when power is on. If this LED is off, compare the jumper
settings on the PIC-MDS with the defaults shown in Chapter 4 and reset the
jumpers on the PIC-MDS before reapplying power.
• If you use a power supply instead of the wall adapter, check your connections to
the terminal strip with the schematic in Chapter 4. Also, ensure that JU1 and
JU2 are set properly.
• Make sure that the PIC microcontroller is in the microcontroller socket on the
PIC-MDS and that a crystal or resonator is in the crystal socket, Y1.
• Check the jumpers and the JU6 jumper block in particular to ensure that they
match the defaults shown in Chapter 4.

Appendix B
©1998 Sirius microSystems B-5 Troubleshooting
• Make sure that the program source files haven’t been inadvertently modified.
Compare the source code to the original program source code in the Pull-Out
Program References section and if needed copy the original files from the “PIC-
MDS Programs and Subroutine Libraries” diskette to your PICMDS directory.
For example, if the OUTPUT.ASM program from Chapter 5 doesn’t light the
LEDs in a 10101010 pattern, the OUTPUT.ASM code in your PICMDS direc-
tory may have been modified. Copy the original from the PIC-MDS Programs
and Subroutine Libraries disk to your PICMDS directory by typing:
copy a:\output.asm c:\picmds [Enter]

• Read the comments at the beginning of the source code. Jumper settings and
special requirements are explained here.
• Check to make sure that the bottom of the PIC-MDS is clean and free of debris
and that the PIC-MDS is resting on a non-conductive surface.

Converting PIC-MDS Source Code


for Third-Party Tools
If you use a third-party assembler:

• Comment out or remove the “MACLIB” directive. While most other assem-
blers do not require you to explicitly specify the target device, the MACLIB
directive allows the PIC Macro Assembler (PM.EXE) to easily accommodate
new Microchip microcontrollers.
• Check your assembler documentation to see if the “DEVICE” directive is sup-
ported. Parallax and microEngineering Labs assemblers use the DEVICE di-
rective to set configuration fuses and ID bytes.
• Check the default radix of your assembler. PM assumes a default decimal radix
if no suffix follows the number.
• PM uses a suffix to denote a numerical radix. For example, 11 represents eleven,
11B represents the number three and 11H represents the number seventeen.
Some assemblers require a prefix or an alternate suffix.
• Both PM and Parallax tools support local assembly labels. Local labels are
prefixed with a colon (:). If your assembler does not support local labels, change
each local label to a unique label.

Assembling,
Downloading and B-6 ©1998 Sirius microSystems
Running Programs
PIC Macro Assembler
C Reference

Appendix C
©1996 microEngineering Labs C-1 PIC Macro Assembler
Reference
Copyrights and Trademarks
Copyright © 1996, microEngineering Labs.

Parallax is a trademark of Parallax, Inc.


PIC is a Registered Trademark of Microchip Technology, Inc.

Disclaimer of Liability
microEngineering Labs is not responsible for special, incidental, or
consequential damages resulting from any breach of warranty, or under any
legal theory, including lost profits, downtime, goodwill, damage to or
replacement of equipment or property, or any costs for recovering,
reprogramming, or reproducing any data used with microEngineering Labs'
products.

C-2 ©1996 microEngineering Labs


Table of Contents
1. Assembler Overview C-7
Compatibility ................................................................................ C-7
Operation ..................................................................................... C-7
Symbol Names ............................................................................ C-7
Numbers ...................................................................................... C-7
Strings ......................................................................................... C-7

2. Command Line Options C-7


2.1. Usage ................................................................ C-7
2.2. The PM Environment Variable ........................... C-8
2.3. Options .............................................................. C-8
2.3.1. Option -C ........................................................................... C-9
2.3.2. Option -D ........................................................................... C-9
2.3.3. Option -ELext .................................................................... C-9
2.3.4. Option -EMext ................................................................... C-9
2.3.5. Option -EOext ................................................................... C-9
2.3.6. Option -ESext .................................................................... C-9
2.3.7. Option -EIext ..................................................................... C-9
2.3.8. Option -G# ....................................................................... C-10
2.3.9. Option -Ipath ................................................................... C-10
2.3.10. Option -Lname .............................................................. C-10
2.3.11. Option -OB .................................................................... C-10
2.3.12. Option -OH .................................................................... C-10
2.3.13. Option -Q ....................................................................... C-10

3. Pseudo-Ops C-11
3.1. CODE .............................................................. C-11
3.2. DATA................................................................ C-11
3.3. EEPROM ......................................................... C-11
3.4. ABS ................................................................. C-11
3.5. ORG................................................................. C-11
3.6. DS .................................................................... C-12
3.7. DB .................................................................... C-12
3.8. DW .................................................................. C-12
3.9. EQU ................................................................. C-12
3.10. =..................................................................... C-12

4. Conditional Assembly C-12


4.1. IF...................................................................... C-13
4.2. ELSEIF ............................................................ C-13
4.3. ELSE ............................................................... C-13
4.4. ENDIF .............................................................. C-13
Appendix C
©1996 microEngineering Labs C-3 PIC Macro Assembler
Reference
4.5. IFDEF .............................................................. C-13
4.6. IFNDEF ............................................................ C-13
4.7. IFB ................................................................... C-13
4.8. IFNB................................................................. C-13

5. Macro Facility C-14


5.1. REPT ............................................................... C-14
5.2. IRPC ................................................................ C-14
5.3. IRP ................................................................... C-14
5.4. MACRO ........................................................... C-14
5.5. LOCAL ............................................................. C-14
5.6. EXITM .............................................................. C-15
5.7. ENDM .............................................................. C-15

6. File Controls C-15


6.1. INCLUDE ......................................................... C-15
6.2. MACLIB ........................................................... C-15

7. File and Listing Controls C-16


7.1. TITLE ............................................................... C-16
7.2. PAGE ............................................................... C-16
7.3. LIST ................................................................. C-16
7.4. NLIST............................................................... C-16
7.5. MTLIST ............................................................ C-16
7.6. NMTLIST ......................................................... C-16
7.7. CLIST............................................................... C-17
7.8. NCLIST ............................................................ C-17
7.9. LALL ................................................................ C-17
7.10. XALL .............................................................. C-17
7.11. SALL .............................................................. C-17

8. Device Controls C-17


8.1. DEVICE ........................................................... C-17
8.1.1. Fuse Specifier ................................................................. C-17
8.1.2. Core Specifier ................................................................. C-18
8.1.3. Reserved Options ........................................................... C-18
8.2. ID ..................................................................... C-18
8.3. RESET ............................................................. C-19

9. Expressions C-19
9.1. Calculations ..................................................... C-19
Table of Contents
C-4 ©1996 microEngineering Labs
9.2. Operators ......................................................... C-19
9.2.1. Bit Extension ................................................................... C-20
9.2.2. Modulus ........................................................................... C-20
9.2.3. Shift Right ........................................................................ C-20
9.2.4. DEF & REF ...................................................................... C-20
9.3. Numeric Constants ......................................... C-21
9.4. String Constants .............................................. C-21
9.5. List Quoting ...................................................... C-21
9.6. Identifiers ......................................................... C-22
9.6.1. Identifiers Starting with ‘:’ ................................................ C-22
9.6.2. Identifiers Starting with ‘$’ .............................................. C-22
9.6.3. Identifiers Starting with ‘_’ ............................................... C-22
9.6.4. Identifiers Starting with ‘@’ ............................................. C-22
9.7. System Variables ............................................. C-22
9.7.1. $ ...................................................................................... C-22
9.7.2. DEVICE ........................................................................... C-23

10. File Formats C-23


10.1. Source File ..................................................... C-23
10.2. Map File ......................................................... C-23
10.3. Binary Output File .......................................... C-23
10.4. Merged Intel HEX File .................................... C-23
10.4.1. PIC16C5x Device Descriptor ........................................ C-24
10.4.2. PIC16Cxx Device Descriptor ......................................... C-24
10.5. Symbol Table File........................................... C-25
10.6. Listing File ...................................................... C-25

11. Assembling Existing Parallax Code C-26

12. Warnings C-27


100 Attempt to Skip MultiByte OpCode @ Address ................. C-27
101 Use of Local Label Prior to Use of Non-Local Label ......... C-27
102 Code Crosses Boundary @ Address ................................. C-27
104 Called Addresses must Reside in Lower Half of Page ...... C-27
105 Bit Addresses are the Same .............................................. C-27
106 Register Addresses are the Same .................................... C-27

13. Errors C-28


200 Instruction Restricted to 14-Bit Core .................................. C-28
201 ‘Character’ Expected .......................................................... C-28
202 Illegal Character ‘Character’ .............................................. C-28
203 ‘—’ or ‘++’ Expected ........................................................... C-28
204 ‘W’ Expected as First Parameter ....................................... C-28
205 Illegal Use of Keyword ‘Keyword’....................................... C-28
206 CHECKSUM Not Supported in 14-Bit Core ....................... C-28
208 Illegal Use of SUB Instruction ............................................ C-28

Appendix C
©1996 microEngineering Labs C-5 PIC Macro Assembler
Reference
209 Indirect Jump Expected in Form of ‘PC+W’ ....................... C-29
210 Bit Addresses Must Differ................................................... C-29
211 Poorly Formed Numeric Constant ‘Token’.......................... C-29
212 Extra Tokens on End of Line .............................................. C-29
213 IRPC Expected Id or String Constant ................................ C-29
214 IRPC Missing Replacement Parameter ............................. C-29
215 Attempt to Redefine Macro ‘Identifier’ ............................... C-29
216 Attempt to Redefine Macro Parameter ‘Identifier’ ............. C-29
217 Attempt to Generate Code in Non-Code Segment ............ C-29
218 Address Limit of Address Exceeded .................................. C-30
219 Collision in HEX File @ Address ........................................ C-30
220 Illegal Bit Number ............................................................... C-30
221 Illegal Bit Address .............................................................. C-30
222 Illegal Destination Specifier ................................................ C-30
223 Illegal TriState File Register Address Register .................. C-30
224 Keyword Directive Only for Use in Macros ........................ C-30
225 Undefined Symbol ‘Identifier’ ............................................. C-30
226 Numeric Constant or Symbol Name Expected .................. C-31
227 Divide by Zero .................................................................... C-31
228 Modulus by Zero ................................................................ C-31
229 Device Doesn’t Support EEPROM ..................................... C-31
230 Collision in EEPROM @ Address .................................... C-31
231 Attempt to Redefine ‘Identifier’ .......................................... C-31
232 File Name Expected .......................................................... C-31
233 String Expression Expected for Title .................................. C-31
234 Identifier Expected ............................................................. C-31
235 Opcode Expected Instead of ‘Token’ ................................. C-31
236 Label ‘Identifier’ Undefined in Pass 0 ................................ C-32
237 IRP Missing Replacement Parameter ................................ C-32

14. Fatal Errors C-32


300 Too Many Errors ................................................................. C-32
301 Out of Memory ................................................................... C-32
302 Unable to Open File ‘Filename’.......................................... C-32
303 Unable to Create File ‘Filename’ ........................................ C-32
304 No Source File Specified ................................................... C-33
305 Unable to Write to File ‘Filename’ ...................................... C-33
306 Page Width must be 80 to 255 Columns ........................... C-33
307 Illegal Device Type ............................................................. C-33
308 Macro Buffer Overflow ....................................................... C-33

15. Internal Errors C-33


400 Attempt to Free Non-Allocated Memory [Pointer] .............. C-33
401 Attempt to Reference Non-Allocated Memory [Pointer] .... C-33
402 Attempt to Pop Empty Symbol Table Stack ....................... C-33
403 Attempt to Exit on Empty File Stack .................................. C-33
404 Attempt to Pop Empty Macro Stack ................................... C-33
405 Macro Stack Error .............................................................. C-33
406 Attempt to Pop Empty Conditional Assembly Stack .......... C-33
407 No Function Handler for ‘Keyword’ .................................... C-33

Table of Contents
C-6 ©1996 microEngineering Labs
1. Assembler Overview
Compatibility
Microchip & Parallax Instruction Sets
Microsoft Compatible Macros
Supports all 12-bit (16C5x) and 14-bit (16Cxx) PICs

Operation
Two-Pass Assembly
Operator precedence in evaluation of expressions
Conditional Assembly
Listing Controls
Separate Code, Data and EEPROM Segments

Symbol Names
Symbols up to 32 of the following characters :
: @ $ _ A-Z 0-9
First character must be legal character other than 0-9.
Special Uses :
$ Reserved for Debugger Commands
_ Reserved for Compilers
@ Temporary Labels
: Local Labels
Case sensitivity is optional.
Program labels must begin in column 1.
Non-labels must not begin in column 1.

Numbers
Default Radix is 10. All numbers must begin 0-9. An alternate radix may be
selected with one of the following suffixes :
B Binary
O Octal
H Hexadecimal
Radix suffixes are not case sensitive. All numbers are kept in 32 bit two’s com-
plement form (-231 to 231-1).

Strings
Strings are enclosed by a matching pair of single or double quotes. No string
operations are allowed.

2. Command Line Options

2.1. Usage
PM can be invoked from the DOS command line using the following command
format :
PM Options filename
Appendix C
©1996 microEngineering Labs C-7 PIC Macro Assembler
Reference
Zero or more options can be used to modify the manner in which the assembler
processes the input file. Options begin either with a slash ( ‘/’ ) or a minus ( ‘-’ ). The
character following the minus is a letter which selects the option. Additional charac-
ters may be needed by some options to supply additional information. No spaces may
occur within an option. Options not recognized by the assembler will generate errors
and be ignored.

The first parameter not starting with a minus or a slash is assumed to be the
filename. Extra parameters are ignored.

If PM is invoked with no options and no filename, a brief help screen is dis-


played.

2.2. The PM Environment Variable


With programming tools, a programmer will often want certain options to be
invoked consistently. This usually requires the programmer to invoke these options
each time the tools is used. While batch files and makefiles can reduce this tedium,
problems can also occur due to DOS limits on the length of command lines.

In order to alleviate these problems, the assembler uses a DOS environment


variable named PM. This contains a string of command line options which are im-
plicitly selected whenever the assembler is invoked. It uses the same format as the
options selected on the command line. Once these have been processed, then normal
command line options are processed and the file is assembled. Thus, you can use PM
to override the assembler defaults and then use the command line to override PM
defaults. This allows a great deal of customization to the assembler.

For example, suppose you want the PIC Macro Assembler to look more like the
original Parallax assembler. No problem - simply add the following to your
AUTOEXEC.BAT :

set PM=-EOOBJ

This changes the extension of the output filename from ‘HEX’ to ‘OBJ’.

2.3. Options

Option Option Description


C Identifiers to be Case Sensitive
D Generates Listing, Symbol Table, and Map File
Ecext Sets filename extension for specified file type
L = Listing File
M = Map File
O = Output File
I = Input File
S = Symbol Table
G# Set maximum error count
Ipath Set default INCLUDE/MACLIB directory

Command Line
Options C-8 ©1996 microEngineering Labs
Option Option Description
Lname Generate listing (listing filename is optional)
Of Set output format
B = Binary
H = Merged Intel HEX
Q Force use of explicit extension of source filename

2.3.1. Option -C
By default, all items in PM are case insensitive. Thus, MIXED, Mixed, mixed,
and mIXEd would all be treated as the same label or macro. When the -C option is
invoked, identifiers are case sensitive. In this mode, the sample identifiers would all
be treated as unique. In either mode, opcodes and pseudo-ops are always case insen-
sitive. This mode is generally intended for use by compilers where case is important
(such as C).

2.3.2. Option -D
PM normally assembles a source file and outputs an executable equivalent of the
program. When the -D option is invoked, a listing, a map and a symbol table are also
generated. This options is mainly used to generate information for debuggers.

2.3.3. Option -ELext


2.3.4. Option -EMext
2.3.5. Option -EOext
2.3.6. Option -ESext
The names for listing, map, output and symbol table files are generated auto-
matically by the assembler. These names are created by taking the base name of the
source file (up to 8 characters) and appending an extension indicating file type. The
default extensions are :

File Type Default Extension


Listing LST
Map MAP
Output HEX or BIN
Symbol Table SYM

These files are placed in the current directory. The -E options allows these de-
fault extensions to be changed. If the specified default is longer than 3 characters, it
is truncated without warning or error. This option can be used to make the outputs of
PM easier to use with various debugging platforms.

2.3.7. Option -EIext


Whenever the assembler is invoked, it checks the name of the source file for an
extension. If one is explicitly defined, it is used. If none is defined, then the assembler
appends a default input extension to the filename. By default, this extension is SRC.
The -EI option can be used to change this default to any three letter combination. If
the specified default is longer than 3 characters, it is truncated without warning or
error.
Appendix C
©1996 microEngineering Labs C-9 PIC Macro Assembler
Reference
The -Q option can be used to force the programmer to always specify the filename
extension, if any. Thus, -Q negates the use of the -EI option.

2.3.8. Option -G#


PM can generate an unlimited number of warning. For the sake of clarity, how-
ever, it limits the number of errors that can be generated. By default, PM terminates
with a fatal error if 15 or more errors occur. Using the -G option, this value may be
changed to any arbitrary number.

2.3.9. Option -Ipath


Whenever the assembler encounters an INCLUDE or MACLIB directive, a search
is conducted for the specified file. If a path is explicitly specified, that directory is
searched. If the file is not found, a fatal error is generated.

If no path is specified, the file is first sought in the current directory. If not found
there, then the system header directory is searched. By default, this directory is the
INC subdirectory of the directory from which PM is executed. If also not found here,
a fatal error is generated.

The -I option can be used to specify the new path of this default directory. When
invoked, the path specified by the -I option is not checked for validity. Thus, specify-
ing a non-existent or erroneous path can cause header files to seem to mysteriously
disappear (i.e. the assembler can’t find them because the directory doesn’t exist).

2.3.10. Option -Lname


When used, the -L option causes the assembler to generate a listing file in addi-
tion to the normal executable image generated. When used by itself, the listing is
placed in a file whose name is created by appending the listing extension (default is
LST) to the base name of the source file. If the -L options is used to specify a filename,
the listing is generated to the named file.

Note that even if the -D option (which by default generates a listing) is used, the
-L option can still be valuable, because it allows you to specify the name and path of
the listing file.

2.3.11. Option -OB


By default, PM generates Merged Intel HEX format for the executable image.
The -OB option allows the assembler to generate 16-bit binary format.
2.3.12. Option -OH

The -OH option forces PM to generate the executable image in the Merged Intel
HEX format. This option is mainly useful to override the use of the -OB option that
might be specified in the PM environment variable.

2.3.13. Option -Q
Normally, when no extension is explicitly specified for the source, PM appends
a default extension to the filename (SRC by default). The -Q option prevents this and
forces the programmer to explicitly define the extension (if any) of the source filename.
Command Line
Options C-10 ©1996 microEngineering Labs
3. Pseudo-Ops

3.1. CODE
CODE [ Expr ]

The code segment manages the program space of the PIC. The CODE pseudo-op
selects the code segment as the current segment. All bytes generated in the code
segment are placed in the executable image file. The optional expression may be used
to set the load pointer for the code segment.

3.2. DATA
DATA [ Expr ]

The data segment manages the RAM space of the PIC. The DATA pseudo-op
selects the data segment as the current segment. Generation of code or initialized data
in this segment results in an error (due to the Harvard architecture of the PIC). Thus,
DS is the only usable pseudo-op in the data segment. The optional expression may be
used to set the load pointer for the data segment.

3.3. EEPROM
EEPROM [ Expr ]

The EEPROM segment manages the EEPROM space available in the 8x family
of PICs. The EEPROM pseudo-op selects the EEPROM segment as the current
segment. Generation of code in this segment results in an error (due to the Harvard
architecture of the PIC). Thus, DS, DB and DW are the only usable pseudo-ops in
the EEPROM segment. The optional expression may be used to set the load pointer
for the EEPROM segment.

3.4. ABS
ABS [ Expr ]

Sets the current segment to the absolute segment. This is the default segment and
operates in the mode most familiar to programmers as “absolute” assembly. All bytes
generated in this segment are placed in the executable image file. The DS command
merely advances the load pointer. The optional expression may be used to set the load
pointer for the absolute segment.

3.5. ORG
ORG Expr

Sets the load pointer for the current space. The user may get the current value of
the load pointer for the current segment via the system variable $.

Appendix C
©1996 microEngineering Labs C-11 PIC Macro Assembler
Reference
3.6. DS
DS Expr

Advances the load pointer by the specified value. DS is normally used to allocate
space within the data or EEPROM segments. When used in the EEPROM segment,
no data is generated in the HEX file for the allocate locations. This allows EEPROM
locations to be allocated that will not be programmed (assuming your programmer
doesn’t unconditionally program all EEPROM locations).

3.7. DB
DB (Expr|String) { , (Expr|String) }

Stores one or more constant bytes in the current segment. In the case of numeric
constants, the resulting values (truncated to 8 bits, if necessary) are stored. String
constants are stored as consecutive bytes.

Since the PIC cannot store data in the code space directly, each byte generated in
the code segment is actually stored as a RETLW instruction. Bytes generated in the
EEPROM segment are stored merely as data. And, of course, bytes generated to the
data segment result in errors.

3.8. DW
DW Expr { , Expr }

Stores the resulting value in the current segment. The value is truncated to 16-
bits. The least significant byte is stored first. Each byte is generated in the same
manner as the DB pseudo-op.

3.9. EQU
3.10. =
Label EQU Expr
Label = Expr

Assigns a numeric value to the specified symbol. The two operations are similar,
except it is an error to redefine a symbol created using the EQU pseudo-op. Symbols
created using the = may be reassigned value without error.

4. Conditional Assembly
Note: PM requires that all symbols be defined at the end of the first pass. In order
to meet this requirement, the evaluation of all conditional assembly constructs must
be consistent in both passes. Thus, unlike other assembler features, conditional as-
sembly may not assemble correctly if it relies on forward references.

Pseudo-Ops
C-12 ©1996 microEngineering Labs
4.1. IF
4.2. ELSEIF
4.3. ELSE
4.4. ENDIF
IF Expr
...
ELSEIF Expr
...
ELSE
...
ENDIF

Assembly continues following the first true (i.e. non-zero) expression in the se-
ries of IF and ELSEIF statements and continues until the next statement in the
IF..ELSE..ENDIF chain. If no statement is true and an ELSE statement is present,
the code between ELSE and ENDIF is assembled. The IF and ENDIF terms are
mandatory. One ELSE and multiple ELSEIF terms are optional.

4.5. IFDEF
4.6. IFNDEF
IFDEF Label
IFNDEF Label

The IFDEF and IFNDEF statements may be substituted for the IF term in the
IF..ELSE..ENDIF construct. IFDEF evaluates true if the specified symbol is de-
fined. IFNDEF evaluates true if the specified symbol is not defined. There are no
IFDEF/IFNDEF replacements for the ELSEIF statement.

The DEF operator may be used for more complicated variations on the IFDEF/
IFNDEF pseudo-ops.

4.7. IFB
4.8. IFNB
IFB [ Item ]
IFNB [ Item ]

The IFB and IFNB statements may be substituted for the IF term in the
IF..ELSE..ENDIF construct. IFB evaluates true if an item is listed on the line follow-
ing the IFB statement. IFNB evaluates true if no item is listed on the line following
the IFNB statement. There are no IFB/IFNB replacements for the ELSEIF state-
ment.

Comments are treated as blanks in the evaluation of IFB and IFNB statements.
These constructs are mainly useful in macros to test whether a parameter has been
specified by the caller or has been omitted.

Appendix C
©1996 microEngineering Labs C-13 PIC Macro Assembler
Reference
5. Macro Facility

5.1. REPT
REPT Expr
Body
ENDM

The body of the macro is repeated the number of times specified by the numeric
expression. The REPT macro is executed immediately.

5.2. IRPC
IRPC Param , String
Body
ENDM

The body of the macro is repeated once for each character in the specified string.
The specified parameter is substituted on each expansion with the scanned character.
The IRPC macro is executed immediately.

5.3. IRP
IRPParam , < Expr { , Expr } >
Body
ENDM

The IRP macro is similar to the IRPC macro, except that items from the speci-
fied list (bracketed with < and >) are substituted for the specified parameter. The IRP
macro is executed immediately.

5.4. MACRO
Label MACRO Param { , Param }
Body
ENDM

Unlike other macro types, MACRO merely creates a template for later macro
expansions. MACRO accepts up to 32 identifiers as parameters. Whenever found in
the body (even in quotes), these parameters are substituted with the value specified
when the macro is invoked. Macros are invoked just as any other pseudo-op or opcode.
Parameters specified in the definition but not assigned values when invoked are left
unsubstituted. This allows macros with a variable number of parameters if used with
the IFB and IFNB conditional assembly constructs.

Since a macro’s name is a label, it must begin in column 1.

5.5. LOCAL
LOCAL Symbol { , Symbol }
Macro Facility
C-14 ©1996 microEngineering Labs
Allows the creation of local symbols in any macro type. A unique temporary
symbol is created for each local symbol for every expansion of the macro’s body.
Any number of LOCAL statements may be defined, but they must immediately fol-
low the macro definition (REPT, IRPC, IRP or MACRO pseudo-op). Local symbols
take the form @@NNNN, where NNNN is a four digit decimal number assigned
sequentially from 0000.

5.6. EXITM
Allows premature abortion of macro expansion. This is useful for implementing
loops whose lengths are not determinant.

5.7. ENDM
All macro definitions are terminated by the ENDM pseudo-op.

6. File Controls

6.1. INCLUDE
INCLUDE String

The INCLUDE statement is replaced with the contents of the specified file. If no
path is specified, the file is searched for first in the current directory. If not found,
then the system header directory is searched. If still not found, an error results.

By default, the system header directory is the INC subdirectory of the directory
from which PM.EXE is executed. This directory contains files defining important
constants and macros for each of the PICs supported. This can be changed by the use
of the -I command line option.

6.2. MACLIB
MACLIB String

MACLIB is identical in operation to INCLUDE, except that the file is only


parsed on the first pass. This is intended for use on include files that contain only
macro and symbol definitions.

Avoid the use of MACLIB if the file includes any opcodes. If used on such a file,
the file will affect assembly on the first pass, but not on the second. This can create
major discrepancies in the second pass of assembly and usually results in a large
number of confusing error.

Appendix C
©1996 microEngineering Labs C-15 PIC Macro Assembler
Reference
7. File and Listing Controls

7.1. TITLE
TITLE String

Specify the title at the top of every page in listing file.

7.2. PAGE
PAGE Expr , Expr
PAGE Expr
PAGE

If the first parameter is defined, it sets the page width for the listing. The page
width must be between 80 and 255 characters (default is 132). Characters beyond
this width are truncated from the listing. If the second parameter is defined, it sets the
page length of the listing (default is 60). If the page length is set 0, no automatic page
breaks are generated.

If the PAGE pseudo-op is used without parameters, it forces a page break in the
listing.

7.3. LIST
7.4. NLIST
If the -L option is used, the listing counter is initialized to 1. Otherwise, it de-
faults to an initial value of 0. LIST increments the listing counter. NLIST decrements
the listing enable counter. Whenever the listing counter is positive, lines are gener-
ated for the listing.

This simple arrangement allows a greater flexibility in listing control than did
earlier versions of PM. For example, the source file may contain listing controls
without unconditionally generating a listing.

7.5. MTLIST
7.6. NMTLIST
If the MTLIST pseudo-op is used, enough lines are generated to display all bytes
generated by the listed statement. This is the default.

If the NMTLIST is pseudo-op is used, only one line is listed for each line of
source code. If a line generates more than 4 words of code, additional bytes are not
displayed and the line is marked with an ‘#’.

File and Listing


Controls C-16 ©1996 microEngineering Labs
7.7. CLIST
7.8. NCLIST
The CLIST pseudo-op forces all portions of IF..ELSE..ENDIF constructs to be
listed. This is the default.

The NCLIST pseudo-op forces only those portions of IF..ELSE..ENDIF con-


structs that are assembled to be listed. The conditional statements themselves are
always listed, although nested IF..ELSE..ENDIF constructs in unassembled blocks
of code are not listed.

7.9. LALL
7.10. XALL
7.11. SALL
If LALL pseudo-op is used, all lines of a macro expansion are listed. This is the
default.

If XALL pseudo-op is used, only those lines of a macro expansion which gener-
ate code are listed.

If SALL pseudo-op is used, no lines of a macro expansion are listed.

8. Device Controls
PM was written to be compatible with all 12-bit and 14-bit PICs. The assembler
was designed to handle the architectural limits of both core types. Each program
must specify which core and a specific set of capabilities by using the DEVICE
statement.

8.1. DEVICE
DEVICE Expr { , Expr }

The DEVICE pseudo-op takes one or more comma separated 32-bit expressions
as parameters. The bits 31 and 30 of each value distinguishes one of four separate
processor specifications. These two bits determine how the remaining thirty bits of
that value are interpreted.

8.1.1. Fuse Specifier


If the upper two bits of a parameter are 00, this word defines the configuration
fuses. PM allows arbitrary control of a 14-bit fuse word. When a fuse specifier is
used, two actions are taken:

• The current fuse value is ANDed with the upper 16 bits of the 32 bit word.
• The resulting fuse value is then ORed with the lower 16 bits of the 32 bit word.

Appendix C
©1996 microEngineering Labs C-17 PIC Macro Assembler
Reference
This system allows one or more values to be chained together to control various
bit locations in the fuses. These may occur in any order or even in multiple DEVICE
statements. The actual values used to set the fuses are normally defined in the header
file defined for a particular component or family of components. Below is a partial
table containing the most common fuse specifiers. For a full list, consult the device
header for your particular device.

DEVICE Parameter Description


RC_OSC RC Oscillator
HS_OSC HS Oscillator
XT_OSC XT Oscillator
LP_OSC LP Oscillator
BOD_ON Brown-Out Detection Enabled
BOD_OFF Brown-Out Detection Disabled
PROTECT_ON Code Protection Enabled
PROTECT_OFF Code Protection Disabled
WDT_ON Watch Dog Timer Enabled
WDT_OFF Watch Dog Timer Disabled

8.1.2. Core Specifier


The core specifier defines the processor’s core type (12 bit or 14 bit) and the
amount of ROM/EEPROM available. This information is needed to generate core
appropriate instructions and to perform range checking on addresses.

Additionally, an arbitrary 8-bit numeric code may be assigned to the processor.


While PM doesn’t use this information, it is embedded in the output file and this
information is used by some simulators, programmers, and other third party develop-
ment tools. There is no standardization (among tool providers) on these numbers.

No attempt is made to provide RAM availability information. The asymmetry of


data pages makes it difficult to perform error checking without generating warnings
on valid instructions.

Unlike fuse specifiers, a core specifier must be set in one value - it lacks the
running accumulation effect of fuse specifiers.

8.1.3. Reserved Options


The two remaining DEVICE fields (10 and 11) are reserved for future use. Any
DEVICE value containing these upper 2 bits will generate an error.

8.2. ID
ID Expr
ID String
ID CHECKSUM

Each PIC has a 16-bit (12-bit core) or 28-bit (14-bit core) ID. This value can be
set in one of three methods. A numeric expression or string constant can be used for
either core type. For 12-bit cores only, the reserved word CHECKSUM may be used.
Device Controls
C-18 ©1996 microEngineering Labs
This forces the Parallax PIC Programmer to compute the checksum of the PIC
code space.

8.3. RESET
RESET Expr

Each time a PIC is powered up or reset, the PC is set to a determinant spot. It is


assumed that the programmer will use this knowledge to get his program to start
executing whenever the PIC is ready. The most common method of doing this is to
place a GOTO instruction at this spot. In the 12 bit core, execution begins with the
last word of ROM. In the 14 bit core, execution begins at 0000h.

The RESET pseudo-op places a GOTO at the correct address determined for the
current processor type (as set by the DEVICE pseudo op). The RESET command is
most commonly used in programs for 12-bit cores.

9. Expressions

9.1. Calculations
Even though PIC processors only handles 8-bit math and use 11-bit or 13 bit
addresses, PM performs all calculations and stores all constants 32-bit, two’s com-
plement form.

No string operations are available.

9.2. Operators

Operator Function Unary Precedence


() Grouping Operators x 1
REF Label Reference x 2
DEF Label Defined x 2
- Unary Minus x 2
+ Unary Plus x 2
~ Bitwise NOT x 2
! Logical NOT x 2
HI MSB of Word x 2
LO LSB of Word x 2
* Multiply 3
/ Divide 3
% Modulus 3
>> Shift Right 4
<< Shift Left 4

continued on next page..

Appendix C
©1996 microEngineering Labs C-19 PIC Macro Assembler
Reference
Operator Function Unary Precedence
- Subtract 5
+ Addition 5
= Equivalence 6
<> Inequality 6
< Less Than 6
> Greater Than 6
<= Less Than or Equal 6
>= Greater Than or Equal 6
& Bitwise AND 7
^ Bitwise XOR 8
| Bitwise OR 8
. Bit Address Operator 9

Expressions are resolved from left to right using operator precedence to resolve
ambiguities in evaluation. The precedence of each operator is shown. Operators with
the highest precedence (i.e. those which are evaluated first) are show as precedence_1.

9.2.1. Bit Extension


Whenever bits in a number are inverted, this inversion occurs in all 32 bits. This
causes the bit-wise inversion and negation of byte-sized numbers with 1’s in the
upper bits. This, however, isn’t usually a problem, since opcodes usually truncate
calculated values to the appropriate size without generating warnings or errors.

9.2.2. Modulus
Modulus is the proper name for what you may have learned in school as the
“remainder”. In short, it is value that is “left over” when one integer value is divided
by another. In systems which support signed numbers, there is some ambiguity as to
the sign of the remainder for negative numbers. PM returns a modulus with the same
sign as the dividend.

9.2.3. Shift Right


Shift right is often used as a fast-divide for binary values (e.g. shifting right by 3
bits is the same as dividing by 8). Since PM works with signed numbers, a number
shifted right will retain the value of the 32nd bit (i.e. sign extension).

9.2.4. DEF & REF


DEF ( LabelList )
REF ( LabelList )

In order to allow PM to simulate a linking library, the DEF and REF operators
are defined. The DEF operator returns true (1) if the specified label(s) have been
defined earlier in the program. Similarly, the REF operator returns true (1) if the
specified label(s) have been used (referenced) earlier in the program. Both return 0 if
the tested condition is false.

To increase flexibility, more than one label may be tested. In fact, logical opera-

Expressions
C-20 ©1996 microEngineering Labs
tors (‘|’ for OR and ‘&’ for AND) and parenthesizes have are supported for complex
label lists.

9.3. Numeric Constants


All numbers default to radix 10. All numbers (regardless of radix) must begin
with digits 0-9. Other bases may be selected by appending the following suffixes.
Suffixes are not case sensitive.

B Binary
O Octal
H Hexadecimal

9.4. String Constants


PM supports string constants mainly for the purpose of generating strings of
RETLWs (via the RETW opcode and DB pseudo-op). Strings may be enclosed by
either single ( ‘ ) or double ( “ ) quotes. If single quotes are used, then double quotes
may be used freely within the string, and vice versa. Single quotes may not appear
within a single quoted string and double quotes may not appear within a double
quoted string.

String constants may also be used to drive the IRPC macro pseudo-op. On each
expansion of the IRPC macro, the replacement parameter is replaced with an unquoted
character. When used as a parameter for macros defined using the MACRO pseudo-
op, the quoted string is passed unmodified (quotes intact).

9.5. List Quoting


The IRP macro is driven by a list of comma separated items bracketed with <
and > characters. This item can be so useful, that < and > have been given a special
“quoting” function in macros. When the < character is encountered in the parameter
list for a macro defined using the MACRO pseudo-op, the parameter is considered to
contain all characters up to the next >. This type of bracketing may not be nested.
When this parameter is substituted, the < and > are stripped from the substitution.

1 defb1 macro list


2 irp item,<list>
3 db item
4 endm
5 endm
6
7 defb2 macro list
8 db list
9 endm
10
11 defb1 <1,”One”,2,”Two”>
+ irp item,<1,”One”,2,”Two”>
+ db item
+ endm
+ 000- 801 db 1
+ 001- 84F 86E 865 db “One”
+ 004- 802 db 2
+ 005- 854 877 86F db “Two”
12 defb2 <1,”One”,2,”Two”>
+ 008- 801 84F 86E 865 db 1,”One”,2,”Two”
00C- 802 854 877 86F
Appendix C
©1996 microEngineering Labs C-21 PIC Macro Assembler
Reference
9.6. Identifiers
Identifiers are the names used as program labels, variables and macro names.
Although they can be any length, only the first 32 characters are significant and they
must be unique in these 32 characters. Identifiers differing only in the 33rd or later
character are considered identical. Identifiers consist of any of the following charac-
ters :

A-Z 0-9 : @ $ _

Identifiers may begin with any of these characters except 0-9. The first character
may have a special meaning, as described in the following sections.

9.6.1. Identifiers Starting with ‘:’


Symbols starting with a colon ( ‘:’ ) are local symbols. This method appends this
local label to the last non-local label (i.e. label beginning with other than a colon).
This allows simple labels within a global block not to pollute valuable name space.
The labels can be referenced within this local block using the abbreviated local name.
To reference this label outside the block, the full form needs to be used (i.e. non
local:local).

9.6.2. Identifiers Starting with ‘$’


Symbols starting with the dollar sign ( ‘$’ ) are reserved for future debugging
use. Currently, only one symbol starting with the dollar sign is reserved by the as-
sembler, which is the dollar sign itself. It is used to get the value of the load pointer
for the current segment.

9.6.3. Identifiers Starting with ‘_’

Symbols starting with the underscore ( ‘_’ ) are reserved for use by compilers.

9.6.4. Identifiers Starting with ‘@’


Symbols starting with the at symbol ( ‘@’ ) are treated as temporary labels.
Temporary symbols are treated just like other labels, except they are not included in
the symbol table. The LOCAL pseudo-op generates symbols in the form of
@@NNNN, where NNNN is a four digit decimal number starting with 0000.

9.7. System Variables


In order to make programming easier, PM defines some system variables. You
cannot redefine these variables, although they can be used as you would other vari-
able.

9.7.1. $
The dollars sign ( $ ) is used to get the value of the load pointer for the current
segment. Each of the four segments (CODE, DATA, EEPROM and ABS) has its
own load pointer. Therefore, the value of $ depends on the segment in which it ap-
pears.
Expressions
C-22 ©1996 microEngineering Labs
9.7.2. DEVICE
DEVICE returns the core specifier. For details on these flags, see the description
of the DEVICE pseudo-op.

10. File Formats

10.1. Source File


; Test File for PIC Macro Assembler

include ‘T13.INC’ ; Show Include File

SIZE equ 10h ; Show Assignment Statement


mac “uChip” ; Show Macro Expansion

nmtlist ; Suppress Multi Line Listing


db “uChip” ; Generate Constants
mac “uChip” ; Expand & Generate Constants

PM uses a common collimated format for the input (or source) file. This is the
same format as used by the original Parallax PIC assembler. Items starting in column
1 are either labels, variables, or macro names. Items beginning in column 2 or later
are assumed to be opcodes or pseudo ops. Depending on the opcode or pseudo-op,
zero or more comma separated parameters may follow the opcode/pseudo-op. Com-
ments (which begin with a semicolon) may begin in any column.

10.2. Map File


The MAP file is used to link the executable file to the source file. The MAP file
contains one 16-bit number (2 bytes) for each word in the code space of the target
processor. This 16-bit number (stored LSB first) is the number of the line in the
source file which generated the corresponding instruction in the executable image.
No provisions are made for mapping instructions on to lines in generated in IN-
CLUDE or MACLIB files.

10.3. Binary Output File


The simplest output format of PM is the 16-bit binary format. The binary file
contains one 16-bit word (2 bytes) for each word in the code space of the target
processor. This word (stored LSB first) contains the actual PIC opcode for the corre-
sponding address (i.e. the first word of the file corresponds to address 000h in the
target processor). The most significant bits of the word which are unused by the
processor (4 in the 12-bit core, 2 in the 14-bit core) are zeroed. Addresses not as-
signed values by the assembler are stored with all 1’s (0FFFh in the 12-bit core,
3FFFh in the 14-bit core).

10.4. Merged Intel HEX File


The default output format of PM is the Merged Intel HEX format. This section
will not describe the standard Intel HEX format (which is well documented else-
where), but details the deviations from the standard for the Merged format.
Appendix C
©1996 microEngineering Labs C-23 PIC Macro Assembler
Reference
Each word of the executable image is stored in consecutive bytes in the Intel
format (LSB first). To adjust for the 2-byte word size of the PIC, the Intel HEX
addresses are doubled (since the format is strictly byte oriented). With these two
adjustments made, the Merged Intel HEX format is identical to the standard Intel
HEX format.

Unlike the binary format, only bytes which are actually generated have any value
specified in the Merged Intel HEX format. If some fill value is required, this must be
handled by your PIC programmer.

Unlike the binary file format, the Merged Intel HEX format also contains infor-
mation on the processor type, ID/checksuming flag and the fuses.

10.4.1. PIC16C5x Device Descriptor


:061FFA00 0001 FFFF 03 02 DD
Intel Checksum
Fuses
Processor Number
ID
Checksum Flag
Intel Header

The device descriptor for the PIC16C5x family is shown above. The checksum
flag (2 bytes) is 0000 if no checksum is to be calculated and 0001 is the checksum is
to be calculated. The ID field contains the 16-bit ID (LSB first) as specified by the
ID pseudo-op. The ID is FFFF if the checksum for the PIC is to be calculated (i.e.
Checksum = 0001). The processor numbers for the PIC16C5x family are as follows:

00 PIC16C54
01 PIC16C55
02 PIC16C56
03 PIC16C57
04 PIC16C58

For details on the fuses field, see the description of the DEVICE pseudo op.

10.4.2. PIC16Cxx Device Descriptor


:084000007F007F007F007F00BC
Intel Checksum
ID
Intel Header

:04400E00FF3F000070
Intel Cheksum 00 PIC16C71
Processor Code 01 PIC16C84
Fuses 02 PIC16C64
Intel Header 03 PIC16C74

File Formats
C-24 ©1996 microEngineering Labs
10.5. Symbol Table File
a_abs 0000000A
a_code CODE 0000000A
a_data DATA 0000000A
a_eeprom EEPROM 0000000A
x_abs 00000000
x_code CODE 00000000
x_data DATA 00000000
x_eeprom EEPROM 00000000

The symbol table contains all labels (except labels starting with the ‘@’ charac-
ter) defined in the program. This file contains three unlabeled columns. The first
column contains the actual name of the symbol. The case of the defining instance is
preserved and only the first 32 significant characters are displayed. The second col-
umn may contain the label’s type (CODE, DATA or EEPROM). This is determined
by the segment in which the label was defined. No type is generated for the ABS
segment, which is the default. Finally, the last column contains the full 32-bit repre-
sentation of the number in hexadecimal. Note that base-16 is understood and no ‘H’
suffixes or ‘0x’ prefix has been included. Symbols are listed in alphabetical order.

This format is intended for use by debuggers and is not really made human
readable. While the items currently begin in fixed column, this may change in the
future. Those parsing these items should rely on the use of whitespace as separators,
rather than column numbers. Additional fields (columns) may be added to the end of
each line in the future, so those processing this format should ignore items occurring
after the value.

10.6. Listing File


1 ; Test File for PIC Macro Assembler
2
3 include ‘T13.INC’
* 1 mac macro p
* 2 db ‘p’
* 3 endm
* 4 mac “uChip”
+ 000- 822 875 843 868 db ‘“uChip”’
004- 869 870 822
4
5 =0010 SIZE equ 10h
6 mac “uChip”
+ 007- 822 875 843 868 db ‘“uChip”’
00B- 869 870 822
7
8 nmtlist
# 9 00E- 875 843 868 869 db “uChip”
10 mac “uChip”
# + 013- 822 875 843 868 db ‘“uChip”’

The listing file gives the programmer the most information about the actual as-
sembly of the source file, and is therefore the most complex. This file contains three
columns of assembly information followed by the source code.

The first column of the listing is a single character which gives additional infor-
mation about the line being listed. The following table shows these tag characters.
While multiple tags might apply to a single line, only one is listed. Thus, they are
listed below in order of preference :
Appendix C
©1996 microEngineering Labs C-25 PIC Macro Assembler
Reference
# More than 4 Words Generated, but Suppressed
* Line is from Include File
Normal Source Line

The second column displays the line number. If the current line is from an in-
cluded file, the number of that line within the include file is listed. If the current line
is generated by a macro expansion, the line number is replaced with a ‘+’.

The last column displays the results of the line. If the line computes a value for a
label or as the parameter for a pseudo-op, then the value is display either as a 4 or 8
hexadecimal digit number following an ‘=’. If the line generates code, the current
load pointer is displayed, followed by ‘-’ and one or more lines of up to 4 words per
line. For comments and many pseudo-ops, this column is left blank.

11. Assembling Existing Parallax Code


For the most part, PM will assemble existing Parallax code (previously assem-
bled w/ PASM, PASM71 or PASMX) with little or no change. The following steps
may be needed :

* Depending on the type of PIC, place the following line in the source prior to
any lines of code :

PIC16C5x MACLIB ‘P5X.INC’


PIC16C61 MACLIB ‘P61.INC’
PIC16C62 MACLIB ‘P62.INC’
PIC16C62x MACLIB ‘P62x.INC’
PIC16C63 MACLIB ‘P63.INC’
PIC16C64 MACLIB ‘P64.INC’
PIC16C65 MACLIB ‘P65.INC’
PIC16C70 MACLIB ‘P70.INC’
PIC16C71 MACLIB ‘P71.INC’
PIC16C72 MACLIB ‘P72.INC’
PIC16C73 MACLIB ‘P73.INC’
PIC16C74 MACLIB ‘P74.INC’
PIC16C84 MACLIB ‘P84.INC’

* If you receive the error [225] Undefined Symbol ‘W’, the source may con-
tain the Parallax opcode MOV W,fr-W. This opcode is not supported by PM. This
opcode can, however, be replaced with the Microchip equivalent SUBWF fr,0.

MOV W,fr-W Becomes SUBWF fr,0

* The SUBB instruction of PASM was specialized for use with the PIC carry
flag (C), which is inverted from carry flags in most conventional processors (0 if a
borrow occurs). Thus, SUBB modified its destination if the specified bit is 0, which
is nonsense for general bit usage (although it makes sense for 16-bit subtraction). If
you used these instructions in your program, you must invert the sense of the bit.
File Formats
C-26 ©1996 microEngineering Labs
SUBB fr,bit Becomes SUBB fr,/bit
SUBB fr,/bit Becomes SUBB fr,bit

* The original Parallax assembler evaluates equations strictly left to right (i.e.
3+4*5 = 35). PM also evaluates equations left to right, but uses operator precedence
(i.e. 3+4*5 = 23). This typically creates no problems since PIC programs tend to be
relatively simple. You should, however, check for complex calculations to assure that
their evaluation will be correct.

12. Warnings
100 Attempt to Skip MultiByte OpCode @ Address
Indicates the current instruction is a multibyte Parallax instructions and that the
previous instruction is attempting to skip it. Obviously, if this were done unintention-
ally, a successful skip would enter the current opcode mid-instruction.

101 Use of Local Label Prior to Use of Non-Local Label


Indicates that a local label (i.e. starting with a colon) has been defined prior to the
definition of a non-local label (i.e. a legal label name starting with other than a colon).
Because local names depend on the named of last non-local label defined, this usage is
obviously suspicious. The label generating the warning is not expanded as are other
local labels (see Local Labels).

102 Code Crosses Boundary @ Address


Both the 12-bit and 14-bit PIC cores have paged architectures in which the normal
incrementing of the PC doesn’t extended into page select registers (PA0 & PA1 in the
PIC16C5x, PCLATH in the PIC16Cxx). If a continuous block of code is generated
across a page boundary and a forward jump is coded, the actual jump location will be
to the previous page.

104 Called Addresses must Reside in Lower Half of Page


In the PIC16C5x family, the 9th bit of address is zeroed on calls. Thus, call desti-
nations must reside in the lower 256 words of any 512 word page. This mistake is only
a warning since calls made to the upper 256 words will alias to an address in the lower
256 words of the page.

105 Bit Addresses are the Same


This warning indicates that you have attempted to copy a bit to itself. The Parallax
MOVB bit,bit instruction will correctly copy a bit to itself, although the operation has
no useful applications.

106 Register Addresses are the Same


This warning indicates that you have attempted to copy a register to itself. While
this is legal, it generates a MOVF and MOVWF instruction, placing the moved value in
W and setting the Z flag. If your intentions are to set the Z flag according to contents of
the specified register, the TEST instruction will do this in one word and without de-
stroying the contents of W.
Appendix C
©1996 microEngineering Labs C-27 PIC Macro Assembler
Reference
13. Errors
Unless specified otherwise, each of the following errors will terminate the as-
sembly of the current line. If possible, the assembler will generate correct code (or at
least the correct number of words) before the line is aborted. Assembly continues
with the next line of source.

Unless otherwise specified, the error report has no side effects other than to
bump the error count.

200 Instruction Restricted to 14-Bit Core


The opcode of the specified line cannot be used for the PIC16C5x family:
ADDLW #literal
SUBLW #literal
RETFIE
RETURN

201 ‘Character’ Expected


The assembler expected, but didn’t find, the specified character.

202 Illegal Character ‘Character’


The assembler doesn’t recognize the legal use of the specified character.

203 ‘—’ or ‘++’ Expected


The Parallax instruction MOVSZ (MOVe and Skip in Zero) must take one of
two forms : MOVSZ W,++fr
MOVSZ W,—fr

204 ‘W’ Expected as First Parameter


The Parallax instruction MOVSZ (MOVe and Skip in Zero) must take one of
two forms : MOVSZ W,++fr
MOVSZ W,—fr

205 Illegal Use of Keyword ‘Keyword’


Indicates that the specified identifier is a reserved word of the assembler and has
been improperly used.

206 CHECKSUM Not Supported in 14-Bit Core


The CHECKSUM option may be used as the ID of a processor in the PIC16C5x
family. This option is not legal on the 14-bit core.

208 Illegal Use of SUB Instruction


This error indicates an attempt was made to use the illegal instruction :
SUB W,fr

Errors
C-28 ©1996 microEngineering Labs
209 Indirect Jump Expected in Form of ‘PC+W’
This error indicates an attempt was made to use the illegal instruction :
JMP PC+Expr

210 Bit Addresses Must Differ


The Parallax MOVB bit1,/bit2 instruction requires that the source and destina-
tion bits be different. An attempt to copy the complement of a bit to itself will result
in the unconditional setting of the bit.

211 Poorly Formed Numeric Constant ‘Token’


Indicates that the symbol is not a legally formed numeric token. If any initial
portion of this token is a valid constant, that portion is converted and its value is used
as the result of the token.

212 Extra Tokens on End of Line


Some initial portion of the current line assembled correctly, but additional as-
sembly tokens remain unprocessed. This is often the result of a syntax error (extra
parameters, misplaced or missing punctuation, etc.). Code is generated for the cor-
rect initial portion of the line.

213 IRPC Expected Id or String Constant


The second parameter of the IRPC macro definition is the item (scanned charac-
ter by character) which drives the macro expansion. This item must be either an
identifier or a quote-enclosed string constant.

214 IRPC Missing Replacement Parameter


The first parameter of the IRPC macro definition is the variable which accepts
the characters scanned from the second parameter. The first parameter must be an
identifier unique within the definition of the macro.

215 Attempt to Redefine Macro ‘Identifier’


An attempt was made to redefine the named macro.

216 Attempt to Redefine Macro Parameter ‘Identifier’


Each parameter and local variable of a macro must be unique. This error indi-
cates that a parameter or local name has been duplicated.

217 Attempt to Generate Code in Non-Code Segment


Due to the Harvard Architecture (split code and data spaces) of the PICs, in-
structions may only be executed from CODE space (ROM). This error indicates that
an attempt was made to generate opcodes in the data or EEPROM segments. In
general, only the DS pseudo-op is legal in the data segment and DS, DB and DW are
the only legal pseudo-ops in the EEPROM segment.

Appendix C
©1996 microEngineering Labs C-29 PIC Macro Assembler
Reference
218 Address Limit of Address Exceeded
This error indicates that current segment has overflowed.

219 Collision in HEX File @ Address


This error indicates that more than one word has been generated for the specified
ROM address.

220 Illegal Bit Number


In the PIC (and most processors), the bits of a byte are numbered from 0 (the
least significant bit - LSB) to 7 (the most significant bit - MSB). This error indicates
that the specified bit number is not in the range of 0 to 7.

221 Illegal Bit Address


The four basic bit operators of the PIC take either an 8-bit field (12-bit core) or
a 10-bit field (14-bit core). This is composed of a register address and a bit number.
If this combination exceeds the 8 or 10 bit range for the selected processor, this error
is generated. Note that only the composite value is checked - this check in no way
guarantees the validity of the bit number or the register address. These value are,
however, checked whenever they can be checked as separate parameters.

222 Illegal Destination Specifier


Many Microchip instructions expect the second parameter to specify the destina-
tion of the operation result : 0 if the result is also the source register, 1 if the result is
to be placed in W. This error indicates that a numeric expression was used for this
parameter which neither evaluated to 0 nor 1. For clarity, the second parameter can
be omitted to use the source register as the destination and W can be used to specify
W as the destination.

223 Illegal TriState File Register Address Register


The TRIS instruction may only operate upon registers 5, 6, or 7. This error
indicates that the specified register value was other than 5, 6, or 7. The equivalent
Parallax instruction may also generate this error :

MOV !Register,Source

224 Keyword Directive Only for Use in Macros


Some keywords (such as LOCAL and ENDM) only have meaning in the defini-
tion of a macro body. This error indicates that an attempt was made to use such a
keyword in some other context.

225 Undefined Symbol ‘Identifier’


A reference was made to the specified symbol although no such symbol was
detected in the first pass of the assembler.

Errors
C-30 ©1996 microEngineering Labs
226 Numeric Constant or Symbol Name Expected
A legal expression is a well formed sentence containing operators and terminals
from which values for the operators are derived. This error indicates that an expres-
sion terminal was encountered which didn’t evaluate to a numeric value.

227 Divide by Zero


An attempt was made (in the source) to divide by zero at assembly time.

228 Modulus by Zero


An attempt was made (in the source) to take the modulus of a number by zero at
assembly time.

229 Device Doesn’t Support EEPROM


An attempt was made to generate values in the EEPROM segment for a device
which doesn’t support EEPROM.

230 Collision in EEPROM @ Address


An attempt was made to generate more that one value for the specified EEPROM
location.

231 Attempt to Redefine ‘Identifier’


An attempt was made to assign a new value to a symbol defined either as a
program label or using the EQU pseudo-op. A common (but confusing) source of
this error can result from different flows through conditional assembly blocks be-
tween the first and second passes. While this type of variant programming can be
done, it is very tricky and poor programming practice - it should be avoided.

232 File Name Expected


Indicates that the parameter specified for the current INCLUDE or MACLIB
pseudo-op is not a quoted string.

233 String Expression Expected for Title


The TITLE pseudo-op is used to replace the normal copyright notice of the
listing with a customized header. This new header must be specified as a quoted
string and is the only parameter of the TITLE pseudo-op.

234 Identifier Expected


The IFDEF and IFNDEF conditional assembly pseudo-ops require one identifier
as it parameter. This error is generated whenever this parameter is other than a legal
identifier.

235 Opcode Expected Instead of ‘Token’


Any text starting in column 2 or later which is not a commented is assumed to
either be an opcode, a pseudo-op or the name of a defined macro. All other tokens
will generate this error.

Appendix C
©1996 microEngineering Labs C-31 PIC Macro Assembler
Reference
236 Label ‘Identifier’ Undefined in Pass 0
This error indicates that an attempt was made to define the specified symbol in
pass 1, although no definition was made for the symbol during pass 0. This is almost
always the result of different flows through conditional assembly blocks between
pass 0 and pass 1.

237 IRP Missing Replacement Parameter


The IRP macro takes two parameters. The first parameter is an identifier which
is substituted on each expansion with the next item from the comma separated list
(the second parameter). This error indicates that the identifier expected for the first
parameter of the IRP statement was not found.

14. Fatal Errors


300 Too Many Errors
The assembler can generated an unlimited number of warnings, but the number
of errors is limited. While this value defaults to 15, it can be changed using the -G
option. This fatal error is generated when this allowance is exceeded.

301 Out of Memory


Indicates that the symbol table, macro table and other memory requirements for
internal bookkeeping have exceeded the memory capacity of your PC. While this
error message is unlikely, it can occur on limited or heavily burdened systems. If not
already at the 640K limit for conventional memory, add memory. Unloading or load-
ing high of TSRs and network drivers can increase usable memory. Memory may
also be gained by reducing the number of BUFFERS and FILES allocated in
CONFIG.SYS.

302 Unable to Open File ‘Filename’


Indicates that DOS was unable to open the specified file. This is either because
the file could not be found or not enough file handles were available (this usually only
occurs with deep nesting of INCLUDE and MACLIB statements). If the file exists,
make sure it resides in the current directory. If the file is an INCLUDE or MACLIB
file, also check in the default include directory. While this defaults to the INC
subdirectory of the directory where PM.EXE is kept, it can be modified using the -I
option. If the file is found as described above, try increasing the number of FILES in
CONFIG.SYS.

303 Unable to Create File ‘Filename’


Indicates that DOS was unable to create the specified file. This is either because
there are not enough file handles available or there is not enough space on the desti-
nation disk. If there is adequate disk space available, try increasing the number of
FILES in CONFIG.SYS.

Errors
C-32 ©1996 microEngineering Labs
304 No Source File Specified
This error is generated if PM is invoked with options, but without the name of a
source file. If PM is invoked with no options and no source name, a brief help screen
is displayed.

305 Unable to Write to File ‘Filename’


Indicates that DOS was unable to write to the specified file. This usually results
when there is not enough space on the destination disk or the specified file has some
special write protection (such as DOS SHARE.EXE).

306 Page Width must be 80 to 255 Columns


The PAGE pseudo-op is used to specify the size of the listing page. The first
parameter is used to specify the width of the page. This value must be between 80
and 255, inclusive.

307 Illegal Device Type


An attempt was made to use an illegal specifier with the DEVICE statement.
Such values would have 10 or 11 as the two most significant bits.

308 Macro Buffer Overflow


An attempt was made to define a macro which was larger than 4K. This usually
indicates a missing ENDM pseudo-op.

15. Internal Errors


These errors are not documented, because they should not occur. If they occur,
technical support should be contacted and a copy of the code producing the error
should be made available.

400 Attempt to Free Non-Allocated Memory [Pointer]


401 Attempt to Reference Non-Allocated Memory [Pointer]
402 Attempt to Pop Empty Symbol Table Stack
403 Attempt to Exit on Empty File Stack
404 Attempt to Pop Empty Macro Stack
405 Macro Stack Error
406 Attempt to Pop Empty Conditional Assembly Stack
407 No Function Handler for ‘Keyword’

Appendix C
©1996 microEngineering Labs C-33 PIC Macro Assembler
Reference
Notes
C-34 ©1996 microEngineering Labs
Parallax Instruction Set
D Reference

Larry found that he learned a lot of instructions during his walk home ... as long as
it didn’t rain.

Appendix D
©1998 Sirius microSystems D-1 Parallax Instruction
Set Reference
D-2 ©1998 Sirius microSystems
Table of Contents
Microchip Instructions ............................................... D-7

Parallax Instructions .................................................. D-7


Introduction ........................................................................................... D-7

Summary of Parallax Instructions ............................. D-8


Byte-oriented Operations ...................................................................... D-8
Bit-oriented operations ......................................................................... D-9
Inc/dec-conditional branches ................................................................ D-9
Compare-conditional branches............................................................. D-9
Bit-conditional branches ....................................................................... D-9
Unconditional branches ...................................................................... D-10
I/O and control operations .................................................................. D-10

ADD............................................................................ D-11
ADD destination, source ...................................................................... D-11

ADDB ......................................................................... D-11


ADDB destination, bit .......................................................................... D-11

AND............................................................................ D-12
AND destination, source ..................................................................... D-12

Call ............................................................................. D-13


Call addr .............................................................................................. D-13

Compare and Jump .................................................. D-13


Compare and jump if above .......................................................................
D-13
Compare and jump if above or equal ................................................. D-13
Compare and jump if Below ............................................................... D-14
Compare and Jump if below or equal ................................................ D-14
Compare and jump if equal ................................................................ D-15
Compare and jump if not equal .......................................................... D-15

Clear Carry ................................................................ D-16

Clear .......................................................................... D-16


CLR register/flag ................................................................................. D-16
Clear bit ............................................................................................... D-16

Compare and Skip .................................................... D-17


Compare and skip if above ................................................................. D-17
Compare and skip if above or equal .................................................. D-17
Appendix D
©1998 Sirius microSystems D-3 Parallax Instruction
Set Reference
Compare and skip if below ................................................................. D-18
Compare and skip if below or equal ................................................... D-18
Compare and skip if equal .................................................................. D-18
Compare and skip if not equal ............................................................ D-19

Decrement ................................................................. D-19


Dec file register ................................................................................... D-19
Dec file register and skip if zero ......................................................... D-19
Dec file register and jump if not zero .................................................. D-20

Increment .................................................................. D-20


Increment file register and jump if not zero ....................................... D-20
Increment file register ......................................................................... D-20
Increment file register and skip if zero.............................................. D-20

Jump .......................................................................... D-20


Jump if carry ....................................................................................... D-20
Jump to addr ....................................................................................... D-21
Jump PC + W ..................................................................................... D-21
Jump W ............................................................................................... D-21
Jump if not bit ..................................................................................... D-21
Jump if not carry ................................................................................. D-21
Jump if not zero .................................................................................. D-21
Jump if zero ........................................................................................ D-22

Long Instructions ..................................................... D-22


Long Call ............................................................................................. D-22
Long Jump .......................................................................................... D-22
Long Set ............................................................................................. D-22

Move .......................................................................... D-22


MOV destination, Source .................................................................... D-22

Bit Move .................................................................... D-25


MOVB Destination bit, Source bit ....................................................... D-25

Move and Skip .......................................................... D-26


Move and skip if zero .......................................................................... D-26

Negate ....................................................................... D-26

No Operation ............................................................. D-26

Not ............................................................................. D-26


Not fr/W ............................................................................................... D-26

OR .............................................................................. D-27
Or Destination, Source ....................................................................... D-27
Table of Contents
D-4 ©1998 Sirius microSystems
Return ........................................................................ D-28
Return from subroutine ....................................................................... D-28
Return from interrupt........................................................................... D-28
Return with value in W........................................................................ D-28

Rotate ........................................................................ D-28

Skip ............................................................................ D-29

Set .............................................................................. D-30


Set bit .................................................................................................. D-30
Set Carry ............................................................................................. D-30
Set Zero .............................................................................................. D-30

Sleep .......................................................................... D-30

Subtract ..................................................................... D-30


Sub minuend,subtrahend ................................................................... D-30

Subtract Bit ............................................................... D-31

Swap Nibbles ............................................................ D-31

Test ............................................................................ D-31

XOR ........................................................................... D-32


XOR Destination,Source .................................................................... D-32

Appendix D
©1998 Sirius microSystems D-5 Parallax Instruction
Set Reference
Notes
D-6 ©1998 Sirius microSystems
Microchip Instructions
Microchip instructions are described in detail in the PIC16C8X data sheets be-
ginning on pages 53.

Parallax Instructions
Introduction
Early adopters of the PIC microcontroller were less than pleased with the PIC’s
instruction set. While appropriate for a RISC architecture, it is somewhat cryptic
and makes code unreadable. Parallax realized this when they decided to build PIC
development tools. To overcome the problem, Parallax decided to build an 8051-like
instruction set.

The Parallax intruction set has some advantages. Most notably, the instructions
are more intuitive and generally allow programmers to write more readable code. It
also has some disadvantages. First, each Parallax instruction expands to between 1
and 4 PIC instructions. This variable instruction length makes “cycle
counting”difficult. Second, it is not always obvious from the Parallax instruction
what it actually happening. Consider the intruction mov fr,#lit. While the in-
struction does the obvious (setting the file register to the literal value), it also has the
less obvious side effect (setting the W register to the literal value). Such hidden side
effects can make debugging difficult.

Recognizing that each instruction set has advantages and disadvantages, PM


supports both. While the PIC instruction set is widely documented, the Parallax
instruction set is not. That is the purpose of this supplement.

—From microEngineering Labs “PIC Macro Assembler Instruction Set Supplement


© 1996 microEngineering Labs

The following example demostrates the syntax difference between Parallax in-
structions and Microchip instructions. Parallax instructions follow the Intel conven-
tion of listing the operands in sequentially reverse order:

Instruction Destination,Source

whereas Microchip instructions take the form:

OpCode Operand,n

Microchip instructions encode the Source in the Operand and specify the desti-
nation as a bit (n) that can represent either the Operand if n=1 (the default), or the
Working Register (W) if n=0.

We recommend that you examine both instruction sets. Work with the one you
find the most comfortable to use, or the most intuitive.

All PIC-MDS example programs are provided in Micochip and Parallax code
formats. Parallax code chapters have been printed on blue paper to distinguish them
from the Microchip code chapters.
Appendix D
©1998 Sirius microSystems D-7 Parallax Instruction
Set Reference
Summary of Parallax Instructions
Byte-oriented Operations
Words Flags W used
mov w,#literal* 1 - - Move literal into w
mov w,fr 1 Z - Move fr into w
mov fr,w 1 - - Move w into fr
mov fr,#literal 2 - W Move literal into fr
mov fr1,fr2 2 Z W Move fr2 into fr1
mov w,#literal-w 1 C,DC,Z - Move literal-w into w
mov w,fr-w‡ 1 C,DC,Z - Move fr-w into w

add w,#literal* 1 C,DC,Z - Add literal into w


add w,fr 1 C,DC,Z - Add fr into w
add fr,w 1 C,DC,Z - Add w into fr
add fr,#literal 2 C,DC,Z W Add literal into fr
add fr1,fr2 2 C,DC,Z W Add fr2 into fr1

sub fr,w 1 C,DC,Z - Subtract w from fr


sub fr,#literal 2 C,DC,Z W Subtract literal from fr
sub fr1,fr2 2 C,DC,Z W Subtract fr2 from fr1

and w,#literal 1 Z - AND literal into w


and w,fr 1 Z - AND fr into w
and fr,w 1 Z - AND w into fr
and fr,#literal 2 Z W AND literal into fr
and fr1,fr2 2 Z W AND fr2 into fr1

or w,#literal 1 Z - OR literal into w


or w,fr 1 Z - OR fr into w
or fr,w 1 Z - OR w into fr
or fr,#literal 2 Z W OR literal into fr
or fr1,fr2 2 Z W OR fr2 into fr1

xor w,#literal 1 Z - XOR literal into w


xor w,fr 1 Z - XOR fr into w
xor fr,w 1 Z - XOR w into fr
xor fr,#literal 2 Z W XOR literal into fr
xor fr1,fr2 2 Z W XOR fr2 into fr1

clr w 1 Z - Clear w
clr fr 1 Z - Clear fr

mov w,++fr 1 Z - Move fr+1 into w


inc fr 1 Z - Increment fr

mov w,—fr 1 Z - Move fr-1 into w

dec fr 1 Z - Decrement fr

mov w,>>fr 1 C - Move right-rotated fr into w


rr fr 1 C - Rotate right fr

mov w,<<fr 1 C - Move left-rotated fr into w


rl fr 1 C - Rotate left fr

mov w,<>fr 1 - - Move nibble-swapped fr into w


swap fr 1 - - Swap nibbles in fr

not w 1 Z - Perform 1’s-complement on w


mov w,/fr 1 Z - Move 1’s-complemented fr into w
not fr 1 Z - Perform 1’s-complement on fr

test w 1 Z - Test w for zero


test fr 1 Z - Test fr for zero

Summary of Parallax
Instructions D-8 ©1998 Sirius microSystems
Bit-oriented operations
Words Flags W used
addb fr,bit 2 Z - Add bit into fr
subb fr,bit† 2 Z - Subtract bit from fr

clrb bit 1 - - Clear bit


clc - - Clear carry
clz 1 - - Clear zero

setb bit 1 - - Set bit


stc 1 - - Set carry
stz 1 - - Set zero

movb bit1,bit2 4 - - Move bit2 into bit1


movb bit1,/bit2 4 - - Move not bit2 into bit1

Inc/dec-conditional branches
movsz w,++fr 1 - - Move fr+1 into w and skip if zero
incsz fr 1 - - Increment fr and skip if zero
ijnz fr,addr 2 - - Increment fr and jump if not zero

movsz w,—fr 1 - - Move fr-1 into w and skip if zero


decsz fr 1 - - Decrement fr and skip if zero
djnz fr,addr 2 - - Decrement fr and jump if not zero

Compare-conditional branches
csa fr,#literal 3 C,DC,Z W Compare and skip if above
csa fr1,fr2 3 C,DC,Z W Compare and skip if above
csae fr,#literal 3 C,DC,Z W Compare and skip if above or equal
csae fr1,fr2 3 C,DC,Z W Compare and skip if above or equal
csb fr,#literal 3 C,DC,Z W Compare and skip if below
csb fr1,fr2 3 C,DC,Z W Compare and skip if below
csbe fr,#literal 3 C,DC,Z W Compare and skip if below or equal
csbe fr1,fr2 3 C,DC,Z W Compare and skip if below or equal
cse fr,#literal 3 C,DC,Z W Compare and skip if equal
cse fr1,fr2 3 C,DC,Z W Compare and skip if equal
csne fr,#literal 3 C,DC,Z W Compare and skip if not equal
csne fr1,fr2 3 C,DC,Z W Compare and skip if not equal

cja fr,#lit,addr 4 C,DC,Z W Compare and jump if above


cja fr1,fr2,addr 4 C,DC,Z W Compare and jump if above
cjae fr,#lit,addr 4 C,DC,Z W Compare and jump if above or equal
cjae fr1,fr2,addr 4 C,DC,Z W Compare and jump if above or equal
cjb fr,#lit,addr 4 C,DC,Z W Compare and jump if below
cjb fr1,fr2,addr 4 C,DC,Z W Compare and jump if below
cjbe fr,#lit,addr 4 C,DC,Z W Compare and jump if below or equal
cjbe fr1,fr2,addr 4 C,DC,Z W Compare and jump if below or equal
cje fr,#lit,addr 4 C,DC,Z W Compare and jump if equal
cje fr1,fr2,addr 4 C,DC,Z W Compare and jump if equal
cjne fr,#lit,addr 4 C,DC,Z W Compare and jump if not equal
cjne fr1,fr2,addr 4 C,DC,Z W Compare and jump if not equal

Bit-conditional branches
sb bit 1 - - Skip if bit
sc 1 - - Skip if carry
sz 1 - - Skip if zero

snb bit 1 - - Skip if not bit


snc 1 - - Skip if not carry
snz 1 - - Skip if not zero
Words Flags W used

Appendix D
©1998 Sirius microSystems D-9 Parallax Instruction
Set Reference
jb bit,addr 2 - - Jump to address if bit
jc addr 2 - - Jump to address if carry
jz addr 2 - - Jump to address if zero

jnb bit_addr,addr 2 - - Jump to address if not bit


jnc addr 2 - - Jump to address if not carry
jnz addr 2 - - Jump to address if not zero

Unconditional branches
skip 1 - - Skip following instruction word
(Skip should be followed by a single word instruction)

jmp addr 1 - - Jump to address


jmp pc+w 1 C,DC,Z - Add w into pcl
jmp w 1 - - Move w into pcl

call add 1 - - Call to address


ret 1 - - Return from call
retw lit,lit... 1 - - Return from call with literal in w

reti 1 - - Return from interrupt

I/O and control operations

mov !port,w* 1 - - Move w into port’s tris


mov !port,#lit* 2 - W Move literal into port’s tris
mov !port,fr* 2 Z W Move fr into port_fr’s tris

mov !option,w* 1 - - Move w into option


mov !option,#lit* 2 - W Move literal into option
mov !option,fr* 2 Z W Move fr into option

clr wdt 1 TO,PD - Clear wdt and prescaler


sleep 1 TO,PD - Clear wdt and enter sleep mode

nop 1 - - No operation

* Applies to PIC16C71 and PIC16C84 only


† PM implementation differs from Parallax
‡ Not implemented by PM

Source & Destination Descriptions:


fr & frn represent one of the PIC File Registers (see Chaper 3)
w represents the Working Register
#literal is an 8-bit numeric constant
bit corresponds to a bit in a file register and can also be represented as
fr,n where n (from 0-7) represents the nth bit of file register fr
addr can be a memory address or address label

Summary of Parallax
Instructions D-10 ©1998 Sirius microSystems
ADD
ADD destination, source
Destination = Destination + Source. Destination may be W or a file register.
Source may be W, a file register or a literal (all literals must have a # sign as their
first char).

ADD fr,#literal Reg./Flags affected: W,C,DC,Z


Words: 2
Add literal into fr. Translates to: Cycles: 2
movlw literal ;W=literal
addwf fr1 ;fr=fr+W

Note: Although not explicitly referenced, ADD fr,#literal modifies W.

ADD fr1,fr2 Reg./Flags affected: W,C,DC,Z


Add fr2 into fr1. Translates to: Words: 2
Cycles: 2
movf fr2,0 ;W=fr2
addwf fr1 ;fr1=fr1+W

Note: Although not explicitly referenced, ADD fr1,fr2 modifies W.


ADD fr,W
Reg./Flags affected: C,DC,Z
Add W into fr. Translates to: Words: 1
Cycles: 1
addwf fr ;W=W+fr

ADD W,#literal Reg./Flags affected: W,C,DC,Z


Add literal into W. Translates to: Words: 1
Cycles: 1
addlw literal ;W=W+literal

ADD W,fr
Reg./Flags affected: W,C,DC,Z
Add fr into W. Translates to: Words: 1
Cycles: 1
addwf fr,0 ;W=W+fr

ADDB
ADDB destination, bit
If bit = 1, destination = destination + 1. If bit = 0, destination = destination + 0.
Destination must be a file register.

ADDB fr,bit Reg./Flags affected: Z


Words: 2
Translates to: Cycles: 2
btfsc bit ;if bit=0,PC=PC+2
incf fr ;fr=fr+1

Appendix D
©1998 Sirius microSystems D-11 Parallax Instruction
Set Reference
AND
AND destination, source

Destination=logical and with source. Destination may be fr or W. Source may fr,


W or literal (precede literal with a # sign).

AND fr,#literal Reg./Flags affected: W,Z


Words: 2
AND literal into file register.
Cycles: 2
Translates to:
movlw literal ;W=literal
andwf fr ;fr=fr&W

Usefull for masking out or including desired bits. For example, to isolate the
bottom three bits in a file register AND the file register with #07h. Eg.

fr = 55h 01010101
and fr, #07h and 00000111
results in fr = 5h 00000101

Note: Although not explicitly referenced, and fr,#literal modifies W.

AND fr1,fr2 Reg./Flags affected: W,Z


Words: 2
And fr2 into fr1. Translates to: Cycles: 2
movf fr2,0 ;W = fr2
andwf fr1 ;fr1 = W and fr2

Note: Although not explicitly referenced, and fr,fr2 modifies W.


AND fr,W Reg./Flags affected: Z
Words: 1
And W into fr. Translates to: Cycles: 1
andwf fr ;fr=fr&W

AND W,#literal Reg./Flags affected: W,Z


Words: 1
And literal into W. Translates to:
Cycles: 1
andlw literal ;W=W&literal

AND W,fr Reg./Flags affected: W,Z


Words: 1
And fr into W. Translates to: Cycles: 1
andwf fr,0 ;W=W&fr

D-12 ©1998 Sirius microSystems


Call
Call addr
Calls the subroutine located at address location specified by label addr. Execu-
tion will continue at subroutine location until a return instruction executes. After
return execution continues at the intstruction after the CALL.

CALL addr Reg./Flags affected: none


Words: 1
Call Subroutine. Translates to:
Cycles: 2
call addr ;push PC:PC=addr

Compare and Jump


Compare and jump if above

CJA fr,#literal,addr Reg./Flags affected: W,C,DC,Z


Compare fr to literal and jump if above. Words: 4
Translates to: Cycles: 4(5 if jump)

movf fr1,0 ;W=fr1


subwf, fr2,0 ;W=fr2-W
btfsc C ;if fr<=literal, PC=PC+2
goto addr ;pc=addr

Note: Although not explicitly referenced, CJA fr,#literal,addr modifies W.


CJA fr1,fr2,addr Reg./Flags affected: W,C,DC,Z
Compare fr1 to fr2 and jump if above Words: 4
to addr. Translates to: Cycles: 4(5 if jump)

movf fr1,0 ;W=fr1


subwf, fr2,0 ;W=fr2-W
btfss C ;if fr1<=fr2, PC=PC+2
goto addr ;pc=addr

Note: Although not explicitly referenced, CJA fr1,fr2,addr modifies W.

Compare and jump if above or equal

CJAE fr,#literal,addr Reg./Flags affected: W,C,DC,Z


Words: 4
Compare fr to literal and jumps if above
Cycles: 4(5 if jump)
or equal to addr. Translates to:
movlw literal ;W=literal
subwf, fr,0 ;W=fr-W
btfsc C ;if fr<literal, PC=PC+2
goto addr ;pc=addr

Appendix D
©1998 Sirius microSystems D-13 Parallax Instruction
Set Reference
CJAE fr1,fr2,addr Reg./Flags affected: W,C,DC,Z
Words: 4
Compare fr1 to fr2 and jumps if above
Cycles: 4(5 if jump)
or equal to addr. Translates to:
movf fr2,0 ;W=fr2
subwf, fr1,0 ;W=fr1-W
btfsc C ;if fr1<fr2, PC=PC+2
goto addr ;pc=addr

Note: Although not explicitly referenced, CJAE fr1,fr2,addr modifies W.

Compare and jump if Below

CJB fr1,#literal,addr Reg./Flags affected: W,C,DC,Z


Words: 4
Compare fr1 to literal and jump if below
Cycles: 4(5 if jump)
to addr. Translates to:
movlw literal ;W=literal
subwf, fr,0 ;W=fr-W
btfss C ;if fr>=literal, PC=PC+2
goto addr ;pc=addr

Note: Although not explicitly referenced, CJB fr1,#literal,addr modifies W.

CJB fr1,fr2,addr Reg./Flags affected: W,C,DC,Z


Words: 4
Compare fr1 to fr2 and jump if below
Cycles: 4(5 if jump)
to addr. Translates to:
movf fr2,0 ;W=literal
subwf, fr1,0 ;W=fr1-W
btfss C ;if fr>=fr2, PC=PC+2
goto addr ;pc=addr

Note: Although not explicitly referenced, CJB fr1,fr2,addr modifies W.

Compare and Jump if below or equal

CJBE fr,#literal,addr Reg./Flags affected: W,C,DC,Z


Words: 4
Compare fr1 to literal and jump if below
Cycles: 4(5 if jump)
or equal to addr. Translates to:
movlw ~literal;W=~literal
addwf fr,0 ;W=fr+W
btfss C ;if fr> literal, PC=PC+2
goto addr ;pc=addr

Note: Although not explicitly referenced, CJBE fr,#literal,addr modifies W.

D-14 ©1998 Sirius microSystems


CJBE fr1,fr2,addr Reg./Flags affected: W,C,DC,Z
Words: 4
Compare fr1 to fr2 and jump if below
Cycles: 4(5 if jump)
or equal to addr. Translates to:
movf fr1,0 ;W=fr1
subwf, fr2,0 ;W=fr2-W
btfsc C ;if fr>=fr2, PC=PC+2
goto addr ;pc=addr

Note: Although not explicitly referenced, CJBE fr1,fr2,addr modifies W.

Compare and jump if equal

CJE fr,#literal,addr Reg./Flags affected: W,C,DC,Z


Compare fr to literal and jump if equal Words: 4
to addr. Translates to: Cycles: 4(5 if jump)

movlw literal ;W=literal


subwf, fr,0 ;W=fr-W
btfsc Z ;if fr<>literal, PC=PC+2
goto addr ;pc=addr

Note: Although not explicitly referenced, CJE fr1,#literal,addr modifies W.


CJE fr1,fr2,addr Reg./Flags affected: W,C,DC,Z
Compare fr1 to fr2 and jump if equal Words: 4
to addr. Translates to: Cycles: 4(5 if jump)

movf fr2,0 ;W=literal


subwf, fr1,0 ;W=fr1-W
btfsc Z ;if fr<>fr2, PC=PC+2
goto addr ;pc=addr

Note: Although not explicitly referenced, CJE fr1,fr2,addr modifies W.

Compare and jump if not equal

CJNE fr,#literal Reg./Flags affected: W,C,DC,Z


Words: 4
Compare fr to literal and jump if not equal
Cycles: 4(5 if jump)
to addr. Translates to:
movlw literal ;W=literal
subwf, fr,0 ;W=fr-W
btfss Z ;if fr=literal, PC=PC+2
goto addr ;pc=addr

Note: Although not explicitly referenced, CJNE fr,#literal,addr modifies W.

Appendix D
©1998 Sirius microSystems D-15 Parallax Instruction
Set Reference
CJNE fr1,fr2,addr Reg./Flags affected: W,C,DC,Z
Compare fr1 to fr2 and jump if equal Words: 4
to addr. Translates to: Cycles: 4(5 if jump)

movf fr2,0 ;W=literal


subwf, fr1,0 ;W=fr1-W
btfsc Z ;if fr1=fr2, PC=PC+2
goto addr ;pc=addr

Note: Although not explicitly referenced, CJNE fr1,fr2,addr modifies W.

Clear Carry
CLC
Reg./Flags affected: C
Clears the carry flag. Translates to: Words: 1
Cycles: 1
bcf C ;C=0

Clear
CLR register/flag
Register/flag = 0. Clears the specified register or flag.
CLR fr Reg./Flags affected: Z
Clears fr. Translates to: Words: 1
Cycles: 1
clrf fr ;fr=0

CLR W Reg./Flags affected: Z


Words: 1
Clears the working register.
Cycles: 1
Translates to:
clrw ;W=0

CLR WDT
Reg./Flags affected: T0,PD
Clears the watchdog timer Words: 1
Translates to: Cycles: 1

clrwdt ;reset WDT

Clear bit

CLRB bit Reg./Flags affected: none


Words: 1
Clears the specified bit.
Cycles: 1
Translates to:
bcf bit ;bit=0

D-16 ©1998 Sirius microSystems


CLZ Reg./Flags affected: none
Clears the zero flag. Words: 1
Translates to: Cycles: 1

bcf Z

Compare and Skip


Compare and skip if above
CSA fr,#literal Reg./Flags affected: W,C,DC,Z
Compare fr to literal and skip next Words: 3
instruction if above.Translates to: Cycles: 3 (4 if skip)

movlw ~lit ;W=~literal


addwf fr,W ;W=W+fr
btfss C ;If fr>literal, PC=PC+2

Note: Although not explicitly referenced, CSA fr,#literal,addr modifies W.


CSA fr1,fr2 Reg./Flags affected: W,C,DC,Z
Compare fr1 to fr2 and skip next Words: 3
instruction if above.Translates to: Cycles: 3 (4 if skip)

movf fr,0 ;W=~fr1


subwf fr2,0 ;W=fr2-W
btfsc C ;If fr1>fr2, PC=PC+2

Note: Although not explicitly referenced, CSA fr1,fr2,addr modifies W.

Compare and skip if above or equal


CSAE fr,#literal Reg./Flags affected: W,C,DC,Z
Words: 3
Compare fr to literal and skip next
Cycles: 3 (4 if skip)
instruction if above or equal .Translates to:
movlw lit ;W=literal
subwf fr,0 ;W=W-fr
btfss C ;If fr>=literal, PC=PC+2

Note: Although not explicitly referenced, CSAE fr,#literal,addr modifies W.


CSAE fr1,fr2 Reg./Flags affected: W,C,DC,Z
Words: 3
Compare fr1 to fr2 and skip next
Cycles: 3 (4 if skip)
instruction if above or equal.Translates to:
movf fr1,0 ;W=fr2
subwf fr1,0 ;W=fr1-W
btfsc C ;If fr1>=fr2, PC=PC+2

Note: Although not explicitly referenced, CSAE fr1,fr2,addr modifies W.

Appendix D
©1998 Sirius microSystems D-17 Parallax Instruction
Set Reference
Compare and skip if below
CSB fr,#literal Reg./Flags affected: W,C,DC,Z
Compare fr to literal and skip next Words: 3
instruction if below. Translates to: Cycles: 3 (4 if skip)

movlw lit ;W=literal


subwf fr,0 ;W=fr-W
btfsc C ;If fr<literal, PC=PC+2

Note: Although not explicitly referenced, CSB fr,#literal,addr modifies W.


CSB fr1,fr2 Reg./Flags affected: W,C,DC,Z
Compare fr1 to fr2 and skip next Words: 3
instruction if below. Translates to: Cycles: 3 (4 if skip)

movf fr2,0 ;W=~fr2


subwf fr1,0 ;W=fr1-W
btfsc C ;If fr1<fr2, PC=PC+2

Note: Although not explicitly referenced, CSB fr1,fr2,addr modifies W.

Compare and skip if below or equal


CSBE fr,#literal Reg./Flags affected: W,C,DC,Z
Compare fr to literal and skip next Words: 3
instruction if below or equal. Translates to: Cycles: 3 (4 if skip)

movlw ~lit ;W=~literal


addwf fr,0 ;W=W+fr
btfsc C ;If fr<=literal, PC=PC+2

Note: Although not explicitly referenced, CSBE fr,#literal,addr modifies W.


CSBE fr1,fr2 Reg./Flags affected: W,C,DC,Z
Compare fr1 to fr2 and skip next Words: 3
instruction if below or equal. Translates to: Cycles: 3 (4 if skip)

movf fr1,0 ;W=~fr1


subwf fr2,0 ;W=fr2-W
btfss C ;If fr1<=fr2, PC=PC+2

Note: Although not explicitly referenced, CSBE fr1,fr2,addr modifies W.

Compare and skip if equal


CSE fr,#literal Reg./Flags affected: W,C,DC,Z
Words: 3
Compare fr to literal and skip next
Cycles: 3 (4 if skip)
instruction if equal. Translates to:
movlw lit ;W=literal
subwf fr,0 ;W=W-fr
btfss C ;If fr=literal, PC=PC+2

Note: Although not explicitly referenced, CSBE fr,#literal,addr modifies W.

D-18 ©1998 Sirius microSystems


CSE fr1,fr2 Reg./Flags affected: W,C,DC,Z
Compare fr1 to fr2 and skip next Words: 3
instruction if equal. Translates to: Cycles: 3 (4 if skip)

movf fr2,0 ;W=fr2


subwf fr1,0 ;W=fr1-W
btfss C ;If fr1=fr2, PC=PC+2

Note: Although not explicitly referenced, CSE fr1,fr2,addr modifies W.

Compare and skip if not equal


CSNE fr,#literal Reg./Flags affected: W,C,DC,Z
Compare fr to literal and skip next Words: 3
instruction if equal. Translates to: Cycles: 3 (4 if skip)

movlw lit ;W=literal


subwf fr,0 ;W=fr-W
btfsc C ;If fr<>literal, PC=PC+2

Note: Although not explicitly referenced, CSBE fr,#literal,addr modifies W.

CSNE fr1,fr2 Reg./Flags affected: W,C,DC,Z


Compare fr1 to fr2 and skip next Words: 3
instruction if equal. Translates to: Cycles: 3 (4 if skip)

movf fr2,0 ;W=fr2


subwf fr1,0 ;W=fr1-W
btfss C ;If fr1<>fr2, PC=PC+2

Note: Although not explicitly referenced, CSNE fr1,fr2,addr modifies W.

Decrement
Dec file register
DEC fr Reg./Flags affected: Z
Fr=fr-1. Decrements the specified Words: 1
file register. Translates to: Cycles: 1

decf fr ;fr=fr-1

Dec file register and skip if zero


DECSZ fr Reg./Flags affected: none
Words: 1
Decrement the specified file register and
Cycles: 1 (2 if skip)
skip next instruction if zero results.
Translates to:
decfsz fr ;fr=fr-1:if 0,PC=PC+2

Appendix D
©1998 Sirius microSystems D-19 Parallax Instruction
Set Reference
Dec file register and jump if not zero
DJNZ fr,addr Reg./Flags affected: none
Decrement the specified file register and Words: 2
jump to addr if result is not zero. Cycles: 2(3 if jump)
Translates to:
decfsz fr ;fr=fr-1:If 0,PC=PC+2
goto addr ;PC=addr

Increment
Increment file register and jump if not zero
IJNZ fr,addr Reg./Flags affected: none
fr=fr+1. Increments the specified Words: 2
file register and jump to addr if result Cycles: 2(3 if jump)
is not zero. Translates to:
incfsz fr ;fr==fr+1: If 0,PC=PC+2
goto addr ;PC=addr

Increment file register


INC fr Reg./Flags affected: Z
Increment the specified file register. Words: 1
Translates to: Cycles: 1

incf fr ;fr=fr+1

Increment file register and skip if zero


INCSZ fr Reg./Flags affected: none
fr=fr+1. Increments the specified Words: 1
file register and skips next instruction if Cycles: 1 (2 if skip)
result is zero. Translates to:
incfsz fr ;fr=fr+1: If 0,PC=PC+2

Jump
Jump if carry
JC addr Reg./Flags affected: none
Jump if carry bit set to addr. Words: 1
Translates to: Cycles: 1 (2 if skip)

btfsc C ;IF C=0,PC=PC+2


goto addr ;PC=addr

D-20 ©1998 Sirius microSystems


Jump to addr
JMP addr Reg./Flags affected: none
Words: 1
Jump to address.
Cycles: 2
Translates to:

goto addr ;PC=addr

Jump PC + W
JMP PC+W Reg./Flags affected: C,DC,Z
Words: 1
Skips W+1 instructions.
Cycles: 2
Translates to:

addwf PCL ;PC=PC+W+1

Jump W
JMP W Reg./Flags affected: none
Words: 1
Jump to W.
Cycles: 2
Translates to:

movwf PCL ;PC=(PCLATH<<8)+W

Jump if not bit


JNB bit,addr
Reg./Flags affected: none
Jump if bit equals 0 to addr. Words: 2
Translates to: Cycles: 2(3 if jump)

btfss bit ;If bit=1,PC=PC+2


goto addr ;PC=addr

Jump if not carry


JNC addr Reg./Flags affected: none
Jump if carry equals 0 to addr. Words: 2
Translates to: Cycles: 2(3 if jump)

btfss C ;If C=1,PC=PC+2


goto addr ;PC=addr

Jump if not zero


JNZ addr Reg./Flags affected: none
Words: 2
Jump if Z flag equals 0 to addr.
Cycles: 2(3 if jump)
Translates to:

btfss Z ;If Z=1, PC=PC+1


goto addr ;PC=addr

Appendix D
©1998 Sirius microSystems D-21 Parallax Instruction
Set Reference
Jump if zero
JZ addr Reg./Flags affected: none
Words: 2
Jump if Z flag equals 1 to addr.
Cycles: 2(3 if jump)
Translates to:

btfsc Z ;If Z=0.PC=PC+2


goto addr ;PC=addr

Long Instructions
Long Call

LCALL addr Reg./Flags affected: none


Words: 1-3
Perfroms a long call.
Cycles: 2-4
[bcf/bsf PCLTH.4] ;set if 8k code
[bcf/bsf PCLTH.3] ;set if 4k or 8k code
call addr

Long Jump

LJMP addr Reg./Flags affected: none


Performs a long jump. Words: 1-3
Cycles: 2-4
[bcf/bsf PCLTH.4] ;set if 8k code
[bcf/bsf PCLTH.3] ;set if 4k or 8k code
goto addr ;Push PC: PC=addr

Long Set

LSET addr
Reg./Flags affected: none
Perfroms a long set. Words: 1-3
Cycles: 2-4
[bcf/bsf PCLTH.4] ;set if 8k code
[bcf/bsf PCLTH.3] ;set if 4k or 8k code

Move
MOV destination, Source
Moves the source into the destination. Source may be a file register or register.
Destination is a file register.
MOV fr,#literal Reg./Flags affected: W
Move literal into file register. Words: 2
Translates to: Cycles: 2

movlw literal ;W=literal


movwf fr ;fr=W

Note: Although not explicitly referenced, MOV fr,#literal modifies W.

D-22 ©1998 Sirius microSystems


MOV fr1,fr2 Reg./Flags affected: W,Z
Words: 2
Move fr2 into fr1.
Cycles: 2
Translates to:
movf fr2,0 ;W=fr2
movwf fr1 ;fr1=W

Note: Although not explicitly referenced, MOV fr1,fr2 modifies W.

MOV fr,W Reg./Flags affected: none


Move W into fr. Words: 1
Translates to: Cycles: 1

movwf fr ;fr=W

MOV OPTION,#literal Reg./Flags affected: W


Words: 2
Move literal into OPTION register.
Cycles: 2
Translates to:
movlw literal ;W=literal
option ;OPTION=W

Note: Although not explicitly referenced, MOV OPTION,#literal modifies W.


Microchip recommends that the OPTION instruction not be used if upwards compatabilty
with future PIC16CXX products is desired.

MOV OPTION,fr Reg./Flags affected: W,Z


Words: 2
Move fr into OPTION register.
Cycles: 2
Translates to:
movf fr,0 ;W=fr
option ;OPTION=W

Note: Although not explicitly referenced, MOV OPTION,fr modifies W. Microchip


recommends that the OPTION instruction not be used if upwards compatabilty with
future PIC16CXX products is desired.

MOV OPTION,W Reg./Flags affected: none


Words: 1
Move W into OPTION register.
Cycles: 1
Translates to:
option

Note: Microchip recommends that the OPTION instruction not be used if upwards
compatabilty with future PIC16CXX products is desired.

Appendix D
©1998 Sirius microSystems D-23 Parallax Instruction
Set Reference
MOV !fr,#literal Reg./Flags affected: W
Move literal into fr’s TRIS register. Words: 2
Translates to: Cycles: 2

movlw literal ;W=literal


tris fr ;TRIS(fr)=W

Note: Although not explicitly referenced, MOV !fr,#literal modifies W. Micro-


chip recommends that the TRIS instruction not be used if upwards compatabilty with
future PIC16CXX products is desired.

MOV !fr1,fr2 Reg./Flags affected: W,Z


Words: 2
Move fr2 into fr’s TRIS register.
Cycles: 2
Translates to:
movf fr2,0 ;W=fr2
tris fr1 ;TRIS(fr1)=W

Note: Although not explicitly referenced, MOV !fr1,fr2 modifies W. Microchip


recommends that the TRIS instruction not be used if upwards compatabilty with future
PIC16CXX products is desired.

MOV !fr,W Reg./Flags affected: W


Move W into fr’s TRIS register. Words: 1
Translates to: Cycles: 1

tris fr ;TRIS(fr)=W

Note: Microchip recommends that the TRIS instruction not be used if upwards
compatabilty with future PIC16CXX products is desired.

MOV W,#literal Reg./Flags affected: W


Words: 1
Move literal into W register.
Cycles: 1
Translates to:
movlw literal ;W=literal

MOV W,fr Reg./Flags affected: W,Z


Move fr into W register. Words: 1
Translates to: Cycles: 1

movf fr,0 ;W=fr

MOV W,/fr Reg./Flags affected: W,Z


Words: 1
Move complement of fr into W register.
Cycles: 1
Translates to:
comf fr,0 ;W=~fr

D-24 ©1998 Sirius microSystems


MOV W,fr-W Reg./Flags affected: W,C,DC,Z
Move fr-W into W register. Words: 1
Translates to: Cycles: 1

subwf fr,0 ;W=fr-W

Note: Not supported by PM.

MOV W,++fr Reg./Flags affected: W,Z


Move fr+1 into W register. Words: 1
Translates to: Cycles: 1

incf fr,0 ;W=fr+1

MOV W,--fr Reg./Flags affected: W,Z


Words: 1
Move fr-1 into W register.
Cycles: 1
Translates to:
decf fr,0 ;W=fr-1

MOV W,<<fr Reg./Flags affected: W,C


Words: 1
Move value of fr rotated left through
Cycles: 1
carry into W register. Translates to:
rlf fr,0 ;C=fr.7:W=(fr<<1)|C

MOV W,>>fr Reg./Flags affected: W,C


Move value of fr rotated right through Words: 1
carry into W register. Translates to: Cycles: 1

rrf fr,0 ;C=fr.7:W=(fr>>1)|C

MOV W,<>fr Reg./Flags affected: W


Move swapped nibbles of fr into W. Words: 1
Translates to: Cycles: 1

swapf fr,0 ;W=fr[3..0]|fr[7..4]

Bit Move
MOVB Destination bit, Source bit
MOVB Bit1,Bit2 Reg./Flags affected: none
Move bit2 into bit1. Translates to: Words: 4
Cycles: 4
btfss bit2 ;if bit2=1, pc=pc+2
bcf bit1 ;bit1=0
btfsc bit2 ;if bit2=0, pc=pc+2
bsf bit1 ;bit1=1

Appendix D
©1998 Sirius microSystems D-25 Parallax Instruction
Set Reference
MOVB Bit1,/Bit2 Reg./Flags affected: none
Move complement of bit2 into bit1. Words: 4
Translates to: Cycles: 4

btfsc bit2 ;if bit2=0, pc=pc+2


bcf bit1 ;bit1=0
btfss bit2 ;if bit2=1, pc=pc+2
bsf bit1 ;bit1=1

Move and Skip


Move and skip if zero
MOVSZ W,++fr
Reg./Flags affected: W
Move fr+1 into W and skip if zero. Words: 1
Translates to: Cycles: 1

incfsz fr,0 ;W=fr+1:if 0,PC=PC+2

MOVSZ W,--fr
Reg./Flags affected: W
Move fr-1 into W and skip if zero. Words: 1
Translates to: Cycles: 1

decfsz fr,0 ;W=fr-1:if 0,PC=PC+2

Negate
NEG fr
Reg./Flags affected: Z
Negates fr. Translates to: Words: 2
Cycles: 2
comf fr ;fr=~fr
incf fr ;fr=fr+1

No Operation
NOP Reg./Flags affected: none
No operation. Translates to: Words: 1
Cycles: 1
nop ;do nothing for one machine cycle

Not
Not fr/W
Complement file or working register.

NOT fr
Reg./Flags affected: Z
Complements file register specified. Words: 1
Translates to: Cycles: 1
comf fr ;fr=~fr

D-26 ©1998 Sirius microSystems


NOT W Reg./Flags affected: Z
Complements working register. Words: 1
Translates to: Cycles: 1
xorlw 0ffh ;W=W XOR FFh = ~W

OR
Or Destination, Source
Source is ORed with Destination. Destination may be file or working register.
Source may be file or working register or a literal.

OR fr,#literal Reg./Flags affected: W,Z


Words: 2
OR literal into fr.
Cycles: 2
Translates to:

movlw literal ;W=literal


iorwfr fr

OR fr1,fr2
Reg./Flags affected: W,Z
OR fr2 into fr1. Words: 2
Translates to: Cycles: 2

movf fr2,0 ;W=fr2


iorwf fr1 ;fr1=fr1 OR W

OR fr,W
Reg./Flags affected: Z
OR W into fr. Words: 1
Translates to: Cycles: 1

iorwf fr ;fr=fr OR W

OR W,#literal
Reg./Flags affected: W,Z
OR literal into W Words: 1
Translates to: Cycles: 1

iorlw literal ;W=W OR literal

OR W,fr
Reg./Flags affected: W,Z
OR fr into W. Words: 1
Translates to: Cycles: 1

iorwf fr,0 W=W OR fr

Appendix D
©1998 Sirius microSystems D-27 Parallax Instruction
Set Reference
Return
Return from subroutine
RET Reg./Flags affected: none
Return from subroutine. Pops the value Words: 1
off the stack and places the value into Cycles: 2
the program counter. Translates to: (12 bit core)
retlw 0 ;W=0: Pop PC

Translates to: (14 bit core)


return ;Pop PC

Return from interrupt


RETI Reg./Flags affected: none
Return from interrupt subroutine. Pops the Words: 1
value off the stack and places the value Cycles: 2
into the program counter. GIE bit is set
enabling interrupts. Translates to: (14 bit core only)
retfie ;Pop PC: Set GIE

Return with value in W


RETW #literal,#literal,...
Reg./Flags affected: W
Return from subroutine with value(s) in Words: 1 - many
W. Pops the value off the stack and Cycles: 2 per literal
places the value into the program counter.
Translates to:

retlw literal1 ;Pop PC: W=literal1


retlw literal2 ;Pop PC: W=literal2
...

Rotate
RL fr Reg./Flags affected: C
Rotate fr left through carry. Words: 1
Translates to: Cycles: 1

rlf fr ;C=fr.7:fr=(fr<<1)|C

RR fr Reg./Flags affected: C
Rotate fr right through carry. Words: 1
Translates to: Cycles: 1

rrf fr ;C=fr.7:fr=(fr>>1)|C

D-28 ©1998 Sirius microSystems


Skip
SB Bit Reg./Flags affected: none
Skip next instruction if bit set. Words: 1
Translates to: Cycles: 1 (2 if skip)

btfss bit ;if bit=0,PC=PC+2

SC
Reg./Flags affected: none
Skip next instruction if Carry flag set. Words: 1
Translates to: Cycles: 1 (2 if skip)

btfss C ;if C=0,PC=PC+2

SKIP
Reg./Flags affected: none
Skip next instruction. Words: 1
Translates to: Cycles: 2

btfss 4,7

SNB bit
Reg./Flags affected: none
Skip next instruction if not bit. Words: 1
Translates to: Cycles: 1 (2 if skip)

btfsc bit ;if bit=0,PC=PC+2

SNC C Reg./Flags affected: none


Skip next instruction if not Carry. Words: 1
Translates to: Cycles: 1(2 if skip)

btfsc C ;if C=0,PC=PC+2

SNZ bit Reg./Flags affected: none


Skip next instruction if not Carry. Words: 1
Translates to: Cycles: 1(2 if skip)

btfsc Z ;if C=0,PC=PC+2

SZ Reg./Flags affected: none


Words: 1
Skip next instruction if zero.
Cycles: 1(2 if skip)
Translates to:

btfss Z ;if Z=0,PC=PC+2

Appendix D
©1998 Sirius microSystems D-29 Parallax Instruction
Set Reference
Set
Set bit

SETB Bit Reg./Flags affected: none


Bit = 1. Sets the specified bit. Words: 1
Translates to: Cycles: 1

bsf bit ;bit=1

Set Carry

STC Reg./Flags affected: C


Words: 1
Set carry flag.
Cycles: 1
Translates to:

bsf C ;C=1
Set Zero

STZ Reg./Flags affected: Z


Set zero flag. Words: 1
Translates to: Cycles: 1

bsf Z ;Z=1

Sleep
SLEEP Reg./Flags affected: TO,PD
Words: 1
Enter sleep mode.
Cycles: 1
Translates to:

sleep ;Enter low power mode

Subtract
Sub minuend,subtrahend
Subtracts the subtrahend from the minuend. Minuend must be a file register.
Subtrahend may be a file or working register or a literal.

SUB fr,#literal
Reg./Flags affected: W,C,DC,Z
Subtracts literal from fr. Words: 2
Translates to: Cycles: 2

movlw literal ;W=literal


subwf fr ;fr=fr-W

Note: Although not explicitly referenced, SUB fr,#literal modifies W

D-30 ©1998 Sirius microSystems


SUB fr1,fr2 Reg./Flags affected: W,C,DC,Z
Words: 2
Subtracts fr2from fr1.
Cycles: 2
Translates to:
movf fr2,0 ;W=fr2
subwf fr1 ;fr1=fr1-W

Note: Although not explicitly referenced, SUB fr1,fr2 modifies W.

SUB fr,W Reg./Flags affected: C,DC,Z


Subtracts W from fr. Words: 2
Translates to: Cycles: 2

subwf fr ;fr=fr-W

Subtract Bit
SUBB fr,bit Reg./Flags affected: Z (If bit 1)
Subtracts bit from fr. Words: 2
Translates to: Cycles: 2

btfsc bit
decf fr

Swap Nibbles
SWAP fr Reg./Flags affected: none
Words: 1
Swaps nibbles in fr.
Cycles: 1
Translates to:
swap fr ;fr[3..0]|fr7..4]

Test
TEST fr
Reg./Flags affected: Z
Tests fr for zero. Words: 1
Translates to: Cycles: 1

movf fr ;if fr=0,Z=1 Else Z=0

Appendix D
©1998 Sirius microSystems D-31 Parallax Instruction
Set Reference
XOR
XOR Destination,Source
Exclusive ORs destination with source. Destination may be the working register
or a file register. Source may be a literal, working or file register.

XOR fr,#literal Reg./Flags affected: W,Z


Words: 2
Exclusive OR literal into fr.
Cycles: 2
Translates to:

movlw literal ;W=literal


xorwf fr ;fr=fr XOR W

Note: Although not explicitly referenced, XOR fr,#literal modifies W.

XOR fr1,fr2 Reg./Flags affected: W,Z


Exclusive OR fr2 into fr1. Words: 2
Translates to: Cycles: 2

movf fr2,0 ;W=fr2


xorwf fr1 ;fr1=fr1 XOR W

XOR fr,W Reg./Flags affected: Z


Words: 1
Exclusive OR W into fr.
Cycles: 1
Translates to:

xorwf fr ;fr=fr XOR W

XOR W,#literal Reg./Flags affected: W,Z


Words: 1
Exclusive OR literal into W.
Cycles: 1
Translates to:

xorlw literal ;W=W XOR literal

XOR W,fr Reg./Flags affected: W,Z


Words: 1
Exclusive OR fr into W.
Cycles: 1
Translates to:

xorwf fr,0 ;W=W XOR fr

D-32 ©1998 Sirius microSystems


Program Pull-Out References
Microchip Code

While we can’t promise a solution to all your problems, we do give you a good start!

Program Pull-Out
©1998 Sirius microSystems Microchip Code 1 References
Copyright © 1996, 1998 Sirius microSystems. All rights reserved.

Second Printing.

Parallax is a Trademark of Parallax, Inc.


PICmicro™ is a Registered Trademark of Microchip Technology Inc. in the U.S.A. and other countries.

No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any
means, mechanical, electronic, photocopying, or recording, or otherwise, without the prior written permission
of Sirius microSystems.

Sirius microSystems has taken care to trace ownership of copyright material contained in this text. However,
Sirius microSystems will gladly accept any information that enables them to rectify any reference or credit in
subsequent editions.

For conditions, permissions and other rights under this copyright, contact Sirius microSystems:

Sirius microSystems
172 Harvard Road
Waterloo, ON N2J 3V3
Canada
tel.: 519.886.4462
fax: 519.886.4253
http://www.siriusmicro.com

ISBN 0-9681220-0-0 (Training Manual)


ISBN 0-9681220-1-9 (Teacher’s Reference)

Disclaimer of Liability
This manual and the program subroutines included herein are written for the Sirius microSystems PICmicro™
Development System and are provided on an “as is” basis, without any warranty, either expressed or implied.
These materials are provided for educational use only, and Sirius microSystems does not assume any liability for
damages, either incidental or consequential, arising out of the application, use, or misuse of any of its software
or hardware products. Sirius microSystems reserves the right, without further notice, to make changes to any of
its training materials, software or hardware referred to in this manual in order to improve its function, design or
reliability.

Printed in Canada.

2 Microchip Code ©1998 Sirius microSystems


Contents
PIC-MDS Subroutine Library Summary ........................................................ 5
ATOD.LIB .......................................................................................................................................5
BIN2BCD.LIB .................................................................................................................................5
BIN2DEC.LIB .................................................................................................................................6
DEC2BIN.LIB .................................................................................................................................6
EEPROM.LIB .................................................................................................................................6
KEYPAD.LIB ...................................................................................................................................7
LCD.LIB ..........................................................................................................................................7
LCD4BIT.LIB ...................................................................................................................................7
RS232RX.LIB .................................................................................................................................8
RS232TX.LIB .................................................................................................................................8
SEEPROM.LIB ...............................................................................................................................9

Subroutine Library Files


ATOD.LIB - PIC16C711 A/D Subroutine Library .......................................................................... 11
BIN2BCD.LIB - Binary to BCD Conversion Library ......................................................................13
BIN2DEC.LIB - Binary to Decimal Conversion Library .................................................................15
DEC2BIN.LIB - Decimal to Binary Conversion Library .................................................................16
EEPROM.LIB - PIC16F84 EEPROM Subroutine Library .............................................................17
KEYPAD.LIB - Keypad Subroutine Library ...................................................................................19
LCD.LIB - LCD Subroutine Library ............................................................................................... 21
LCD4BIT.LIB - 4-bit Interface LCD Subroutine Library.................................................................24
LCD71.LIB - PIC16C71/711 LCD Subroutine Library ...................................................................28
RS232RX.LIB - RS-232 Receive Subroutine Library ...................................................................31
RS232TX.LIB - RS-232 Transmit Subroutine Library ..................................................................34
SEEPROM.LIB - Serial EEPROM Subroutine Library ..................................................................37

Chapter Example Program Files


ALARM.ASM - Chapter 9 Example Program ...............................................................................43
ASCII.ASM - Chapter 12 Example Program ................................................................................45
BLIP.ASM - Chapter 8 Example Program ....................................................................................49
BOUNCE.ASM - Chapter 9 Example Program ............................................................................51
CLOCK.ASM - Chapter 11 Example Program..............................................................................53
COUNT.ASM - Chapter 8 Example Program ...............................................................................58
CUSTOM.ASM - Chapter 12 Example Program ..........................................................................59
DBOUNCE.ASM - Chapter 9 Example Program ..........................................................................63
DELAY.ASM - Chapter 8 Example Program .................................................................................65
KEY.ASM - Chapter 10 Example Program ...................................................................................66
KEYINT.ASM - Chapter 11 Example Program .............................................................................69
KEYSCAN.ASM - Chapter 9 Example Program...........................................................................73
KEYSCLB.ASM - Chapter 10 Example Program .........................................................................76
NVMEM.ASM - Chapter 13 Example Program ............................................................................79
OUTPUT.ASM - Chapter 5 Example Program .............................................................................84
RECV232.ASM - Chapter 15 Example Program ..........................................................................85
SEETEST.ASM - Chapter 17 Example Program ..........................................................................88
TIMEOUT.ASM - Chapter 18 Example Program ..........................................................................97
VMETER.ASM - Chapter 16 Example Program .........................................................................101
Program Pull-Out
©1998 Sirius microSystems Microchip Code 3 References
WDTIMER.ASM - Chapter 18 Example Program ......................................................................107
XMIT232.ASM - Chapter 15 Example Program ......................................................................... 111

4 Microchip Code ©1998 Sirius microSystems


PIC-MDS Subroutine Library Summary
This section provides a quick reference to the function, requirements if any, and
use of each subroutine library file included with the PIC-MDS. All variables shown
as belonging to a subroutine library are not defined in the library code. These vari-
ables must be defined (in the form of an EQUate statement) by the program that
calls the library. For more details on library subroutines and operation, see the indi-
vidual library pull-out programs and the chapters using the libraries.

ATOD.LIB
Provides subroutine function calls for analog-to-digital (A/D) converter operation
in the PIC16C71/711.

Variables: none

Requirements: ADRES (09h) is used as a temporary register. Read ADRES con-


tents before changing the A/D port, A/D clock divisor, or initiating
a new conversion.

Use: To convert a voltage on an A/D input pin into a binary number:


1. CALL AD_Port to initialize Port A and turn on A/D. (opt.) Steps marked with (opt.)
2. Load W with a clock divisor, below, and CALL AD_Clock. (opt.) are necessary when first
ADCLK2 - oscillator/2 calling the library and are
ADCLK8 - oscillator/8 unneccessary for subse-
ADCLK32 - oscillator/32 quent calls provided that no
ADCLKRC - internal RC oscillator other libraries are called in
between. For example,
3. Load W with a pin number, below, and call AD_Channel. (opt.)
calling LCD_Port after
ADCH0 - channel 0, pin RA0/AN0 calling AD_Port will
ADCH1 - channel 1, pin RA1/AN1 reconfigure Port A for
ADCH2 - channel 2, pin RA2/AN2 digital I/O. Before calling
ADCH3 - channel 3, pin RA3/AN3 AD_Poll, AD_Port must be
4. CALL AD_Poll to start the conversion. called.
5. Read the conversion result from ADRES.

BIN2BCD.LIB
Converts a 16-bit binary number into five BCD nybbles.

Variables: HighByte - upper eight bits of the 16-bit number to convert


LowByte - lower eight bits of the 16-bit number to convert
TenThous - ten-thousands digit of result stored in lower nybble
ThouHund - thousands digit and hundreds digit of result
TensOnes - tens digit and ones digit of result
ShiftCounter - a counter used to count shifts during a conversion

Requirements: none

Use: To convert a 16-bit number into five BCD digits:


1. Move a 16-bit binary number into HighByte and LowByte.
2. CALL BIN_BCD to initiate the conversion.
3. Read conversion results from TenThous, ThouHund, & TensOnes.
Program Pull-Out
©1998 Sirius microSystems Microchip Code 5 References
BIN2DEC.LIB
Converts an 8-bit binary number into three binary digits.

Variables: Hundreds - hundreds digit of the result


Tens - tens digit of the result
Ones - ones digit of the result

Requirements: none

Use: To convert an 8-bit binary number into three binary digits:


1. Load W with the binary number to be converted.
2. CALL BIN_DEC to initiate the conversion.
3. Read the results from Hundreds, Tens & Ones.

DEC2BIN.LIB
Converts three binary decimal (with values less than 10) digits into an 8-bit binary
number.

Variables: Hundreds - hundreds digit of the initial number


Tens - tens digit of the initial number
Ones - ones digit of the initial number

Requirements: none

Use: To convert three binary digits into an 8-bit binary number:


1. Load Hundreds, Tens & Ones with the numbers to be converted.
2. CALL DEC_BIN to initiate the conversion.
3. Read the result from W.

EEPROM.LIB
Provides function calls for the internal data EEPROM in the PIC16C/F84.

Variables: none

Requirements: none

Use: To write data into an EEPROM address:


1. Move an EEPROM address into EEADR.
2. Move a data byte into EEDATA.
3. CALL EE_Write.

To wait for EEPROM write completion:


1. CALL EE_Wait.

To read data from an EEPROM address:


1. Move an EEPROM address into EEADR.
2. CALL EE_Read.
3. Read the data from EEDATA.

6 Microchip Code ©1998 Sirius microSystems


KEYPAD.LIB
Provides function calls for keypad scanning on the PIC-MDS. Returns a key code
corresponding to the key number of any one key being pressed. A return code of 0
indicates no keys are pressed. This library does not implement key debouncing.

Variables: Key - contains the key code following a key scan

Requirements: none

Use: To scan for a key press:


1. CALL KB_Port to configure Port B for keypad use. (opt.)
2. CALL KB_Scan to scan for a key press.
3. Read the key code from Key.

LCD.LIB
Provides function calls for LCD operation in 8-bit mode (this is the default mode for
PIC-MDS programs).

Variables: none

Requirements: 1. Two free levels of processor stack are required for nested calls.
2. The calling program must provide a 5 ms (minimum) time delay
routine called Delay_5ms.

Use: To initialize the LCD display after power-up:


1. CALL LCD_Port to configure Port A and Port B for the LCD.
2. CALL LCD_Init to initialize the LCD controller.

To write a character to the current LCD cursor position:


1. CALL LCD_Port to configure Ports A and B for the LCD. (opt.)
2. Load W with the ASCII value of the character.
3. CALL LCD_Data to display the character.

To write a command or character address to the LCD controller:


1. CALL LCD_Port to configure Ports A and B for the LCD. (opt.)
2. Load W with the command or character address.
3. CALL LCD_Reg to write the data into the LCD controller.

Some important LCD commands (see the library file for others):
LCDLine1 - character address for the start of line 1
LCDLine2 - character address for the start of line 2
LCDCLR - clears the LCD display memory
LCDInc - sets automatic cursor increment mode
CursOn - displays the LCD cursor
CursOff - disables display of the LCD cursor

LCD4BIT.LIB
Same as LCD.LIB but operates in 4-bit mode. Requirements and Use are as above.

Variables: LCDTemp - stores commands and data for transmission.


Program Pull-Out
©1998 Sirius microSystems Microchip Code 7 References
RS232RX.LIB
Provides function calls to receive RS-232 serial data without handshaking. The de-
fault RS-232 data rate is 9600 bps, although this can by changed by modifying the
Bit_Time variable in RS232RX.LIB. Subroutines are provided to wait for a serial
character, or to begin reception after the calling program detects a start bit. If a
framing error occurs during reception, the Receive byte will be cleared (00h).

Variables: Counter - delay counter for bit time delay loop


BitCounter - counts number of received bits
Receive - holds received serial character

Requirements: Two free levels of processor stack are required for nested calls.

Use: To wait for and receive a serial character:


1. CALL Receive_Port to configure Port A.4 for input.
2. CALL Receive_Wait to wait for the next serial character.
3. Read the received character from Receive.

To receive a serial character after detecting a start bit:


1. CALL Receive_Port prior to waiting for a start bit.
2. CALL Receive_Data after detecting a start bit.
3. Read the received character from Receive.

RS232TX.LIB
Provides function calls to transmit RS-232 serial data without handshaking. The
default RS-232 data rate is 9600 bps, although this can be changed by modifying the
Bit_Time variable in RS232TX.LIB.

Variables: Counter - delay counter for bit time delay loop


BitCounter - counts number of transmitted bits
Transmit - stores the serial character to be transmitted

Requirements: Two free levels of processor stack are required for nested calls.

Use: To transmit a serial character:


1. CALL Transmit_Port to configure Port A.4 for output.
2. Move the byte to be transmitted into Transmit.
3. CALL Transmit_Data to send the serial byte.

8 Microchip Code ©1998 Sirius microSystems


SEEPROM.LIB
Provides function calls for interfacing to 93LC56 (256-byte) and 93LC66 (512-byte)
serial EEPROMs (SEEPROMs) in 8-bit mode only.

Variables: SEEClock - clock counter register for serial data frame


SEEData - SEEPROM data byte storage register
SEEAddrh - SEEPROM high address byte
SEEAddrl - SEEPROM low address byte

Requirements: Two free levels of processor stack are required for nested calls.

Use: To enable or disable SEEPROM write access:


1. CALL SEE_Port to configure Ports A & B. (opt.)
2. Move SEEEWEN (enable) or SEEEWDS (disable) into W.
3. CALL SEE_Command to send the command to the SEEPROM.

To write a data byte into a SEEPROM address:


1. CALL SEE_Port to configure Ports A & B. (opt.)
2. Load SEEAddrh with the high byte of the SEEPROM address.
3. Load SEEAddrl with the low byte of the SEEPROM address.
4. Load SEEData with the data byte to be written.
5. Move the SEEWrite constant into W.
6. CALL SEE_Command to initiate the write operation.
7. CALL SEE_Wait to wait for the completion of the write. (opt.)

To read a data byte from a SEEPROM address:


1. CALL SEE_Port to configure Ports A & B. (opt.)
2. Load SEEAddrh with the high byte of the SEEPROM address.
3. Load SEEAddrl with the low byte of the SEEPROM address.
4. Move the SEERead constant into W.
5. CALL SEE_Command to initiate the write operation.
6. Read the data byte from SEEData.

See the library pull-out for information on the Erase, Erase All, and
Write All commands.

Program Pull-Out
©1998 Sirius microSystems Microchip Code 9 References
10 Microchip Code ©1998 Sirius microSystems
ATOD.LIB - PIC16C711 A/D Subroutine Library
;ATOD.LIB V1.2 Last Modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This subroutine library provides calls for A/D converter operation,


; including:
; - Port configuration
; - A/D Channel selection
; - Conversion Clock selection
; - A/D conversion routine with polling

;Variables

; No file register variables are required by this subroutine library.


; ADRES (09h) is used for temporary storage.

;Requirements

; ADRES (09h) is used as a temporary register before conversion. Ensure


; that its data has been read before calling the library functions for
; the next conversion. ADRES normally holds the A/D conversion result.

; Calling programs may require shorting jumpers over RA0 and RA1 on the
; JU6 header. These jumpers physically connect potentiometers VR3 and
; VR4 to the RA0 and RA1 inputs on the PIC16C711. Normally these jumpers
; are not installed to minimize the effect of an analog voltage source
; (from the potentiometers) on the digital I/O lines.

;Use

; 1. Call AD_Port to initialize Port A for A/D operation and turn on A/D
; 2. Move a clock divisor constant into W and call AD_Clock
; 3. Move a channel selector constant into W and call AD_Channel
; 4. Call AD_Poll
; 5. Read the result from ADRES

;A/D Clock Divisor Software Constants

ADCLK2 EQU 00000000b ;A/D clock=oscillator/2


ADCLK8 EQU 01000000b ;A/D clock=oscillator/8
ADCLK32 EQU 10000000b ;A/D clock=oscillator/32
ADCLKRC EQU 11000000b ;A/D clock from internal RC osc.

;One A/D clock (TAD) must be greater than 2 microseconds. Choose a clock
;divider from above based on your oscillator frequency.

;eg. 16 MHz oscillator 1 oscillator clock = T = 62.5 ns


;
; TAD / T = Clock divider
; 2 us / 62.5 ns = 32
;
; Therefore, a 16 MHz oscillator must be divided by 32 to
; produce the correct A/D clock.
;

Program Pull-Out
©1998 Sirius microSystems Microchip Code 11 References
ATOD.LIB - PIC16C711 A/D Subroutine Library
;An A/D conversion completes in 10 TAD. For the example above, the
;conversion will finish in 20 microseconds.

;Using the internal oscillator allows a conversion to be performed during


;SLEEP for greatest accuracy. Use interrupt to wake processor when the
;conversion finishes. Conversion time with the RC oscillator is nominally
;40 microseconds but varies between individual processors.

;A/D Channel Selector Software Constants

ADCH0 EQU 00000000b ;A/D conversion on RA0


ADCH1 EQU 00001000b ;A/D conversion on RA1
ADCH2 EQU 00010000b ;A/D conversion on RA2
ADCH3 EQU 00011000b ;A/D conversion on RA3

;A/D conversion channels 2 and 3 are not implemented on the PIC-MDS but
;can be accessed through the screw terminal strip or PICBUS.

AD_Port ;Initializes ADCON1 for analog input on RA0 and RA1 with
;VDD as the voltage reference and turns A/D converter on.

BSF RP0 ;Select memory page 1


MOVLW 00000011b ;OR this byte with TRISA to enable
IORWF TRISA ;required analog pins as inputs
MOVLW 02h ;Make RA0 and RA1 analog inputs by
MOVWF ADCON1 ;writing this byte to ADCON1 (88h)
BCF RP0 ;Back to page 0
BSF ADON ;Turn A/D converter on
RETURN

AD_Clock ;Sets ACDS0 and ADCS1 bits in ADCON0 based on the number
;in W. Load W with a clock divider constant from the
;list, above. Read ADRES before calling AD_Clock.

MOVWF ADRES ;Use ADRES as temporary storage


MOVLW 3Fh ;Load W with 0011 1111
ANDWF ADCON0,1 ;AND with ADCON0 to clear high bits
MOVF ADRES,0 ;Get clock divider bits from ADRES
IORWF ADCON0,1 ;OR with ADCON0 to set clock bits
RETURN

AD_Channel ;Sets CHS0 and CHS1 bits in ADCON0 based on the number in
;W when AD_Channel was called. Load W from channel constants
;list, above. Read ADRES before calling AD_Channel.

MOVWF ADRES ;Use ADRES as temporary storage


MOVLW 11100111b ;Load W with 1110 0111 and
ANDWF ADCON0,1 ;AND with ADCON0 to clear CHS0/1
MOVF ADRES,0 ;Get channel select bits from ADRES
IORWF ADCON0,1 ;OR with ADCON0 to set channel bits
RETURN

AD_Poll ;Sets GO_DONE bit in ADCON0 to start the A/D conversion


;and keeps polling the bit until the conversion is
;complete. Get the result of the conversion from ADRES.

BSF GO_DONE ;Start A/D conversion


:Loop BTFSC GO_DONE ;Check GO_DONE for end of conversion
GOTO :Loop ;and keep checking until done
RETURN

12 Microchip Code ©1998 Sirius microSystems


BIN2BCD.LIB - Binary to BCD Conversion Library
;BIN2BCD.LIB V1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This subroutine library converts 16-bit binary numbers to five BCD


; digits stored in three file register locations. The result registers
; are TenThous to hold the ten-thousands digit, ThouHund to hold the
; thousands and hundreds digits, and TensOnes to hold the tens and ones
; digits. This subroutine is useful for displaying a 16-bit variable as
; five decimal digits on the LCD display.

; This routine takes 458 clock cycles to complete. If you don’t need
; 16-bit accuracy—for example for a 12-bit A/D converter—you can
; redefine the BinBits (Binary Bits) variable for the number of bits of
; accuracy that are required. This results in shorter conversion times.

; Note also that the contents of HighByte and LowByte are corrupted during
; the conversion and therefore their contents will have changed upon
; returning to the calling program.

;Variables

; The following variables must be defined as file register locations in


; your calling program. Use the format:

; Variable name EQU File Register location (0Ch to 2Fh)

; HighByte - the high byte of the 16-bit number to convert


; LowByte - the low byte of the 16-bit number to convert
; TenThous - the ten-thousands digit of the result
; ThouHund - the thousands and hundreds digits of the result
; TensOnes - the tens and ones digits of the result
; ShiftCounter - a counter used to count shifts during the conversion

; The following variable is a Software variable that defines the number


; of bits to be converted. By default, this is 16 bits.

; BinBits - equated to 16. Change this in the program to


; convert fewer digits

;Use

; 1. Move the binary number into HighByte and LowByte


; 2. Call BIN_BCD
; 3. Retreive your results from TenThous, ThouHund, and TensOnes

;Software Equate

BinBits EQU 16 ;Number of binary bits to convert

BIN_BCD ;This conversion subroutine uses the add-3 algorithm to


;convert binary to BCD. The binary number is shifted into
;the BCD registers one bit at a time. After each shift, each

Program Pull-Out
©1998 Sirius microSystems Microchip Code 13 References
BIN2BCD.LIB - Binary to BCD Conversion Library
;BCD digit is checked to see if it is greater than or equal
;to five. If so, three is added to the BCD digit. The original
;number is the shifted again before each digit is checked to
;see if it equals or exceeds 5. After 16 shifts, the result
;is complete.

MOVLW BinBits ;Save the number binary digits in the


MOVWF ShiftCounter ;number into the ShiftCounter register

CLRF TensOnes ;Clear all BCD digits before starting


CLRF ThouHund
CLRF TenThous

GOTO ShiftBits ;Start by shifting bits into BCD regs.

Adj_BCD MOVLW 03h ;Preload W with 03 and add to lower


ADDWF TensOnes ;nybble in TensOnes register
BTFSS TensOnes.3 ;Check for a result greater than 7
SUBWF TensOnes ;If not, subtract three from nybble
MOVLW 30h ;Preload W to add 03 to upper nybble
ADDWF TensOnes ;in TensOnes register
BTFSS TensOnes.7 ;Check for a result greater than 7
SUBWF TensOnes ;If not, subtract three from nybble

MOVLW 03h ;Preload W with 03 and add to lower


ADDWF ThouHund ;nybble in ThouHund register
BTFSS ThouHund.3 ;Check for a result greater than 7
SUBWF ThouHund ;If not, subtract three from nybble
MOVLW 30h ;Preload W to add 03 to upper nybble
ADDWF ThouHund ;in ThouHund register
BTFSS ThouHund.7 ;Check for a result greater than 7
SUBWF ThouHund ;If not, subtract three from nybble

MOVLW 03h ;Preload W with 03 and add to lower


ADDWF TenThous ;nybble in TenThous register
BTFSS TenThous.3 ;Check for a result greater than 7
SUBWF TenThous ;If not, subtract three from nybble

ShiftBits BCF C ;Clear Carry before first shift


RLF LowByte ;Shift Low Byte left, C into HighByte
RLF HighByte ;Shift High Byte left, C into TensOnes
RLF TensOnes ;Shift TensOnes left, C into ThouHund
RLF ThouHund ;Shift ThouHund left, C into TenThous
RLF TenThous ;Shift TenThous left

DECFSZ ShiftCounter ;Check if all bits have been shifted


GOTO Adj_BCD ;If not, adjust digits and shift again
RETURN

14 Microchip Code ©1998 Sirius microSystems


BIN2DEC.LIB - Binary to Decimal Conversion Library
;BIN2DEC.LIB v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This subroutine library converts 8-bit binary numbers to a three-digit


; decimal code (ie. 0-0-0 - 2-5-5) and stores the result in three file
; register locations. This subroutine is useful for displaying a binary
; number as three decimal digits on the LCD display.

;Variables

; The following variables must be defined as file register locations in


; your calling program. Use the format:

; Variable name EQU File Register location (0Ch to 2Fh)

; HUNDREDS - the hundreds digit counter


; TENS - the tens digit counter
; ONES - the ones remainder

;Use

; 1. Move the binary number into W


; 2. Call BIN_DEC
; 3. Retreive your results from Hundreds, Tens and Ones

BIN_DEC ;This conversion program attempts to subtract 100 from


;the binary number until the result is negative. Each
;subtraction increments the HUNDREDS digit. When it can’t
;subtract 100, the program subtracts 10 from the remainder
;until the result once again is negative, incrementing the
;TENS digit for each subtraction. The remainder of the
;subtraction becomes the ONES digit.

CLRF HUNDREDS ;Reset the hundreds counter


CLRF TENS ;and the tens counter
MOVWF ONES ;Ones digit holds results

:Hundred MOVLW 100 ;Load W with 100 and


SUBWF ONES,W ;subtract it from the number
BTFSS C ;If result is negative
GOTO :Ten ;check for any tens
INCF HUNDREDS ;otherwise count 1 hundred
MOVWF ONES ;Remainder becomes result
GOTO :Hundred ;Check for another hundred

:Ten MOVLW 10 ;Load W with 10 and


SUBWF ONES,W ;subtract it from the number
BTFSS C ;If result is negative
RETURN ;we’re done, ONES holds remainder
INCF TENS ;otherwise count 1 ten
MOVWF ONES ;Remainder becomes result
GOTO :Ten ;Check for another ten

Program Pull-Out
©1998 Sirius microSystems Microchip Code 15 References
DEC2BIN.LIB - Decimal to Binary Conversion Library
;DEC2BIN.LIB v1.2 Last Modified on July 9, 1999

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This subroutine library converts a three-digit decimal code to an


; 8-bit binary number and returns the number in W. The three digits are
; loaded from three file register locations and should not represent a
; number larger than 255 (no error checking is done). This routine is
; useful for storing user input as a byte of data.

;Variables

; The following variables must be defined as file register locations in


; your calling program. Use the format:

; Variable name EQU File Register location (0Ch to 2Fh)

; HUNDREDS - the hundreds digit counter


; TENS - the tens digit counter
; ONES - the ones remainder

;Use

; 1. Move three decimal numbers into Hundreds, Tens and Ones


; 2. Call Dec_Bin
; 3. Retrieve the binary number from W

Dec_Bin ;This conversion program starts by clearing W. 100 is added


;to W for each Hundreds digit. Hundreds digits are counted
;by decrementing the Hundreds digit until it reaches 0. Next,
;10 is added to W for each Tens digit. Finally, the Ones
;digit is added to W to get the result.

CLRW ;Clear W to store result


MOVF Hundreds,1 ;Move Hundreds register to itself
BTFSC Z ;to check for zero
GOTO :Tens ;If no hundreds digit check tens digit
:Add_Hundred ADDLW 100 ;Add 100 to W since there are hundreds
DECFSZ Hundreds,1 ;Decrement hundreds digit, check for 0
GOTO :Add_Hundred ;If more hundreds, add another 100

:Tens MOVF Tens,1 ;Move Tens register to itself


BTFSC Z ;to check for zero
GOTO :Ones ;If no tens digit check ones digit
:Add_Ten ADDLW 10 ;Add 10 to W since there are tens
DECFSZ Tens,1 ;Decrement tens digit, check for 0
GOTO :Add_Ten ;If more tens, add another 10

:Ones ADDWF Ones,0 ;Add contents of Ones register to W


RETURN ;All Done!

16 Microchip Code ©1998 Sirius microSystems


EEPROM.LIB - PIC16F84 EEPROM Subroutine Library
;EEPROM.LIB v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This subroutine provides calls for PIC16F84 EEPROM operation including:


; - EEPROM data write
; - EEPROM data read
; - Wait for EEPROM write to finish

;Variables

; None

;Requirements

; None

;Use

; To write data to the EEPROM:


; 1. Move an EEPROM address into EEADR
; 2. Move the data to be written into EEDATA
; 3. CALL EE_Write

; To wait for EEPROM write completion:


; 1. CALL EE_Wait (on RETURN, EEPROM write is complete)

; To read data from the EEPROM:


; 1. Move an EEPROM address into EEADR
; 2. CALL EE_Read (the data will be available in EEDATA)

;Notes

; Instead of waiting for the EEPROM write to finish, EEIF can generate
; an interrupt. When using interrupts, some precautions must be taken:

; 1. Disable GIE (all interrupts) before calling EE_Write.


; 2. On exit from EE_Write, re-enable interrupts

; Microchip strongly recommends that interrupts be disabled during


; the EEPROM write sequence.

EE_Read ;Sets the RD bit in EECON1 to read the contents of EEADR


;into EEDATA.

BSF RP0 ;Select memory register page 1


BSF RD ;Set the EECON1.RD bit to read
BCF RP0 ;Return to memory register page 0
RETURN

EE_Write ;Writes the contents of EEDATA to EEADR as specified in


;the PIC16F84 data sheets after enabling WREN. After
;writing the data, WREN is cleared, disabling accidental

Program Pull-Out
©1998 Sirius microSystems Microchip Code 17 References
EEPROM.LIB - PIC16F84 EEPROM Subroutine Library
;writes.

BSF RP0 ;Select memory register page 1


BSF WREN ;Enable EEPROM writes
MOVLW 55h
MOVWF EECON2 ;Write 55h to EECON2
MOVLW 0aah
MOVWF EECON2 ;Write AAh to EECON2
BSF WR ;Set EECON1.WR bit
BCF WREN ;Disable any further writes
BCF RP0 ;Return to memory register page 0
RETURN

EE_Wait ;Wait for an EE_Write to finish by checking the EEIF


;flag bit in EECON1.

BSF RP0 ;Select memory register page 1


:Wait BTFSS EEIF ;Check EEIF for a high (1=finished)
GOTO :Wait ;If low, wait for EEIF to go high
BCF EEIF ;Clear EEIF after write is done
BCF RP0 ;Return to memory register page 0
RETURN

18 Microchip Code ©1998 Sirius microSystems


KEYPAD.LIB - Keypad Subroutine Library
;KEYPAD.LIB v1.2 Last Modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This subroutine library provides calls for keyboard scanning, including:


; - Keypad port configuration
; - Key code retrieval

;Variables

; Key - key code return register (EQU to a file register)

;Requirements

; Ensure that your calling program defines KEY as a hardware register.


; After calling KB_Scan, the KEY register contains the number of the
; key pressed. If no key was pressed, KEY contains the number 0.

;Use

; 1. Call KB_Port to initialize Port B for the keyboard


; 2. Call KB_Scan to scan for a key press
; 3. Retrieve the Key code from the Key variable

;Notes: You should add a key debouncing routine to your calling program.
; Each time a key is pressed, the mechanical contacts ‘bounce’ for
; a short time, alternately making and breaking the key connection.
; Key bounce would be read by the microcontroller as a series of
; rapid key presses instead of one single key press. Keys and buttons
; can be debounced by reading the keys once, and then again after
; a short debouncing delay:
;
; 1. Call KB_Port to initialize Port B for keypad use
; 2. Call KB_Scan to scan for a key press
; 3. Save the Key code variable in a temporary register
; 4. Call a delay routine of 20 ms
; 5. Call KB_Scan again to scan for a key press
; 6. Compare the new Key code value to the Key code saved in the
; temporary register. If they’re the same the key press is valid,
; otherwise discard the key press.

KB_Port ;Initializes Port B for keyboard input by setting RB0-3 as


;output and RB4-7 as inputs with pull-up resistors enabled.

BSF RP0 ;Select memory page 1


MOVLW 0F0h ;Set high nibble to input and
MOVWF TRISB ; low nibble to output
BSF RBPU ;Enable pull-ups on inputs
BCF RP0 ;Select memory page 0
RETURN ;Done, return to calling program

KB_Scan ;Scans the keyboard by:


; 1. Setting the Key variable to a 1 for the first key code
; 2. Setting all row outputs except row 1 to a high (row 1

Program Pull-Out
©1998 Sirius microSystems Microchip Code 19 References
KEYPAD.LIB - Keypad Subroutine Library
; gets set to a low.
; 3. Checking each column input in turn for the low on row 1.
; If no key is pressed, the column will read high due to
; the pull-up resistors. If a key is pressed, the column
; will read low.
; 4. Repeatedly setting all row outputs except the next row
; high and repeating step 3 for each row.

;If a key press is detected, the routine exits with the key
;number in the Key variable. Key numbers are (in decimal):

; Col. 1 2 3 4
; Row +----+----+----+----+
; 1 | 1 | 2 | 3 | 4 |
; +----+----+----+----+
; 2 | 5 | 6 | 7 | 8 |
; +----+----+----+----+
; 3 | 9 | 10 | 11 | 12 |
; +----+----+----+----+
; 4 | 13 | 14 | 15 | 16 |
; +----+----+----+----+
;If no key press is detected, the routine exits with the
;number 0 in the Key variable. This makes it easy to check
;for no key presses by testing the Z flag.

;The KB_Scan routine checks for key presses in the sequence


;indicated by the key numbers, above. If two or more keys
;are pressed simultaneously, only the first key in the
;sequence will be returned.

CLRF Key ;Clear Key register and then


INCF Key ;set Key to first return code
MOVLW 0Eh ;Output 0 to first row only,
MOVWF PORTB ;Output to Port B
NOP ;and wait for signals to settle

:Col_Check BTFSS PORTB.4 ;Check first column for low


RETURN ;and exit on key press
INCF Key ;If no key press, increment key number
BTFSS PORTB.5 ;Check second column for low
RETURN ;and exit on key press
INCF Key ;If no key press, increment key number
BTFSS PORTB.6 ;Check third column for low
RETURN ;and exit on key press
INCF Key ;If no key press, increment key number
BTFSS PORTB.7 ;Check fourth column for low
RETURN ;and exit on key press
INCF Key ;If no key press, increment key number

:Row_Set MOVLW 11h ;Load W with number of keys + 1


SUBWF Key,0 ;and compare with current key value
BTFSC Z ;If keys + 1 = current key then
GOTO :No_Keys ;no key was pressed
BSF C ;Set carry bit to make first row high
RLF PORTB ;and rotate row outputs
GOTO :Col_Check

:No_Keys CLRF Key ;Set Key variable to 0 and


RETURN ;return to calling program

20 Microchip Code ©1998 Sirius microSystems


LCD.LIB - LCD Subroutine Library
;LCD.LIB v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This subroutine provides calls for LCD operation including:


; - Port Configuration
; - Register mode commands
; - LCD Busy check
; - LCD Enable toggle

;Variables

; None

;Requirements

; Two free levels of processor stack are required for nested calls.

; The LCD_Init subroutine requires a minimum 5ms delay to initialize


; the LCD. Delays longer than 5ms are acceptable. LCD_Init calls a
; subroutine by the name of Delay_5ms which must be included in your
; calling program. If your calling program contains a delay loop of
; longer than 5ms, you can use that delay by adding a Delay_5ms
; label before the routine.

;Use

; To initialize the LCD display after power-up:


; 1. Call LCD_Port to initialize Port A and Port B for the LCD display
; 2. Call LCD_Init to initialize the LCD controller

; To write a command or character to the LCD display:


; 1. Call LCD_Port to initialize Port A and Port B for the LCD display
; 2. Move an LCD command or ASCII character into W
; 3. Call LCD_Reg or LCD_Data to send the command or
; character to the LCD.

;LCD Hardware Equates

LCDRS EQU PORTA.0 ;LCD Register Select


LCDRW EQU PORTA.1 ;LCD Read/~Write
LCDE EQU PORTA.2 ;LCD Enable

;LCD Software Commands (Constants)

LCDLine1 EQU 80h ;Line 1 starting address


LCDLine2 EQU 0C0h ;Line 2 starting address
LCDCLR EQU 01h ;Clear Display, cursor home
LCDHome EQU 02h ;Cursor home, DDRAM unchanged
LCDInc EQU 06h ;Cursor increment mode
LCDDec EQU 04h ;Cursor decrement mode
LCDOn EQU 0Ch ;Display On
LCDOff EQU 08h ;Display Off

Program Pull-Out
©1998 Sirius microSystems Microchip Code 21 References
LCD.LIB - LCD Subroutine Library
CursOn EQU 0Eh ;Display On and Cursor On
CursOff EQU 0Ch ;Display On and Cursor Off
CursBlink EQU 0Fh ;Display On and Cursor Blinking
LCDLeft EQU 18h ;Shift Display Left
LCDRight EQU 1Ch ;Shift Display Right
CursLeft EQU 10h ;Move Cursor Left
CursRight EQU 14h ;Move Cursor Right
LCDFunction EQU 38h ;8-bit function register init. command
LCDInit EQU 38h ;LCD initialization command
LCDCGRAM EQU 40h ;CGRAM starting address

LCD_Port ;Initializes the Port B tristate buffers as outputs for


;LCD data lines. Sets Port A to digital (on PIC16C711) and
;sets the LCD Register Select, Read/~Write, and Enable
;lines to outputs.

BSF RP0 ;Select memory register page 1

;the next two lines are for the PIC16C711 only and should be
;removed for the PIC16F84 (PM produces an error when this
;is assembled for the ’84).

;MOVLW 03h ;1’s set Port A to digital


;MOVWF ADCON1 ;Write W to ADCON1 (88h)

MOVLW 11111000b ;Set lower 3 bits of RA to


ANDWF TRISA ;digital output in TRISA
CLRF TRISB ;Set Port B to output
BCF RP0 ;Go back to register page 0
BCF LCDE ;Keep LCD Enable line off
RETURN ;Ports are now set up for LCD

LCD_Init ;LCD initialization instructions from the Optrex data book.


;Sets LCD functions for DMC16207 display, performs soft-
;ware reset, clears memory and turns the display on.

MOVLW LCDInit ;Load W with initialize LCD code


CALL LCD_Reg_Init ;and send it to LCD
CALL Delay_5ms ;...and wait
MOVLW LCDInit ;Load W with initialize LCD code
CALL LCD_Reg_Init ;and send it to LCD again
CALL Delay_5ms ;...and wait
MOVLW LCDInit ;Load W with initialize LCD code
CALL LCD_Reg_Init ;and send it to LCD again
CALL Delay_5ms ;...and wait
MOVLW LCDFunction ;Load W with initialize 8-bit code
CALL LCD_Reg ;and send it to LCD
CALL Delay_5ms ;...and wait

;Change the constant in the next line to set how the display
;is activated. eg. LCDOn, CursOn, CursBlink. The Constant is
;from the LCD software commands, above.

MOVLW LCDOn ;Command for display on & cursor off

CALL LCD_Reg ;Send it to LCD


MOVLW LCDCLR ;Load W with clear LCD code
CALL LCD_Reg ;and send it to LCD
MOVLW LCDInc ;Load W with increment mode code
CALL LCD_Reg ;and send it to LCD
RETURN

LCD_Reg_Init ;Used only for initialization prior to setting function


;register. In this time, the LCD busy flag cannot be checked.

22 Microchip Code ©1998 Sirius microSystems


LCD.LIB - LCD Subroutine Library
BCF LCDRS ;Enter register mode
MOVWF PORTB ;and send W to LCD reg. on Port B
GOTO LCD_Enable ;Send register command

LCD_Reg ;Load W with LCD software constant from table, above.


;LCD_Reg outputs the command to the LCD and blips the
;enable line with LCD_Enable to complete the command.

BCF LCDRS ;Enter register mode


MOVWF PORTB ;and send W to LCD reg. on Port B
CALL LCD_Check ;Check LCD busy flag
GOTO LCD_Enable ;Send register command

LCD_Data ;Load W with the ASCII character code to send to LCD.


;LCD_Data outputs the character to the LCD and blips
;the enable line with LCD_Enable to complete the send.

BCF LCDRS ;Enter register mode


MOVWF PORTB ;and send W to LCD on Port B
CALL LCD_Check ;Check LCD busy flag
BSF LCDRS ;Enter ASCII mode
GOTO LCD_Enable ;Send ASCII character

LCD_Check ;Checks the state of the LCD Busy flag and waits for any
;previous command to finish before returning to the
;calling routine.

BSF LCDRW ;Set LCD read mode


BSF RP0 ;Select memory page 1
MOVLW 0FFh ;Set Port B to input and
MOVWF TRISB ;disable tristate buffers
BCF RP0 ;Back to memory page 0
BSF LCDE ;Enable LCD
NOP ;and wait for an extra cycle
:Loop BTFSC PORTB.7 ;Check LCD busy bit and
GOTO :Loop ;wait if high. (Busy=1)
BCF LCDE ;Disable LCD
BSF RP0 ;Select memory page 1
CLRF TRISB ;Set Port B to output
BCF RP0 ;Back to memory page 0
BCF LCDRW ;Back to LCD write mode
RETURN ;LCD is now free

LCD_Enable ;Sends a 500 ns enable pulse to the LCD to complete the


;register or character write operation. The NOP instruction
;is only required for processors faster than 8 MHz. For
;processors faster than 16 MHz, add a second NOP.

BSF LCDE ;Set enable line


NOP ;and pause for an extra 250ns
BCF LCDE ;Reset the enable line
RETURN ;Done!

Program Pull-Out
©1998 Sirius microSystems Microchip Code 23 References
LCD4BIT.LIB - 4-bit Interface LCD Subroutine Library
;LCD4BIT.LIB v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This subroutine provides calls for LCD operation in 4-bit mode


; including:
; - Port Configuration
; - Register mode commands
; - LCD Busy check
; - LCD Enable toggle

;Variables

; LCDTemp - Temporary command byte storage register

;Requirements

; Two free levels of processor stack are required for nested calls.

; The LCD_Init subroutine requires a minimum 5ms delay to initialize


; the LCD. Delays longer than 5ms are acceptable. LCD_Init calls a
; subroutine by the name of Delay_5ms which must be included in your
; calling program. If your calling program contains a delay loop of
; longer than 5ms, you can use that delay by adding a Delay_5ms
; label before the routine.

;Use

; To initialize the LCD display after power-up:


; 1. Call LCD_Port to initialize Port A and Port B for the LCD display
; 2. Call LCD_Init to initialize the LCD controller

; To write a command or character to the LCD display:


; 1. Call LCD_Port to initialize Port A and Port B for the LCD display
; 2. Move an LCD command or ASCII character into W
; 3. Call LCD_Reg or LCD_Data to send the command or
; character to the LCD.

;LCD Hardware Equates

LCDRS EQU PORTA.0 ;LCD Register Select


LCDRW EQU PORTA.1 ;LCD Read/~Write
LCDE EQU PORTA.2 ;LCD Enable

;LCD Software Commands (Constants)

LCDLine1 EQU 80h ;Line 1 starting address


LCDLine2 EQU 0C0h ;Line 2 starting address
LCDCLR EQU 01h ;Clear Display, cursor home
LCDHome EQU 02h ;Cursor home, DDRAM unchanged
LCDInc EQU 06h ;Cursor increment mode
LCDDec EQU 04h ;Cursor decrement mode
LCDOn EQU 0Ch ;Display On

24 Microchip Code ©1998 Sirius microSystems


LCD4BIT.LIB - 4-bit Interface LCD Subroutine Library
LCDOff EQU 08h ;Display Off
CursOn EQU 0Eh ;Display On and Cursor On
CursOff EQU 0Ch ;Display On and Cursor Off
CursBlink EQU 0Fh ;Display On and Cursor Blinking
LCDLeft EQU 18h ;Shift Display Left
LCDRight EQU 1Ch ;Shift Display Right
CursLeft EQU 10h ;Move Cursor Left
CursRight EQU 14h ;Move Cursor Right
LCDFunction EQU 28h ;4-bit function register init. command
LCDInit EQU 38h ;LCD Initialization
LCDCGRAM EQU 40h ;CGRAM starting address

LCD_Port ;Initializes the top 4 Port B tristate buffers as outputs for


;LCD data lines. Sets Port A to digital (on PIC16C711) and
;sets the LCD Register Select, Read/~Write, and Enable
;lines to outputs.

BSF RP0 ;Select memory register page 1

;the next two lines are for the PIC16C711 only and should be
;removed for the PIC16F84 (PM produces an error when this
;is assembled for the ’84).

;MOVLW 03h ;1’s set Port A to digital


;MOVWF ADCON1 ;Write W to ADCON1 (88h)

MOVLW 11111000b ;Set lower 3 bits of RA to


ANDWF TRISA ;digital output in TRISA
MOVLW 00001111b ;Set upper 4 bits of TRISB to
ANDWF TRISB ;digital output
BCF RP0 ;Go back to register page 0
BCF LCDE ;Keep LCD Enable line off
RETURN ;Ports are now set up for LCD

LCD_Init ;LCD initialization instructions from the Optrex data book.


;Sets LCD functions for DMC16207 display, performs soft-
;ware reset, sets 4-bit mode, clears memory and turns the
;display on.

MOVLW LCDInit ;Load W with initialize LCD code


CALL LCD_Reg_Init ;and send it to LCD
CALL Delay_5ms ;...and wait
MOVLW LCDInit ;Load W with initialize LCD code
CALL LCD_Reg_Init ;and send it to LCD again
CALL Delay_5ms ;...and wait
MOVLW LCDInit ;Load W with initialize LCD code
CALL LCD_Reg_Init ;and send it to LCD again
CALL Delay_5ms ;...and wait
MOVLW LCDFunction ;Load W with initialize 4-bit mode
CALL LCD_Reg_Init ;and send it to LCD
CALL Delay_5ms ;...and wait
MOVLW LCDFunction ;Load W with initialize 4-bit mode
CALL LCD_Reg ;and send it to LCD
CALL Delay_5ms ;...and wait

;Change the constant in the next line to set how the display
;is activated. eg. LCDOn, CursOn, CursBlink. The Constant is
;from the LCD software commands, above.

MOVLW LCDOn ;Command for display on & cursor off


CALL LCD_Reg ;Send it to LCD
MOVLW LCDCLR ;Load W with clear LCD code
CALL LCD_Reg ;and send it to LCD
MOVLW LCDInc ;Load W with increment mode code
CALL LCD_Reg ;and send it to LCD
RETURN

Program Pull-Out
©1998 Sirius microSystems Microchip Code 25 References
LCD4BIT.LIB - 4-bit Interface LCD Subroutine Library

LCD_Reg_Init ;Used only for initialization prior to setting 4-bit mode.


;W is loaded with the 8-bit initialization string (38h) of
;which only the top 4 bits (3h) are sent to the LCD.

MOVWF LCDTemp ;Store command in temporary register


MOVLW 0Fh ;Load W with value to clear
ANDWF PORTB ;upper 4 bits of Port B
BCF LCDRS ;Enter register mode
MOVF LCDTemp,0 ;Load W with command byte
ANDLW 11110000b ;Keep upper 4 bits of W and
IORWF PORTB ;OR with PORT B
GOTO LCD_Enable ;and send first nybble of command

LCD_Reg ;Load W with LCD software constant from table, above.


;LCD_Reg outputs the command to the LCD as two separate
;nybbles (first the upper 4 bits, then the lower 4 bits) and
;blips the enable line with LCD_Enable to finish the command.

MOVWF LCDTemp ;Store command byte in temp register


MOVLW 0Fh ;Load W with value to clear
ANDWF PORTB ;upper 4 bits of Port B
BCF LCDRS ;Enter register mode
MOVF LCDTemp,0 ;Load W with command byte
ANDLW 11110000b ;Keep upper 4 bits of W and
IORWF PORTB ;OR with PORT B
CALL LCD_Check ;Check LCD busy flag
CALL LCD_Enable ;and send first part of command
MOVLW 0Fh ;Load W with value to clear
ANDWF PORTB ;upper 4 bits of Port B
SWAPF LCDTemp,0 ;Load W with lower nybble of command
ANDLW 11110000b ;Keep upper 4 bits of W and
IORWF PORTB ;OR with PORT B
GOTO LCD_Enable ;Send second part of command & return

LCD_Data ;Load W with the ASCII character code to send to LCD.


;LCD_Data outputs the character to the LCD and blips
;the enable line with LCD_Enable to complete the send.

MOVWF LCDTemp ;Store data byte in temporary register


MOVLW 0Fh ;Load W with value to clear
ANDWF PORTB ;upper 4 bits of Port B
BCF LCDRS ;Enter register mode
MOVF LCDTemp,0 ;Load W with command byte
ANDLW 11110000b ;Keep upper 4 bits of W and
IORWF PORTB ;OR with PORT B
CALL LCD_Check ;Check LCD busy flag
BSF LCDRS ;Set RS to ASCII mode
CALL LCD_Enable ;and send upper nybble of character
MOVLW 0Fh ;Load W with value to clear
ANDWF PORTB ;upper 4 bits of Port B
BCF LCDRS ;Set RS to register mode
SWAPF LCDTemp,0 ;Load W with lower nybble of command
ANDLW 11110000b ;Keep upper 4 bits of W and
IORWF PORTB ;OR with PORT B
BSF LCDRS ;Set RS to ASCII mode
GOTO LCD_Enable ;Send second part of command & return

LCD_Check ;Checks the state of the LCD Busy flag and waits for any
;previous command to finish before returning to the
;calling routine.

BSF LCDRW ;Set LCD read mode


BSF RP0 ;Select memory page 1

26 Microchip Code ©1998 Sirius microSystems


LCD4BIT.LIB - 4-bit Interface LCD Subroutine Library
MOVLW 0F0h ;Set upper 4 bits of Port B to input
IORWF TRISB ;in tristate buffers by ORing
BCF RP0 ;Back to memory page 0
BSF LCDE ;Enable LCD
NOP ;and wait for an extra cycle
:Loop BTFSC PORTB.7 ;Check LCD busy bit and
GOTO :Loop ;wait if high. (Busy=1)
BCF LCDE ;Disable LCD
BSF RP0 ;Select memory page 1
MOVLW 0Fh ;Set upper 4 bits of Port B back to
ANDWF TRISB ;output by ANDing
BCF RP0 ;Back to memory page 0
BCF LCDRW ;Back to LCD write mode
RETURN ;LCD is now free

LCD_Enable ;Sends a 500 ns enable pulse to the LCD to complete the


;register or character write operation. The NOP instruction
;is only required for processors faster than 8 MHz. For
;processors faster than 16 MHz, add a second NOP.

BSF LCDE ;Set enable line


NOP ;and pause for an extra 250ns
BCF LCDE ;Reset the enable line
RETURN ;Done!

Program Pull-Out
©1998 Sirius microSystems Microchip Code 27 References
LCD71.LIB - PIC16C71/711 LCD Subroutine Library
;LCD71.LIB v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This subroutine provides calls for PIC16C711 LCD operation including:


; - Port Configuration
; - Register mode commands
; - LCD Busy check
; - LCD Enable toggle

;Variables

; None

;Requirements

; Two free levels of processor stack are required for nested calls.

; The LCD_Init subroutine requires a minimum 5ms delay to initialize


; the LCD. Delays longer than 5ms are acceptable. LCD_Init calls a
; subroutine by the name of Delay_5ms which must be included in your
; calling program. If your calling program contains a delay loop of
; longer than 5ms, you can use that delay by adding a Delay_5ms
; label before the routine.

;Use

; To initialize the LCD display after power-up:


; 1. Call LCD_Port to initialize Port A and Port B for the LCD display
; 2. Call LCD_Init to initialize the LCD controller

; To write a command or character to the LCD display:


; 1. Call LCD_Port to initialize Port A and Port B for the LCD display
; 2. Move an LCD command or ASCII character into W
; 3. Call LCD_Reg or LCD_Data to send the command or
; character to the LCD.

;LCD Hardware Equates

LCDRS EQU PORTA.0 ;LCD Register Select


LCDRW EQU PORTA.1 ;LCD Read/~Write
LCDE EQU PORTA.2 ;LCD Enable

;LCD Software Commands (Constants)

LCDLine1 EQU 80h ;Line 1 starting address


LCDLine2 EQU 0C0h ;Line 2 starting address
LCDCLR EQU 01h ;Clear Display, cursor home
LCDHome EQU 02h ;Cursor home, DDRAM unchanged
LCDInc EQU 06h ;Cursor increment mode
LCDDec EQU 04h ;Cursor decrement mode
LCDOn EQU 0Ch ;Display On
LCDOff EQU 08h ;Display Off

28 Microchip Code ©1998 Sirius microSystems


LCD71.LIB - PIC16C71/711 LCD Subroutine Library
CursOn EQU 0Eh ;Display On and Cursor On
CursOff EQU 0Ch ;Display On and Cursor Off
CursBlink EQU 0Fh ;Display On and Cursor Blinking
LCDLeft EQU 18h ;Shift Display Left
LCDRight EQU 1Ch ;Shift Display Right
CursLeft EQU 10h ;Move Cursor Left
CursRight EQU 14h ;Move Cursor Right
LCDFunction EQU 38h ;8-bit function register init. command
LCDInit EQU 38h ;LCD initialization command
LCDCGRAM EQU 40h ;CGRAM starting address

LCD_Port ;Initializes the Port B tristate buffers as outputs for


;LCD data lines. Sets Port A to digital (on PIC16C711) and
;sets the LCD Register Select, Read/~Write, and Enable
;lines to outputs.

BSF RP0 ;Select memory register page 1

;the next two lines are for the PIC16C711 only and should be
;removed for the PIC16F84 (PM produces an error when this
;is assembled for the ’84).

MOVLW 03h ;1’s set Port A to digital


MOVWF ADCON1 ;Write W to ADCON1 (88h)

MOVLW 11111000b ;Set lower 3 bits of RA to


ANDWF TRISA ;digital output in TRISA
CLRF TRISB ;Set Port B to output
BCF RP0 ;Go back to register page 0
BCF LCDE ;Keep LCD Enable line off
RETURN ;Ports are now set up for LCD

LCD_Init ;LCD initialization instructions from the Optrex data book.


;Sets LCD functions for DMC16207 display, performs soft-
;ware reset, clears memory and turns the display on.

MOVLW LCDInit ;Load W with initialize LCD code


CALL LCD_Reg_Init ;and send it to LCD
CALL Delay_5ms ;...and wait
MOVLW LCDInit ;Load W with initialize LCD code
CALL LCD_Reg_Init ;and send it to LCD again
CALL Delay_5ms ;...and wait
MOVLW LCDInit ;Load W with initialize LCD code
CALL LCD_Reg_Init ;and send it to LCD again
CALL Delay_5ms ;...and wait
MOVLW LCDFunction ;Load W with initialize 8-bit code
CALL LCD_Reg ;and send it to LCD
CALL Delay_5ms ;...and wait

;Change the constant in the next line to set how the display
;is activated. eg. LCDOn, CursOn, CursBlink. The Constant is
;from the LCD software commands, above.

MOVLW LCDOn ;Command for display on & cursor off

CALL LCD_Reg ;Send it to LCD


MOVLW LCDCLR ;Load W with clear LCD code
CALL LCD_Reg ;and send it to LCD
MOVLW LCDInc ;Load W with increment mode code
CALL LCD_Reg ;and send it to LCD
RETURN

LCD_Reg_Init ;Used only for initialization prior to setting function


;register. In this time, the LCD busy flag cannot be checked.

Program Pull-Out
©1998 Sirius microSystems Microchip Code 29 References
LCD71.LIB - PIC16C71/711 LCD Subroutine Library
BCF LCDRS ;Enter register mode
MOVWF PORTB ;and send W to LCD reg. on Port B
GOTO LCD_Enable ;Send register command

LCD_Reg ;Load W with LCD software constant from table, above.


;LCD_Reg outputs the command to the LCD and blips the
;enable line with LCD_Enable to complete the command.

BCF LCDRS ;Enter register mode


MOVWF PORTB ;and send W to LCD reg. on Port B
CALL LCD_Check ;Check LCD busy flag
GOTO LCD_Enable ;Send register command

LCD_Data ;Load W with the ASCII character code to send to LCD.


;LCD_Data outputs the character to the LCD and blips
;the enable line with LCD_Enable to complete the send.

BCF LCDRS ;Enter register mode


MOVWF PORTB ;and send W to LCD on Port B
CALL LCD_Check ;Check LCD busy flag
BSF LCDRS ;Enter ASCII mode
GOTO LCD_Enable ;Send ASCII character

LCD_Check ;Checks the state of the LCD Busy flag and waits for any
;previous command to finish before returning to the
;calling routine.

BSF LCDRW ;Set LCD read mode


BSF RP0 ;Select memory page 1
MOVLW 0FFh ;Set Port B to input and
MOVWF TRISB ;disable tristate buffers
BCF RP0 ;Back to memory page 0
BSF LCDE ;Enable LCD
NOP ;and wait for an extra cycle
:Loop BTFSC PORTB.7 ;Check LCD busy bit and
GOTO :Loop ;wait if high. (Busy=1)
BCF LCDE ;Disable LCD
BSF RP0 ;Select memory page 1
CLRF TRISB ;Set Port B to output
BCF RP0 ;Back to memory page 0
BCF LCDRW ;Back to LCD write mode
RETURN ;LCD is now free

LCD_Enable ;Sends a 500 ns enable pulse to the LCD to complete the


;register or character write operation. The NOP instruction
;is only required for processors faster than 8 MHz. For
;processors faster than 16 MHz, add a second NOP.

BSF LCDE ;Set enable line


NOP ;and pause for an extra 250ns
BCF LCDE ;Reset the enable line
RETURN ;Done!

30 Microchip Code ©1998 Sirius microSystems


RS232RX.LIB - RS-232 Receive Subroutine Library
;RS232RX.LIB v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This subroutine provides calls for the PIC-MDS to receive RS-232


; characters through the serial header (H3), including:
; - variable Baud rates and data bits
; - receive bit setup
; - wait for a serial start bit
; - receive a serial character

;Variables

; Each of the variables below must be equated to a file register by


; the calling program:
;
; Counter - Used by bit time delay loop
; BitCounter - Counts number of received bits
; Receive - Stores the received serial byte

;Requirements

; Two free levels of processor stack for nested subroutine calls


;
; An external RS-232 serial terminal or a computer with an appropriate
; connection to the PIC-MDS serial input header (H3). For testing we
; used a cable wired as follows and communicated with the MS Windows
; Terminal program in Windows for Work Groups 3.11:
;
; Computer DB-25 PIC-MDS
; Transmit pin 2 —> H3.3 - Rx
; Receive pin 3 —> H3.1 - Tx
; Ground pin 7 —> H3.2 - Gnd

;Use

; To receive serial characters:


; 1. Call Receive_Port to initialize PortA.4 as an input
; 2. Call Receive_Wait to wait for and receive one serial byte
; 3. (Optional) Check the Receive register for 00h indicating a
; serial framing error has occurred.

; Since PortA.4 is the serial input and the input for TMR0, this
; serial library can be interrupt enabled. To receive via TMR0
; interrupts, do the following:
; 1. Enable TMR0 interrupt (see Chapter 11), with external input,
; no prescaler, and falling-edge trigger
; 2. Pre-load TMR0 with FFh. The next falling edge on PortA.4
; increments TMR0 to 00h generating an interrupt.
; 3. Enable GIE (Global Interrupt Enable)
; 4. When a TMR0 interrupt is generated, have your ISR Call
; Receive_Data to receive the character. Depending on the Baud

Program Pull-Out
©1998 Sirius microSystems Microchip Code 31 References
RS232RX.LIB - RS-232 Receive Subroutine Library
; rate and the number of cycles of your ISR, you may have to
; adjust the value of Half_Bit. Reduce Half_Bit by one for every
; four cycles of code taken by your ISR.

;RS232RX.LIB Hardware Equates for PIC-MDS

Serial_Input EQU PORTA.4 ;Serial input pin on PIC-MDS

;Software Equates

; DataBits and Bit_Time may be commented out to allow the calling


; program to select equates governing the number of data bits as
; well as the received baud rate. Or, change DataBits and Bit_Time
; below to your defaults.

DataBits EQU 08h ;8 data bits

;Set Bit_Time, below, with a value from the table corresponding to your
;PIC’s clock speed and the serial Baud rate required. To ensure accurate
;serial bit timing, use a crystal oscillator and not a ceramic resonator
;or RC combination to generate the processor clock.

;+-------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
;|Clk\ Bd| 300 | 600 | 1200| 2400| 4800| 9600|14400|19200|28800|38400|57600|
;+-------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
;| 1 MHz | 0CEh| 65h | 31h | 17h | 0Ah | 04h*| --- | --- | --- | --- | --- |
;| 2 MHz | --- | 0CEh| 65h | 31h | 17h | 0Ah | 06h | 04h*| --- | --- | --- |
;| 4 MHz | --- | --- | 0CEh| 65h | 31h | 17h | 0Fh | 0Ah | 06h | 04h*| --- |
;| 8 MHz | --- | --- | --- | 0CEh| 65h | 31h | 20h | 17h | 0Fh | 0Ah | 06h |
;| 10 MHz| --- | --- | --- | FFh*| 7Fh | 3Eh | 29h | 1Eh | 13h | 0Eh | 08h |
;| 16 MHz| --- | --- | --- | --- | 0CEh| 65h | 43h | 31h | 20h | 17h | 0Fh |
;| 20 MHz| --- | --- | --- | --- | FFh*| 7Fh | 54h | 3Eh | 29h | 1Eh | 13h |
;+-------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
;*Timing inaccuracies using these delay constants may cause serial errors.

Bit_Time EQU 3Eh ;Serial Bit delay from table above


Half_Bit EQU Bit_Time/2 ;Half of the Bit delay

Receive_Port ;Sets PORTA.4 to input. Make sure PIC-MDS JU5 is set to Rx!

BSF RP0 ;Select memory register page 1


MOVLW 00010000b ;Load W with bit to make RA.4 input
IORWF TRISA ;and OR with Port A tristate reg.
BCF RP0 ;Return to memory register page 0
RETURN

Receive_Wait ;Waits for an RS-232 start bit indicated by RA.4 going low.

BTFSC Serial_Input ;Check serial input pin


GOTO Receive_Wait ;If high, wait for low

Receive_Data ;Delay for half the Bit_Time and confirm the presence of the
;start bit. Then wait for Bit_Time and read each bit into
;Carry. Rotate Carry into the Receive byte and repeat the
;delay, Carry and rotate until number of DataBits have been
;received. The Receive register stores the received byte. If
;framing error occurs (only a simple check for a stop bit is
;done) the contents of the Receive register will be 00h.

MOVLW DataBits ;Load W with number of data bits


MOVWF BitCounter ;and save in BitCounter register
MOVLW Half_Bit ;Load W with half of bit delay time
CALL BitDelay ;and wait for 1/2 bit
BTFSC Serial_Input ;Check for low start bit again

32 Microchip Code ©1998 Sirius microSystems


RS232RX.LIB - RS-232 Receive Subroutine Library
GOTO Receive_Data ;If high, error occurred-keep waiting

:Next_Bit MOVLW Bit_Time ;Load W with bit delay time


CALL BitDelay ;and wait until middle of next bit
BTFSS Serial_Input ;Check serial input pin for 1
BCF C ;If serial input is 0, clear Carry
BTFSC Serial_Input ;Check serial input pin for 0
BSF C ;If serial input is 1, set Carry
RRF Receive ;Rotate Carry into received data byte
DECFSZ BitCounter ;Decrement bit counter & check for 0
GOTO :Next_Bit ;If not 0, get the next bit

MOVLW Bit_Time ;Load W with bit delay time


CALL BitDelay ;and wait until middle of stop bit
BTFSS Serial_Input ;Check for high stop bit
GOTO Receive_Error ;If low, we have a framing error
RETURN ;Otherwise, return

Receive_Error ;Simply clears Receive buffer if no stop bit is found.

CLRF Receive ;If a framing error occurs, clear


RETURN ;Receive register before returning

BitDelay ;RS-232 Bit time period delay

MOVWF Counter ;Move delay time in W to Counter


:Loop NOP ;Pad loop to 4 cycles
DECFSZ Counter,1 ;Decrement bit counter
GOTO :Loop ;and do it until zero
RETURN

Program Pull-Out
©1998 Sirius microSystems Microchip Code 33 References
RS232TX.LIB - RS-232 Transmit Subroutine Library
;RS232TX.LIB v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by
phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out
of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This subroutine provides calls for the PIC-MDS to transmit RS-232


; characters through the serial header (H3), including:
; - variable Baud rates and data bits
; - selectable transmit pin
; - transmit a serial character

;Variables

; Each of the variables below must be equated to a file register by


; the calling program:
;
; Counter - Used by bit time delay loop
; BitCounter - Counts number of transmitted bits
; Transmit - Stores the serial byte to be transmitted

;Requirements

; Two free levels of processor stack for nested subroutine calls


;
; An external RS-232 serial terminal or a computer with an appropriate
; connection to the PIC-MDS serial input header (H3). For testing we
; used a cable wired as follows and communicated with the MS Windows
; Terminal program in Windows for Work Groups 3.11:
;
; Computer DB-25 PIC-MDS
; Transmit pin 2 —> H3.3 - Rx
; Receive pin 3 —> H3.1 - Tx
; Ground pin 7 —> H3.2 - Gnd

;Use

; To transmit serial characters:


; 1. Call Transmit_Port to initialize PortA.4 as an output
; 2. Move the data byte to be sent to the Transmit register
; 3. Call Transmit_Data to send the serial byte

;RS232RX.LIB Hardware Equates for PIC-MDS

Serial_Output EQU PORTA.4 ;Serial input pin on PIC-MDS

;Software Equates

; DataBits and Bit_Time may be commented out to allow the calling


; program to select equates governing the number of data bits as
; well as the transmit baud rate. Or, change DataBits and Bit_Time

34 Microchip Code ©1998 Sirius microSystems


RS232TX.LIB - RS-232 Transmit Subroutine Library
; below to your defaults.

DataBits EQU 08h ;8 data bits

;Set Bit_Time, below, with a value from the table corresponding to your
;PIC’s clock speed and the serial Baud rate required. To ensure accurate
;serial bit timing, use a crystal oscillator and not a ceramic resonator
;or RC combination to generate the processor clock.

;+-------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
;|Clk\ Bd| 300 | 600 | 1200| 2400| 4800| 9600|14400|19200|28800|38400|57600|
;+-------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
;| 1 MHz | 0CEh| 65h | 31h | 17h | 0Ah | 04h*| --- | --- | --- | --- | --- |
;| 2 MHz | --- | 0CEh| 65h | 31h | 17h | 0Ah | 06h | 04h*| --- | --- | --- |
;| 4 MHz | --- | --- | 0CEh| 65h | 31h | 17h | 0Fh | 0Ah | 06h | 04h*| --- |
;| 8 MHz | --- | --- | --- | 0CEh| 65h | 31h | 20h | 17h | 0Fh | 0Ah | 06h |
;| 10 MHz| --- | --- | --- | FFh*| 7Fh | 3Eh | 29h | 1Eh | 13h | 0Eh | 08h |
;| 16 MHz| --- | --- | --- | --- | 0CEh| 65h | 43h | 31h | 20h | 17h | 0Fh |
;| 20 MHz| --- | --- | --- | --- | FFh*| 7Fh | 54h | 3Eh | 29h | 1Eh | 13h |
;+-------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
;*Timing inaccuracies using these delay constants may cause serial errors.

Bit_Time EQU 03Eh ;Serial Bit delay from table above


Half_Bit EQU Bit_Time/2 ;Half of the Bit delay

Transmit_Port ;Sets PORTA.4 to output. Make sure PIC-MDS JU5 is set to Tx!

BSF RP0 ;Select memory register page 1


MOVLW 00001111b ;Load W with bit to make RA.4 output
ANDWF TRISA ;and OR with Port A tristate reg.
BCF RP0 ;Return to memory register page 0
BSF Serial_Output ;Set serial line high
RETURN

Transmit_Data ;Drop PortA.4 from high to low to indicate the Start Bit and
;delay for one Bit_Time. Rotate the Transmit buffer right
;into Carry and set or clear the serial output pin based on
;Carry. Wait for another bit time and continue rotating and
;transmitting until all eight bits have been sent. Finally,
;send a stop bit.

MOVWF Transmit ;Save character in W to buffer


MOVLW DataBits ;Load W with number of data bits
MOVWF BitCounter ;and save in BitCounter register
BCF Serial_Output ;Send Start bit
NOP ;and pad routine to be same length
NOP ;as :Next_Bit code so Bit_Time is
NOP ;accurate
NOP
NOP
NOP
NOP

:Next_Bit MOVLW Bit_Time ;Load W with bit delay time


CALL BitDelay ;and wait one bit duration
RRF Transmit ;Rotate Transmit byte into C
BTFSS C ;Check Carry for a 1
BCF Serial_Output ;If C=0, clear serial output
BTFSC C ;Check Carry for a 0
BSF Serial_Output ;If C=1, set serial output
DECFSZ BitCounter ;Decrement bit counter & check for 0
GOTO :Next_Bit ;If not 0, get the next bit

MOVLW Bit_Time ;Load W with bit delay time


CALL BitDelay ;and wait until end of last bit
BSF Serial_Output ;Set serial line high for Stop bit

Program Pull-Out
©1998 Sirius microSystems Microchip Code 35 References
RS232TX.LIB - RS-232 Transmit Subroutine Library
MOVLW Bit_Time ;Load W with bit delay time
CALL BitDelay ;and wait a bit
RETURN

BitDelay ;RS-232 Bit time period delay

MOVWF Counter ;Move delay time in W to Counter


:Loop NOP ;Pad loop to 4 cycles
DECFSZ Counter,1 ;Decrement bit counter
GOTO :Loop ;and do it until zero
RETURN

36 Microchip Code ©1998 Sirius microSystems


SEEPROM.LIB - Serial EEPROM Subroutine Library
;SEEPROM.LIB v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This subroutine provides calls to access the 93LC56 or 93LC66 Serial


; EEPROM (SEEPROM) for long-term data or variable storage. Serial EEPROMs
; are non-volatile and maintain their data even while power is off. The
; SEEPROM connects to the PIC microcontroller using three wires: Chip
; Select (SEECS), Clock (SEECLK) and Data In/Data Out (SEEDIDO).

; To write a byte to the SEEPROM, the PIC must serially transmit a start
; bit, a command op-code, a storage address, and data on SEEDIDO while
; toggling SEECLK. To read data back from the SEEPROM, the PIC clocks out
; the start bit, the command op-code, the storage address, and then keeps
; toggling SEECLK while reading the data on SEEDIDO.

; A full frame of serial data is shown below. Full frames are used by the
; Read, Write and Write All commands. The other four commands, Erase,
; Erase All, Erase-Write Enable, and Erase-Write Disable use a partial
; data frame and omit the data bits.

; +--+---+---+----+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
; |SB|OP1|OP0|X/A8|A7|A6|A5|A4|A3|A2|A1|A0|D7|D6|D5|D4|D3|D2|D1|D0|
; +--+---+---+----+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
; |<- partial frame for non-data instr. ->|
; |<- full frame for data instruction ->|

; SB=Start bit, OPn=Op-code bit, An=Address bit, Dn=Data bit, X=don’t care

; The presence of the A8 bit allows addressing of up to 512 bytes. Because


; the size of the data frame is constant, addressing a 256 byte SEEPROM
; requires a don’t care bit (X) to be transmitted in place of A8.

; +-------+---------------+----+-------------------+
; |SEEPROM| Size X Org. | A8 | A7-A0 |
; +-------+---------------+----+-------------------+
; |93LC56 | 256 X 8-bit | X | Valid Address |
; +-------+---------------+----+-------------------+
; |93LC66 | 512 X 8-bit | Valid Address |
; +-------+---------------+----+-------------------+

; These subroutines support the 93LC56 (256 byte) and 93LC66 (512 byte)
; SEEPROMs, in 8-bit data mode (X8 organization) only, and include
; subroutines for:
; - Port configuration
; - SEEPROM erase or write enable and disable
; - SEEPROM data write to a specific SEEPROM address
; - SEEPROM data read from a specific SEEPROM address
; - SEEPROM global write and erase
; - Wait for SEEPROM Erase/Write completion

; 16-bit data mode (X16 organization) is not supported. For 16-bit


; mode, modify the SEE_Clk subroutine according to the Microchip Data
; book for the 93LC46/56/66 series of serial SEEPROMs.

Program Pull-Out
©1998 Sirius microSystems Microchip Code 37 References
SEEPROM.LIB - Serial EEPROM Subroutine Library

;Variables

; The following variables must be defined by the calling program:

; SEEClock - SEEPROM serial clock counter register


; SEEData - Data byte storage register
; SEEAddrh - SEEPROM high address register
; SEEAddrl - SEEPROM low address register

;Requirements

; These routines require two levels of processor stack as well as the


; variables defined above.

;Use

; To set up Port A for Serial EEPROM use:


; 1. Call SEE_Port

; To read data from or to write data or a command to the Serial EEPROM:


; 1. Load low address byte into SEEAddrl or clear SEEAddrl
; 2. Load high address byte into SEEAddrh or clear SEEAddrh
; 3. For a data write operation, load data byte into SEEData
; 4. Move the SEEPROM Command Op-code into W using a MOVLW instruction
; 5. CALL SEE_Command
; 6. For a data read operation, retrieve the data byte from SEEData

; To wait for the completion of a write operation:


; 1. CALL SEE_Wait. A RETURN is issued when the SEEPROM operations are
; complete. Typical ERASE and WRITE operations take 4 ms to complete,
; ERAL takes 8 ms, and WRAL takes 16 ms.

;SEEPROM Commands

; Below is a list of the SEEPROM Command Op-codes indicating which ones


; require a valid address and the direction of data transfer:

; Op XOP Address Bits


; Code Code Instruction Description X/A8 A7 A6-A0 Data Bits
; ---------------------------------------------------------------------
; 00 00 EWDS -Erase/Write Disable XOP XOP X -
; 00 01 WRAL -Write All XOP XOP X to SEEPROM
; 00 10 ERAL -Erase All XOP XOP X -
; 00 11 EWEN -Erase/Write Enable XOP XOP X -
; 01 WRITE -byte to address X/A8 A7 A6-A0 to SEEPROM
; 10 READ -byte from address X/A8 A7 A6-A0 from SEEPROM
; 11 ERASE -contents of address X/A8 A7 A6-A0 -

; Note that for all 00 Op-Codes, a two bit extended op-code (XOP) takes
; the place of the A8 and A7 bits. The remaining address bits are don’t
; care bits, but must be transmitted to complete the instruction.

;SEEPROM Hardware Equates

SEECLK EQU PORTA.0 ;SEEPROM Serial Clock pin


SEEDIDO EQU PORTA.1 ;SEEPROM Data In and Data Out pins
SEECS EQU PORTA.3 ;SEEPROM Chip Select pin

;SEEPROM Software Commands (Constants)

SEERead EQU 0C0h ;Read data op-code


SEEEWEN EQU 9Ch ;Erase/Write Enable op-code
SEEErase EQU 0E0h ;Erase data op-code
SEEERAL EQU 94h ;Erase All op-code

38 Microchip Code ©1998 Sirius microSystems


SEEPROM.LIB - Serial EEPROM Subroutine Library
SEEWrite EQU 0A0h ;Write data op-code
SEEWRAL EQU 8Ch ;Write All op-code
SEEEWDS EQU 84h ;Erase/Write Disable op-code

SEE_Port ;Configures Port A to digital (on PIC16C71), sets the SEEPROM


;Chip Select and Serial Clock lines to output, and sets the
;Data line to input. Chip Select is left de-activated.

MOVLW 14h ;Make sure SEECS, SEECLK and SEEDIDO


ANDWF PORTA ;pins are 0 before making them outputs
BSF RP0 ;Select memory page 1

;Remove comments from the following two lines if your program


;uses the PIC16C71 with the A/D converter enabled.
;MOVLW 03h ;1’s set Port A to digital,
;MOVWF ADCON1 ;write to ADCON1 (88h)

MOVLW 14h ;Set SEECS, SEECLK & SEEDIDO pins of


ANDWF TRISA ;Port A to digital output
BCF RP0 ;Select memory page 0
RETURN

SEE_Command ;This subroutine parses the SEEPROM command op-code, completes


;op-code formatting and calls the appropriate routine to clock
;the op-code, address, and data (if necessary) to the SEEPROM.

;The op-code command is stored in the upper 4-6 bits of SEEAddrh


;according to the diagram shown below. For non-extended op-
;codes, SEEAddrh stores the Start-Bit, two Op-code bits and A8.
;The top four bits of SEEAddrh and the contents of SEEAddrl are
;later shifted out to the SEEPROM by the SEE_Clk subroutine,
;which transmits these as a partial serial data frame.

; SEEAddrh SEEAddrl
;+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
;|SB|OP|OP|A8| | | | | |A7|A6|A5|A4|A3|A2|A1|A0|
;+--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+

;For extended op-codes, SEEAddrh stores the Start-Bit, four Op-


;code bits (two op-code bits, plus two extended op-code bits)
;and a flag bit (7B) indicating that only 7 dummy address bits
;need to be sent. In this case, SEE_Clk transmits the upper five
;bits of SEEAddrh and the lower seven bits of SEEAddrl.

; SEEAddrh SEEAddrl
;+--+--+--+---+---+--+--+--+ +--+--+--+--+--+--+--+--+
;|SB|OP|OP|XOP|XOP|7B| | | |A7|A6|A5|A4|A3|A2|A1|A0|
;+--+--+--+---+---+--+--+--+ +--+--+--+--+--+--+--+--+

IORWF SEEAddrh ;Store command to top bits of SEEAddrh


BTFSS SEEAddrh.6 ;Check bit 6 for a 1
GOTO :Check_5 ;If 0, find command by checking bit 5
CALL SEE_SetA8 ;Set A8 and counter for SEEAddrh
BTFSS SEEAddrh.5 ;Check bit 5 for a 1
GOTO SEE_Read ;If 0, goto SEEPROM Read routine
CALL SEE_Clk ;Do clocking for ERASE instruction
GOTO SEE_Done ;and clean up before Returning

:Check_5 MOVLW 05h ;Load W with 5 to shift 5 top bits of


MOVWF SEEClock ;SEEAddrh during clocking
BTFSS SEEAddrh.5 ;Check bit 5 for 1
GOTO :Check_4 ;If bit 5=0, check bit 4
CALL SEE_SetA8 ;Otherwise, set counter and A8 for
GOTO SEE_Write ;SEEPROM WRITE instruction

Program Pull-Out
©1998 Sirius microSystems Microchip Code 39 References
SEEPROM.LIB - Serial EEPROM Subroutine Library
:Check_4 BTFSS SEEAddrh.4 ;If 0, check bit 4 for a 1
GOTO :Check_3 ;If bit4=0, check bit 3
CALL SEE_Clk ;If bit4=1, send EWEN or ERAL commands
GOTO SEE_Done ;and clean up before Returning

:Check_3 BTFSC SEEAddrh.3 ;Check bit3 for a 0


GOTO SEE_Write ;If bit3=1, WRAL using SEEPROM Write
CALL SEE_Clk ;otherwise, send EWDS command and
GOTO SEE_Done ;clean up before Returning

SEE_SetA8 ;Moves A8 bit from bit position 0 of SEEAddrh to bit 4 and


;sets SEEClock to 4 to clock out top 4 bits of SEEAddrh only:

; SEEAddrh
; +--+--+--+--+--+--+--+--+
; |SB|OP|OP|A8| | | |A8| <-original A8 gets moved to bit 4
; +--+--+--+--+--+--+--+--+

MOVLW 04h ;Load W with 4 to shift only top 4


MOVWF SEEClock ;bits of SEEAddrh during clocking
BTFSS SEEAddrh.0 ;Check A8 bit for a 1
RETURN ;If A8=0, Return
BSF SEEAddrh.4 ;otherwise, move A8 bit from 0 to 4
RETURN

SEE_Read ;Reads the byte from the specified address location of the
;SEEPROM into the SEEData register.

CALL SEE_Clk ;Clock op-code and address to SEEPROM

BSF RP0 ;Select memory register page 1


MOVLW 00000010b ;and load W with 00000010b to
IORWF TRISA ;set SEEDIDO line to input
BCF RP0 ;Return to register page 0
MOVLW 08h ;Load the clock counter with 8
MOVWF SEEClock ;to clock data out of SEEPROM
CLRF SEEData ;Clear Data receive byte before read

:ClkData BSF SEECLK ;Set serial clock to read bits


NOP ;and wait for data output to settle
BTFSS SEEDIDO ;Check SEEPROM Data Out for a 1
BCF C ;If DO=0, clear Carry
BTFSC SEEDIDO ;Check SEEPROM Data Out for a 0
BSF C ;If DO=1, set Carry
BCF SEECLK ;Clear SEECLK line
RLF SEEData ;Shift Carry into SEEData register
DECFSZ SEEClock ;Decrement clock counter to clock in
GOTO :ClkData ;all 8 bits of SEEData

BCF SEECS ;Disable SEEPROM Chip Select

GOTO SEE_Port ;Return after re-enabling outputs

SEE_Write ;Stores the byte in SEEData to the address in the SEEPROM


;specified by SEEAddrh and SEEAddrl.

CALL SEE_Clk ;Clock Op-code and address to SEEPROM

MOVLW 08h ;Load the clock counter with 8 to


MOVWF SEEClock ;clock out 8 data bits from SEEData

:ClkData BCF SEECLK ;Clear serial clock between bits


RLF SEEData ;Rotate high bit of SEEData into C
BTFSS C ;Check Carry for a 1
BCF SEEDIDO ;If C=0, clear SEEPROM Data line

40 Microchip Code ©1998 Sirius microSystems


SEEPROM.LIB - Serial EEPROM Subroutine Library
BTFSC C ;Check Carry for a 0
BSF SEEDIDO ;If C=1, set SEEPROM Data line
NOP ;and wait for it to settle
BSF SEECLK ;Clock bit in by setting SEECLK
DECFSZ SEEClock ;Decrement clock counter to clock out
GOTO :ClkData ;all 8 bits of SEEData

BCF SEECLK ;Clear SEEPROM Serial Clock and


GOTO SEE_Done ;clean up before Returning

SEE_Clk ;This subroutine writes the Start bit, Op-code and Address to
;the SEEPROM by serially shifting SEEAddrh and SEEAddrl into
;the SEEPROM. The calling routine determines how many bits
;of SEEAddrh are transmitted.

BCF SEECLK ;Ensure SEEPROM serial clock is clear


BSF SEECS ;before enabling SEEPROM Chip Select

:ClkAddrh BCF SEECLK ;Clear serial clock between bits


RLF SEEAddrh ;Rotate high bit of SEEAddrh into C
BTFSS C ;Check Carry for a 1
BCF SEEDIDO ;If C=0, clear SEEPROM Data line
BTFSC C ;Check Carry for a 0
BSF SEEDIDO ;If C=1, set SEEPROM Data line
NOP ;and wait for it to settle
BSF SEECLK ;Clock bit in by setting SEECLK
DECFSZ SEEClock ;Decrement clock counter to clock out
GOTO :ClkAddrh ;the top 4 bits of the instruction

MOVLW 08h ;If SEEClock was 0, reload the clock


MOVWF SEEClock ;counter with 8 for SEEAddrl
RLF SEEAddrh ;Rotate SEEAddrh once more to check
BTFSC C ;C for the 7-bit dummy address flag
DECF SEEClock ;If 7B flag set, decrement bit counter

:ClkAddrl BCF SEECLK ;Clear serial clock between bits


RLF SEEAddrl ;Rotate high bit of SEEAddrl into C
BTFSS C ;Check Carry for a 1
BCF SEEDIDO ;If C=0, clear SEEPROM Data line
BTFSC C ;Check Carry for a 0
BSF SEEDIDO ;If C=1, set SEEPROM Data line
NOP ;and wait for it to settle
BSF SEECLK ;Clock bit in by setting SEECLK
DECFSZ SEEClock ;Decrement clock counter to clock out
GOTO :ClkAddrl ;all 8 bits of SEEAddrl

BCF SEECLK ;Clear SEEPROM serial clock to finish


RETURN

SEE_Done ;It is important that the upper bits of SEEAddrh are cleared
;before initiating a new SEEPROM command. To save a calling
;program from clearing SEEAddrh between successive commands,
;SEEAddrh and SEEAddrl are automatically cleared after de-
;selecting the SEEPROM.

BCF SEECS ;Clear Chip Select to end command

CLRF SEEAddrh ;Clear contents of SEEAddrh and


CLRF SEEAddrl ;SEEAddrl after use and
RETURN ;Return to the calling program

SEE_Wait ;Waits until the SEEPROM RDY/BSY flag is set, indicating


;the SEEPROM Erase or Write operation has finished.

BSF SEECS ;Set SEEPROM Chip Select and

Program Pull-Out
©1998 Sirius microSystems Microchip Code 41 References
SEEPROM.LIB - Serial EEPROM Subroutine Library
NOP ;Wait for set-up time
:Wait BTFSS SEEDIDO ;Check for 1 on DI/DO pin
GOTO :Wait ;If 0, SEEPROM is still busy
RETURN

42 Microchip Code ©1998 Sirius microSystems


ALARM.ASM - Chapter 9 Example Program
;ALARM.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This program demonstrates port input. It initializes port B bit 0


; as an input and port B bit 1 as an output. When the user
; disconnects bit 0 from ground, the LED connected to bit 1
; illuminates. Note that port B has built-in pull-up resistors
; and therefore requires no external pull-ups.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; Attach a small piece of wire to the third screw terminal (CON1-3).


; Connect this wire to the ninth screw terminal (CON1-9).
; When this wire is disconnected the LED on Port B bit 1 (RB1)
; will light. The LED on RB0 displays the state of the input.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘ALRM’

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector

ORG 05h ;One location past Interrupt vector

Initialize BSF RP0 ;Select register page 1


MOVLW 00000001b ;Load W with desired I/O pattern
MOVWF TRISB ;Move W to TRISB to make bit 0 input
;(1=input, 0=output)
BCF RBPU ;Enable Port B pull-up resistors
;(OPTION.7 on register page 1)
BCF RP0 ;Back to register page 0
CLRF PORTB ;Turn off all LEDs

Main BTFSC PORTB.0 ;Check Port B bit 0 for a low


GOTO LED_On ;If we’re here, bit 0 is high
BCF PORTB.1 ;If bit 0 is low, turn off LED
GOTO Main ;Check bit 0 again

Program Pull-Out
©1998 Sirius microSystems Microchip Code 43 References
ALARM.ASM - Chapter 9 Example Program

LED_On BSF PORTB.1 ;Turn on LED on bit 1


GOTO Main ;Check bit 0 again

44 Microchip Code ©1998 Sirius microSystems


ASCII.ASM - Chapter 12 Example Program
;ASCII.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

;
; This program illustrates how to use the LCD.LIB, KEYPAD.LIB and
; DEC2BIN.LIB subroutine libraries. A user enters three key strokes
; representing a binary number (from 000 to 255, but no error checking
; is done). The key strokes are displayed as well as the equivalent
; ASCII character generated by the LCD.
;
; Use this program to determine LCD character codes for programs.
;
; The keypad is remapped after being called by KB_Scan to return
; the following numbers. Key remapping as well as displaying a
; message on the LCD demonstrate ROM data table reads.
;
; Old key from KB_Scan gets remapped to new key values:
; +----+----+----+----+ +----+----+----+----+
; | 1 | 2 | 3 | 4 | | 1 | 2 | 3 | 0 |
; +----+----+----+----+ +----+----+----+----+
; | 5 | 6 | 7 | 8 | | 4 | 5 | 6 | 0 |
; +----+----+----+----+ +----+----+----+----+
; | 9 | 10 | 11 | 12 | | 7 | 8 | 9 | 0 |
; +----+----+----+----+ +----+----+----+----+
; | 13 | 14 | 15 | 16 | | 0 | 0 | 0 | 0 |
; +----+----+----+----+ +----+----+----+----+
;

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; If you are using the EPIC programmer and the In-Circuit programming
; cable, you must remove this cable from the PIC-MDS to ensure proper
; program execution. Otherwise, keys in column 4 will not be read.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘ASCI’

Program Pull-Out
©1998 Sirius microSystems Microchip Code 45 References
ASCII.ASM - Chapter 12 Example Program
;Hardware Equates

ORG 0Ch ;Start of File register area

;Equates required by BIN2DEC.LIB and DEC2BIN.LIB:


Hundreds DS 1 ;Hundreds digit
Tens DS 1 ;Tens digit
Ones DS 1 ;Ones digit

;Other equates
Counter DS 1 ;LCD character counter

Counter1 DS 1 ;LCD delay counter


Counter2 DS 1 ;LCD delay counter

Key DS 1 ;Key return code variable

Digit DS 1 ;ASCII digit counter variable

ORG 00h ;Start program at Reset Vector

CLRF Key ;Clear Key return variable


CLRF Counter1 ;and delay counters
CLRF Counter2
GOTO Initialize ;Continue with initialize routine

ORG 05h ;One location past Interrupt Vector

Include ‘DEC2BIN.LIB’ ;Decimal to Binary conversion routine


Include ‘KEYPAD.LIB’ ;Keypad scanning subroutine library
Include ‘LCD.LIB’ ;LCD subroutine library

Initialize ;This subroutine initializes the LCD display and writes


;a message on to line 1 and ‘=’ on to line 2. The cursor
;is turned on to indicate where input will be shown.

CLRF Digit ;Clear digit counter


CALL LCD_Port ;Set up ports for LCD use
CALL LCD_Init ;Initialize LCD and clear screen
CALL Disp_Init ;Send first line

Send_Equals MOVLW LCDLine2 ;Load W with address of line 2 (C0h)


ADDLW 0Ah ;and offset cursor to position 11
CALL LCD_REG ;Send cursor position to LCD
MOVLW ‘=’ ;Load W with ASCII ‘=’
CALL LCD_Data ;and send to LCD for display

Set_Cursor MOVLW LCDLine2 ;Load W with address of line 2 (C0h)


ADDLW 06h ;and offset cursor to position 7
CALL LCD_REG ;Send cursor position to LCD

Cursor_On MOVLW CursOn ;Load W with cursor on command (0Eh)


CALL LCD_REG ;and send to LCD

CALL KB_Port ;Configures Port B for keypad

Main ;Main waits for a valid key press. When a valid key returns,
;the keypad is scanned again after a debounce delay. The Key
;value is remapped to the keypad numbers shown in the
;description, above. Key values are successively stored in
;the Hundreds, Tens and Ones registers and displayed on line
;two of the LCD. When three keys have been entered, the key
;codes are converted to binary and displayed on the LCD as
;the character code for that key combination.

Get_Key CALL KB_Scan ;Get Key return code

46 Microchip Code ©1998 Sirius microSystems


ASCII.ASM - Chapter 12 Example Program
MOVF Key,0 ;Check Key return code
BTFSC Z ;for no key press (0=no key)
GOTO Get_Key ;If no key pressed, try again

CALL Delay_5ms ;Wait for key to settle


CALL Delay_5ms
CALL Delay_5ms
CALL Delay_5ms

CALL KB_Scan ;Read Key code after settling


MOVF Key,0 ;Read Key code into W
CALL Key_Remap ;and Remap key codes
MOVWF Key ;Save new Key code to key

MOVF Digit,0 ;Get digit count in W


ADDWF PCL ;and offset PC with digit
GOTO Digit1 ;First time through, write Hundreds
GOTO Digit2 ;next, to Tens
GOTO Digit3 ;then, Ones

Digit1 CALL LCD_Port ;Configure Ports for LCD


MOVF Key,0 ;Get Key return code
MOVWF Hundreds ;and store in Hundreds variable
ADDLW 30h ;Convert Key to ASCII
CALL LCD_Data ;and display on LCD
INCF Digit ;Add one to digit counter
GOTO Release ;Wait for user to release key

Digit2 CALL LCD_Port ;Configure Ports for LCD


MOVF Key,0 ;Get Key return code
MOVWF Tens ;and store in Tens variable
ADDLW 30h ;Convert Key to ASCII
CALL LCD_Data ;and display on LCD
INCF Digit ;Add one to digit counter
GOTO Release ;Wait for user to release key

Digit3 CALL LCD_Port ;Configure Ports for LCD


MOVF Key,0 ;Get Key return code
MOVWF Ones ;and store in Ones variable
ADDLW 30h ;Convert Key to ASCII
CALL LCD_Data ;and display on LCD

Move_Cursor MOVLW LCDLine2 ;Load W with address of line 2 (C0h)


ADDLW 0Ch ;and offset cursor to position 13
CALL LCD_REG ;Send cursor position to LCD

CALL Dec_Bin ;Converts Hundreds, Tens Ones to binary


CALL LCD_Data ;and display on LCD

CLRF Digit ;Reset digit counter

Reset_Cursor MOVLW LCDLine2 ;Load W with address of line 2 (C0h)


ADDLW 06h ;and offset cursor to position 7
CALL LCD_REG ;Send cursor position to LCD

Release ;This is the opposite of the first key check. It waits for
;the Key code to be zero and pauses for the debounce delay.

CALL KB_Port ;Set Port B for keypad use


Wait CALL KB_Scan ;Scan keypad
MOVF Key,0 ;Check key for 0
BTFSS Z ;And if Z=1 key has been released
GOTO Wait ;Otherwise, wait for release
CALL Delay_5ms ;Wait for key to settle
CALL Delay_5ms
CALL Delay_5ms
CALL Delay_5ms
GOTO Main ;Get next digit

Program Pull-Out
©1998 Sirius microSystems Microchip Code 47 References
ASCII.ASM - Chapter 12 Example Program

Disp_Init ;Writes ‘ASCII Code Char.’ to the first line of the LCD
;display using LCD display library (LCD.LIB).

CLRF Counter ;Reset character counter


Get_Char MOVF Counter,0 ;Get character offset into W
CALL Message ;use it to get character
IORLW 00h ;RETLW won’t affect flags so use OR to
BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Counter,1 ;Add 1 to Counter
GOTO Get_Char ;Do it again for the next character

Message ADDWF PCL ;Offset program counter by adding W


RETLW ‘A’ ;Message
RETLW ‘S’
RETLW ‘C’
RETLW ‘I’
RETLW ‘I’
RETLW ‘ ‘
RETLW ‘C’
RETLW ‘o’
RETLW ‘d’
RETLW ‘e’
RETLW ‘=’
RETLW ‘C’
RETLW ‘h’
RETLW ‘a’
RETLW ‘r’
RETLW ‘.’
RETLW 0 ;End of message

Key_Remap ADDWF PCL ;Use old Key to offset PC


NOP ;No Key=0 code
RETLW 1 ;old key code 1 remapped to new key 1
RETLW 2 ;old key code 2 remapped to new key 2
RETLW 3 ;old key code 3 remapped to new key 3
RETLW 0 ;old key code 4 remapped to new key 0
RETLW 4 ;old key code 5 remapped to new key 4
RETLW 5 ;old key code 6 remapped to new key 5
RETLW 6 ;old key code 7 remapped to new key 6
RETLW 0 ;old key code 8 remapped to new key 0
RETLW 7 ;old key code 9 remapped to new key 7
RETLW 8 ;old key code 10 remapped to new key 8
RETLW 9 ;old key code 11 remapped to new key 9
RETLW 0 ;old key code 12 remapped to new key 0
RETLW 0 ;old key code 13 remapped to new key 0
RETLW 0 ;old key code 14 remapped to new key 0
RETLW 0 ;old key code 15 remapped to new key 0
RETLW 0 ;old key code 16 remapped to new key 0

Delay_5ms ;Delay loop used to initialize LCD

CLRF Counter1 ;Wipe first counter


MOVLW 1Ah ;Load W with timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;from constant, above
RETURN

48 Microchip Code ©1998 Sirius microSystems


BLIP.ASM - Chapter 8 Example Program
;BLIP.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This program demonstrates looping for Chapter 8. It initializes all


; port B pins to be outputs, keeps all LEDs lit for a short time, delays
; for a longer time and then repeats.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; This is a simple program that requires no prior setup.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘BLIP’

;Hardware Equates

Counter1 EQU 0Ch ;First delay counter register


Counter2 EQU 0Dh ;Second delay counter register
Counter3 EQU 0Eh ;Third delay counter register

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector
ORG 05h ;One location past Interrupt vector

Initialize BSF RP0 ;Select memory register page 1


CLRF TRISB ;Make Port B output by clearing TRISB
BCF RP0 ;Go back to register page 0
CLRF PORTB ;Clear Port B register
CLRF Counter1 ;Clear Counter1 register (0Ch)
CLRF Counter2 ;and Counter2 register (0Dh)

Main MOVLW 0FFh ;Load W with ones to turn on LEDs


MOVWF PORTB ;and write to Port B register
MOVLW 03h ;Load W with 3
MOVWF Counter2 ;and preset Counter2 before Loop_On

Loop_On DECFSZ Counter1 ;Decrement Counter1 and check for 0

Program Pull-Out
©1998 Sirius microSystems Microchip Code 49 References
BLIP.ASM - Chapter 8 Example Program
GOTO Loop_On ;If not 0, decrement Counter1 again
DECFSZ Counter2 ;If 0, decrement Counter2
GOTO Loop_On ;If not 0, do Counter1 loop

CLRF PORTB ;Turn off LEDs by clearing Port B


MOVLW 0Dh ;Load W with 13
MOVWF Counter3 ;and preset Counter3 before Loop_Off

Loop_Off DECFSZ Counter1 ;Decrement Counter1 and check for 0


GOTO Loop_Off ;If not 0, decrement Counter 1 again
DECFSZ Counter2 ;If Counter1=0, decrement Counter2
GOTO Loop_Off ;If not 0, do Counter1 loop
DECFSZ Counter3 ;If Counter2=0, decrement Counter3
GOTO Loop_Off ;If not 0, do Counter1 & 2 loops
GOTO Main ;If 0, go to Main

50 Microchip Code ©1998 Sirius microSystems


BOUNCE.ASM - Chapter 9 Example Program
;BOUNCE.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This program demonstrates switch contact bounce. It initializes port A


; bit 4 as an input and port B as output. When the user connects port A
; bit 4 to ground, the LEDs display the number of contact bounces that
; occur. The count accumulates until the RESET button is pressed.
; Note that port A has no internal pull-up capability. However the
; PIC-MDS has an external pull-up pre-wired to Port A bit 4 (RA4).

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; Attach a small piece of wire to the third screw terminal (CON1-3).


; When this grounded wire is connected to the 8th screw terminal
; (CON1-8) the LEDs on port B reflect the number of bounces.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘BOUN’

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector

ORG 05h ;One location past Interrupt vector

Initialize BSF RP0 ;Select register page 1


MOVLW 00010000b ;Load W with the desired I/O pattern
MOVWF TRISA ;Make Port A bit 4 input
;(1=input, 0=output)
CLRF TRISB ;Make Port B output
BCF RP0 ;Back to register page 0
CLRF PORTB ;Turn off all LEDs

Main BTFSC PORTA.4 ;Check Port A bit 4 for a low


GOTO Main ;If we’re here, bit 4 is high
INCF PORTB ;If bit 4 is low, increment Port B

Wait_for_High BTFSS PORTA.4 ;Check Port A bit 4 for a high

Program Pull-Out
©1998 Sirius microSystems Microchip Code 51 References
BOUNCE.ASM - Chapter 9 Example Program
GOTO Wait_for_High ;If we’re here, bit 4 is still low
GOTO Main ;Bit 4 went high, wait for next bounce

52 Microchip Code ©1998 Sirius microSystems


CLOCK.ASM - Chapter 11 Example Program
;CLOCK.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

;
; This program demonstrates interrupt driven timing while running a
; separate task. A TMR0 interrupt is generated 60 times per second
; and is used to update the elapsed time on the LCD display. When not
; updating the display, a single LED is scanned across Port B.

; Since PortB is used by both the ISR and the Main routine, the ISR
; saves and restores all port registers.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; None

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘CLK ‘

;Hardware Equates

ORG 0Ch ;Start of File register area

;Equates required by BIN2DEC.LIB and DEC2BIN.LIB:


Hundreds DS 1 ;Hundreds digit
Tens DS 1 ;Tens digit
Ones DS 1 ;Ones digit

;Equates required to keep time:


Hours DS 1 ;Holds elapsed hours
Minutes DS 1 ;Holds elapsed minutes
Seconds DS 1 ;Holds elapsed seconds
Sixtieth DS 1 ;Holds sixtieths of a second

;Other equates
Counter DS 1 ;LCD character counter

Program Pull-Out
©1998 Sirius microSystems Microchip Code 53 References
CLOCK.ASM - Chapter 11 Example Program
Counter1 DS 1 ;LCD delay counter
Counter2 DS 1 ;LCD delay counter

Counter3 DS 1 ;general purpose delay counter


Counter4 DS 1 ;general purpose delay counter

Temp_W DS 1 ;Temporary registers


Temp_Status DS 1 ;used to save values during interrupt
Temp_TRISB DS 1 ;service routine (ISR) The ISR
Temp_TRISA DS 1 ;will save their values on entry
Temp_PortB DS 1 ;and restore them on exit.
Temp_PortA DS 1

Key DS 1 ;Key return code variable

ORG 00h ;Start program at Reset Vector

CLRF Hours ;Set hours to 00


CLRF Minutes ;Set minutes to 00
CLRF Seconds ;Set seconds to 00
GOTO Initialize ;Continue with initialize routine

ORG 04h ;Interrupt Service Routine (ISR)


;starts at Interrupt Vector

Check_T0IF ;When an interrupt occurs, Check_T0IF confirms it was


;generated by a TMR0 overflow. If not, and other interrupts
;are enabled, they must get serviced in the Other_Int
;routine. When TMR0 overflows Sixtieth is decremented and
;checked for equaling zero. If Zero then Seconds, Minutes
;and Hours are updated and displayed. Otherwise, interrupts
;are re-enabled and execution continues.

Save MOVWF Temp_W ;Save W in Temp_W


SWAPF Status,0 ;Swap Status halves into W
MOVWF Temp_Status ;and save Status in Temp_Status

MOVF PORTA,0 ;Load W with Port and TRIS contents


MOVWF Temp_PortA ;and save to temporary registers
MOVF PORTB,0
MOVWF Temp_PortB
BSF RP0
MOVF TRISA,0
MOVWF Temp_TRISA
MOVF TRISB,0
MOVWF Temp_TRISB
BCF RP0

ISR BTFSS T0IF ;Check for TMR0 interrupt


GOTO Other_Int ;If cleared, check other interrupts

DECFSZ Sixtieth ;Has 1 second elapsed?


GOTO Exit ;If not, use Exit to leave ISR
MOVLW 60 ;If zero, reset sixtieth counter
MOVWF Sixtieth ;to 60
INCF Seconds ;Update seconds and
SUBWF Seconds,0 ;check for overflow (Seconds=60)
BTFSS Z ;by testing Z
GOTO Update_Clock ;If Z=0, update clock with new time

CLRF Seconds ;If Z=1, Seconds is 60, reset to 0


MOVLW 60 ;reload W with 60
INCF Minutes ;Update Minutes and
SUBWF Minutes,0 ;check for overflow (Minutes=60)
BTFSS Z ;by testing Z
GOTO Update_Clock ;If Z=0, update clock with new time

54 Microchip Code ©1998 Sirius microSystems


CLOCK.ASM - Chapter 11 Example Program

CLRF Minutes ;If Z=1, Minutes is 60, reset to 0


MOVLW 24 ;Load W with 24
INCF Hours ;Update Hours and
SUBWF Hours,0 ;check for overflow (Hours=24)
BTFSS Z ;by testing Z
GOTO Update_Clock ;If Z=0, update clock with new time

CLRF Hours ;If Z=1, reset hours to 00

Update_Clock CALL LCD_Port ;Reconfigure Ports for LCD and


CALL Disp_Time ;display the new time

Exit ;Reloads TMR0 so the next 60th second time-out can generate
;an interrupt and restores all registers.

MOVLW 93 ;Preload W for 60 Hz delay


MOVWF TMR0 ;and save to TMR0
BCF T0IF ;Clear TMR0 interrupt flag and
BSF T0IE ;enable TMR0 interrupt

Restore MOVF Temp_PortA,0 ;Restore registers from temporary


MOVWF PORTA ;registers
MOVF Temp_PortB,0
MOVWF PORTB
BSF RP0
MOVF Temp_TRISA,0
MOVWF TRISA
MOVF Temp_TRISB,0
MOVWF TRISB
BCF RP0

SWAPF Temp_Status,0 ;Swap Status halves to W


MOVWF Status ;and return Status to pre-interrupt
;value
SWAPF Temp_W,1 ;Swap halves of Temp_W
SWAPF Temp_W,0 ;Swap Temp_W back to W

RETFIE ;Return and enable interrupts

Other_Int MOVLW 20h ;Set only TMR0 interrupt


MOVWF INTCON ;and write to interrupt register
RETFIE ;Return and enable global interrupts

Initialize CLRF Counter ;Clear counters


CLRF Counter1
CLRF Counter2
CLRF Counter3
CLRF Counter4
MOVLW 60 ;Preload sixtieths
MOVWF Sixtieth ;with 60

CALL LCD_Port ;Set up ports for LCD use


CALL LCD_Init ;Initialize LCD and clear screen
CALL Disp_Init ;Display “Elapsed time:” on line 1
CALL Disp_Time ;Display time on line 2

CALL TMR0_Init ;Initialize Real Time Clock Counter


;Timer 0 (TMR0) and enable interrupts.

BSF RP0 ;Select Register Page 1


CLRF TRISB ;Make Port B output
BCF RP0 ;Back to Register Page 0

MOVLW 01h ;Light up the first LED


MOVWF PORTB ;on Port B
BCF C ;Clear the Carry

Program Pull-Out
©1998 Sirius microSystems Microchip Code 55 References
CLOCK.ASM - Chapter 11 Example Program

Main ;This code runs when the Interrupt service routine isn’t
;running and cycles a single LED across the display.

:Loop DECFSZ Counter3,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter4,1 ;Decrement, second counter
GOTO :Loop ;from constant, above

RLF PORTB ;Rotate PORTB to the left


GOTO Main ;Do it again and again and ...

Disp_Init ;Writes ‘Elapsed time:’ to first line of LCD display using


;LCD display library (LCD.LIB).

MOVLW LCDCLR ;Send LCD clear display code


CALL LCD_REG ;to LCD as a command
MOVLW LCDLine1 ;Send LCD line one address to
CALL LCD_REG ;LCD as a command
CLRF Counter ;Reset character counter
Get_Char MOVF Counter,0 ;Get character offset into W
CALL Message ;use it to get character
IORLW 00h ;RETLW won’t affect flags so use OR to
BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Counter,1 ;Add 1 to Counter
GOTO Get_Char ;Do it again for the next character

Message ADDWF PCL ;Offset program counter by adding W


RETLW ‘E’ ;Message
RETLW ‘l’
RETLW ‘a’
RETLW ‘p’
RETLW ‘s’
RETLW ‘e’
RETLW ‘d’
RETLW ‘ ‘
RETLW ‘t’
RETLW ‘i’
RETLW ‘m’
RETLW ‘e’
RETLW ‘:’
RETLW 0 ;End of message

Disp_Time ;Converts binary Hours, Minutes and Seconds digits to BCD


;and then to ASCII and displays them on LCD separated by
;colons.

MOVLW LCDLine2 ;Send LCD line two address to


CALL LCD_REG ;LCD as a command
MOVF Hours,0 ;Load W with Hours value
CALL Disp_Digits ;and output to LCD
MOVLW ‘:’ ;Load W with ASCII value of ‘:’
CALL LCD_Data ;and display on LCD
MOVF Minutes,0 ;Load W with Minutes value
CALL Disp_Digits ;and output to LCD
MOVLW ‘:’ ;Load W with ASCII value of ‘:’
CALL LCD_Data ;and display on LCD
MOVF Seconds,0 ;Load W with Seconds value
CALL Disp_Digits ;and output to LCD
RETURN

Disp_Digits ;Converts and displays value in W as two digits on LCD.

56 Microchip Code ©1998 Sirius microSystems


CLOCK.ASM - Chapter 11 Example Program
CALL BIN_DEC ;and convert to tens and ones
MOVLW 30h ;Load W with ASCII offset
ADDWF Tens,1 ;and add to Tens digit
ADDWF Ones,1 ;and Ones to change to ASCII
MOVF Tens,0 ;Load W with Tens value
CALL LCD_Data ;and display on LCD
MOVF Ones,0 ;Load W with Ones value
CALL LCD_Data ;and display on LCD
RETURN

TMR0_Init ;Assign prescaler to TMR0 and preload TMR0 for 60 Hz


;interrupts.

CLRWDT ;Clear WDT and prescaler


BSF RP0 ;Select register page 1
MOVF OPTION,0 ;Load W with current OPTION reg.
ANDLW 11000111b ;Clear T0CS, T0SE and PSA bits
;T0CS=OPTION.5, Counter select
;0=Timer mode, 1=Counter mode
;T0SE=OPTION.4, Source Edge select
;0=Rising edge, 1=Falling edge
;PSA=OPTION.3, Prescaler Assignment
;0=TMR0, 1=WDT
IORLW 00000111b ;Set PS2, PS1 and PS0
;000=/2, 001=/4, ...111=/256
MOVWF OPTION ;Set OPTION register with new value
BCF RP0 ;Return to register page 0

MOVLW 93 ;Load W with 93 because incrementing


MOVWF TMR0 ;TMR0 from 93-256 takes 1/60s

MOVLW 20h ;Enable only the TMR0 interrupt


MOVWF INTCON ;and write to INTCON

RETFIE ;Return and enable global interrupts

Delay_5ms ;Delay loop used to initialize LCD

CLRF Counter1 ;Wipe first counter


MOVLW 1Ah ;Load W with timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;from constant, above
RETURN

Include ‘BIN2DEC.LIB’ ;Binary to Decimal conversion routine


Include ‘LCD.LIB’ ;LCD subroutine library

Program Pull-Out
©1998 Sirius microSystems Microchip Code 57 References
COUNT.ASM - Chapter 8 Example Program
;COUNT.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This program demonstrates port output. It initializes all port B pins


; to be outputs and then counts from 0 to 255 (FFh) repeatedly.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; This is a simple program that requires no prior setup.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘CNT ‘

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector

ORG 05h ;One location past Interrupt vector

Initialize BSF RP0 ;Select memory register page 1


CLRF TRISB ;Make Port B output by clearing TRISB
BCF RP0 ;Go back to register page 0
CLRF PORTB ;Turn off LEDs by clearing Port B

Loop INCF PORTB ;Add 1 to Port B register


GOTO Loop ;and do it again, and again...

Done SLEEP ;Stop executing the program

58 Microchip Code ©1998 Sirius microSystems


CUSTOM.ASM - Chapter 12 Example Program
;CUSTOM.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

;
; This program demonstrates how to create & use custom LCD characters.
; Four Truck and four Man characters are created from bitmaps. The
; Man character is used to show cursor cell animation and the Truck
; demonstrates line scrolling.
;

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; None

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘CUST’

;Hardware Equates

ORG 0Ch ;Start of File register area

Counter DS 1 ;LCD character counter


Position DS 1 ;LCD position counter

Counter1 DS 1 ;LCD delay counter


Counter2 DS 1 ;LCD delay counter

ORG 00h ;Start program at Reset Vector

CLRF Counter ;Clear LCD character counter


CLRF Counter1 ;and delay counters
CLRF Counter2
GOTO Initialize ;Continue with initialize routine

ORG 05h ;One location past Interrupt Vector

Include ‘LCD.LIB’ ;LCD subroutine library

Program Pull-Out
©1998 Sirius microSystems Microchip Code 59 References
CUSTOM.ASM - Chapter 12 Example Program

Initialize ;This subroutine initializes the LCD display and programs


;the custom characters by calling Prog_Character.

CALL LCD_Port ;Set up ports for LCD use


CALL LCD_Init ;Initialize LCD and clear screen
CALL Prog_Character ;Load LCD with custom characters
MOVLW LCDLine1 ;Load W with Line 1 address
MOVWF Position ;Save W in Position register
CALL LCD_REG ;and send to LCD as command
MOVLW 04h ;Load W with Man1 Character code
MOVWF Counter ;and save in LCD character counter

Walk ;Makes a little man walk across the screen by successively


;writing each of the 4 Man characters into the same cursor
;position and then moving the cursor 1 position to the
;right before repeating.

MOVF Counter,0 ;Get current Man Character


CALL LCD_Data ;and send to LCD
MOVLW CursLeft ;Load W with Cursor Left shift
CALL LCD_Reg ;command and send to LCD
CALL Delay ;Wait a bit
INCF Counter ;Increment to next Man Character
MOVLW 08h ;Load W with number of last Man
SUBWF Counter,0 ;and check for last count
BTFSS Z ;by checking Z
GOTO Walk ;If not at last Man, display next man

MOVLW ‘ ‘ ;If at last Man, Load W with ‘ ‘


CALL LCD_Data ;to clear character
MOVLW 04h ;Load W with Man1 Character
MOVWF Counter ;and save to character counter
INCF Position ;Increment cursor position variable
MOVLW 90h ;Load W with last visible position
SUBWF Position,0 ;and compare with Position
BTFSS Z ;by checking Z
GOTO Walk ;If not at last position, do it again

CALL Delay ;If done, wait before rolling Truck

Roll ;Scrolls a Truck back across the screen continuously by


;writing the 4 Truck characters off the screen (cursor was
;left at position 90h by Walk) and then scrolling the
;screen to the left. Since the display was cleared earlier
;you will see only the Truck. The line length is 40 chars.
;Every 40 display shifts, the Truck comes around again.

CLRF Counter ;Clear character counter variable


:Next MOVF Counter,0 ;Load W with counter
CALL LCD_Data ;and send character to LCD
INCF Counter ;Increment Counter register
MOVLW 04h ;Load W with number of Truck chars.
SUBWF Counter,0 ;and compare with counter
BTFSS Z ;by checking Z
GOTO :Next ;If not done, send next Truck char.

:Loop MOVLW LCDLeft ;If done, load W with LCD shift left
CALL LCD_Reg ;command and send to LCD
CALL Delay ;Wait a bit
GOTO :Loop ;Keep scrolling the display

Prog_Character ;Loads the custom character data into the LCD Character
;Generator RAM. CGRAM is ASCII characters 0-7. Each character
;is loaded as a bit-map, one line at a time. The cursor
;auto-increments to the next CGRAM location after each
;write.

60 Microchip Code ©1998 Sirius microSystems


CUSTOM.ASM - Chapter 12 Example Program

MOVLW LCDCGRAM ;Send LCD CGRAM address (40h) to


CALL LCD_REG ;LCD as a command
CLRF Counter ;Reset character counter
Get_Char MOVF Counter,0 ;Get character offset into W
CALL Characters ;use it to get character data
CALL LCD_Data ;If not done, send character to LCD
INCF Counter,1 ;Add 1 to Counter
MOVLW 64 ;Load W with number of char. bytes
SUBWF Counter,0 ;and compare with Counter
BTFSC Z ;by checking Z flag
RETURN ;If Counter=64, we’re done
GOTO Get_Char ;Do it again for the next character

Characters ADDWF PCL ;Offset PC with Counter in W

Truck1 RETLW 00000000b ;Row 1, ASCII character 00


RETLW 00000011b ;Row 2, ASCII character 00
RETLW 00000011b ;Row 3, ASCII character 00
RETLW 00001111b ;etc.
RETLW 00001111b
RETLW 00011010b
RETLW 00000111b
RETLW 00000010b

Truck2 RETLW 00001111b ;Row 1, ASCII character 01


RETLW 00001111b ;Row 2, ASCII character 01
RETLW 00001111b ;etc.
RETLW 00001111b
RETLW 00011111b
RETLW 00001010b
RETLW 00011111b
RETLW 00001010b

Truck3 RETLW 00011111b


RETLW 00011111b
RETLW 00011111b
RETLW 00011111b
RETLW 00011111b
RETLW 00000000b
RETLW 00000000b
RETLW 00000000b

Truck4 RETLW 00011111b


RETLW 00011111b
RETLW 00011111b
RETLW 00011111b
RETLW 00011111b
RETLW 00001010b
RETLW 00011111b
RETLW 00001010b

Man1 RETLW 00000000b


RETLW 00000000b
RETLW 00010000b
RETLW 00011000b
RETLW 00010000b
RETLW 00001000b
RETLW 00001000b
RETLW 00000000b

Man2 RETLW 00000000b


RETLW 00000000b
RETLW 00000000b
RETLW 00001000b
RETLW 00011100b
RETLW 00001000b
RETLW 00011000b

Program Pull-Out
©1998 Sirius microSystems Microchip Code 61 References
CUSTOM.ASM - Chapter 12 Example Program
RETLW 00001000b

Man3 RETLW 00000000b


RETLW 00000000b
RETLW 00000000b
RETLW 00000100b
RETLW 00000110b
RETLW 00000100b
RETLW 00001010b
RETLW 00001010b

Man4 RETLW 00000000b ;Row 1, ASCII character 07


RETLW 00000000b ;Row 2, ASCII character 07
RETLW 00000001b
RETLW 00000011b
RETLW 00000001b
RETLW 00000011b
RETLW 00000001b
RETLW 00000000b ;Row 8, ASCII character 07

Delay ;Delay between Man & Truck movements

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;256 more times
RETURN

Delay_5ms ;Delay loop used to initialize LCD

CLRF Counter1 ;Wipe first counter


MOVLW 1Ah ;Load W with timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;from constant, above
RETURN

62 Microchip Code ©1998 Sirius microSystems


DBOUNCE.ASM - Chapter 9 Example Program
;DBOUNCE.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This program demonstrates switch contact debouncing. It initializes


; port A bit 4 as an input and port B as output. Each time the user
; connects port A bit 4 to ground, the LEDs increment, displaying the
; number of contact closures. The count accumulates until the RESET
; button is pressed. Note that port A has no internal pull-up
; capability. However the PIC-MDS has an external pull-up pre-wired to
; Port A bit 4.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; Attach a small piece of wire to the third screw terminal (CON1-3).


; When this grounded wire is connected to the 8th screw terminal
; (CON1-8) the LEDs on port B increment, reflecting the number of switch
; closures.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘DBNC’

;Hardware Equates

Counter1 EQU 0Ch ;First delay counter variable


Counter2 EQU 0Dh ;Second delay counter variable

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector

ORG 05h ;One location past Interrupt vector

Initialize BSF RP0 ;Select register page 1


MOVLW 00010000b ;Load W with the desired I/O pattern
MOVWF TRISA ;Make Port A bit 4 input
;(1=input, 0=output)
CLRF TRISB ;Make Port B output

Program Pull-Out
©1998 Sirius microSystems Microchip Code 63 References
DBOUNCE.ASM - Chapter 9 Example Program
BCF RP0 ;Back to register page 0
CLRF PORTB ;Turn off all LEDs
CLRF Counter1 ;Clear location Counter1 (0Ch)
MOVLW 40h ;Load W with preset for counter 2
MOVWF Counter2 ;Store W to Counter2 (0Dh)

Main BTFSC PORTA.4 ;Check Port A bit 4 for a low


GOTO Main ;If we’re here, bit 4 is high

Delay DECFSZ Counter1 ;If we’re here, bit 4 is low


GOTO Delay ;Let’s wait at least 20 ms for the
DECFSZ Counter2 ;contacts to settle
GOTO Delay

MOVLW 40h ;Once delay is done, reset counter 2


MOVWF Counter2 ;Store W to Counter2 (0Dh)

BTFSS PORTA.4 ;Is Port A bit 4 still low?


INCF PORTB ;If so, increment Port B

Wait_for_High BTFSS PORTA.4 ;Wait for Port A bit 4 to go high


GOTO Wait_for_High ;If low, keep checking
GOTO Main ;If high, go back to Main

64 Microchip Code ©1998 Sirius microSystems


DELAY.ASM - Chapter 8 Example Program
;DELAY.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This program demonstrates port output. It initializes all port B pins


; to be outputs and then counts from 0 to 255 (FFh) repeatedly with a
; delay of 65536 decrements between each count.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; This is a simple program that requires no prior setup.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘DELA’

;Hardware Equates

Counter1 EQU 0Ch ;First delay counter register


Counter2 EQU 0Dh ;Second delay counter register

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector

ORG 05h ;One location past Interrupt vector

Initialize BSF RP0 ;Select memory register page 1


CLRF TRISB ;Make Port B output by clearing TRISB
BCF RP0 ;Go back to register page 0
CLRF PORTB ;Clear Port B register
CLRF Counter1 ;Clear Counter1 register (0Ch)
CLRF Counter2 ;and Counter2 register(0Dh)

Main INCF PORTB ;Add 1 to Port B register


Loop DECFSZ Counter1 ;Decrement Counter1 and check for 0
GOTO Loop ;If not 0, decrement Counter 1 again
DECFSZ Counter2 ;If 0, decrement Counter2
GOTO Loop ;If Counter2 is not 0, decrement
;Counter1 another 256 times
GOTO Main ;Update the LEDs after 65536 counts
Program Pull-Out
©1998 Sirius microSystems Microchip Code 65 References
KEY.ASM - Chapter 10 Example Program
;KEY.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; Col. 1 2 3 4
; Row +----+----+----+----+
; Port B.0----1---| 1 | 2 | 3 | 4 |
; +----+----+----+----+
; Port B.1----2---| 5 | 6 | 7 | 8 |
; +----+----+----+----+
; Port B.2----3---| 9 | 10 | 11 | 12 |
; +----+----+----+----+
; Port B.3----4---| 13 | 14 | 15 | 16 |
; +----+----+----+----+
; Port B.4----------+ | | |
; | | |
; Port B.5---------------+ | |
; | |
; Port B.6--------------------+ |
; |
; Port B.7-------------------------+
;
; This program demonstrates matrix keypad scanning along with LCD
; output using included subroutine libraries. The keypad is scanned
; continuously. Key return codes are converted to ASCII and displayed
; by their key digit (from the above diagram) on the LCD display.
; The key code will display for as long as it is valid.
;
; This program uses the DS (Define Space) directive instead of EQU
; (Equate) to define RAM registers. The advantage of this approach
; is that hardware registers can be created and removed from this
; program without manually re-locating their addresses. The drawback
; is that the physical location of the register is defined by the
; assembler, not the user.
;
; Also, notice that this program utilizes the space from memory
; location 0000h to the interrupt vector at 0004h. It’s not much
; space, but you can cram an extra 3 words into your program by
; doing this (the 4th word is the GOTO which jumps the interrupt
; vector, and is not really useful as storage).

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

66 Microchip Code ©1998 Sirius microSystems


KEY.ASM - Chapter 10 Example Program

; If you are using the EPIC programmer and the In-Circuit programming
; cable, you must remove this cable from the PIC-MDS to ensure proper
; program execution. Otherwise, keys in column 4 will not be read.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘KEY ‘

;Hardware Equates

ORG 0Ch ;Start of File register area

;Equates required by KEYPAD.LIB:


Key DS 1 ;Key code return register

;Equates required by BIN2DEC.LIB and DEC2BIN.LIB:


Hundreds DS 1 ;Hundreds digit
Tens DS 1 ;Tens digit
Ones DS 1 ;Ones digit

;Other equates
Counter DS 1 ;character counter for LCD
Counter1 DS 1 ;general purpose counter
Counter2 DS 1 ;general purpose counter
Counter3 DS 1 ;general purpose counter

ORG 00h ;Start program at Reset Vector

CLRF Key ;Clear Key storage register


CALL LCD_Port ;Set up ports for LCD output
CALL LCD_Init ;Initialize LCD and clear screen
GOTO Initialize ;Continue with initialize routine

ORG 05h ;Continue after interrupt vector

Include ‘LCD.LIB’ ;LCD subroutines go here


Include ‘KEYPAD.LIB’ ;followed by Keypad subroutines
Include ‘BIN2DEC.LIB’ ;and Binary to Decimal conversion

Initialize CALL DisplayInit ;Display “Key Pressed:” on LCD

Main ;This program loop scans the keypad using KEYPAD.LIB and
;gets the key value from Key register. BIN2DEC.LIB is used
;to convert the binary key number to three decimal digits.
;Each decimal digit is converted to ASCII by adding 30h and
;is sent to the LCD display.

MOVF Key,0 ;Get key code in W


CALL BIN_DEC ;and convert to decimal
CALL LCD_Port ;Set up ports for LCD output
MOVLW 8Dh ;Send address of hundreds digit
CALL LCD_REG ;to LCD display data RAM
MOVLW 30h ;Load constant to convert to ASCII
ADDWF Hundreds,1 ;and add to hundreds digit
ADDWF Tens,1 ;add to tens digit
ADDWF Ones,1 ;and add to ones digit
MOVF Hundreds,0 ;Get hundreds digit into W
CALL LCD_Data ;and send it to LCD
MOVF Tens,0 ;Get tens digit into W
CALL LCD_Data ;and send it to LCD
MOVF Ones,0 ;Get ones digit into W
CALL LCD_Data ;and send it to LCD
CALL KB_Port ;Set up Port B for keypad input

Program Pull-Out
©1998 Sirius microSystems Microchip Code 67 References
KEY.ASM - Chapter 10 Example Program
CALL KB_Scan ;Read Port B for key press
GOTO Main ;Do it again!

DisplayInit ;Writes ‘Key Pressed:’ to first line of LCD using


;LCD display library (LCD.LIB).

MOVLW LCDCLR ;Send LCD clear display code


CALL LCD_REG ;to LCD as a command
MOVLW LCDLine1 ;Send LCD line one address to
CALL LCD_REG ;LCD as a command
CLRF Counter ;Reset character counter
Get_Char MOVF Counter,0 ;Get character offset into W
CALL Message ;use it to get character
IORLW 00h ;RETLW won’t affect flags so use OR to
BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Counter,1 ;Add 1 to Counter
GOTO Get_Char ;Do it again for next character

Message ADDWF PCL ;Offset program counter by adding W


RETLW ‘K’ ;Message
RETLW ‘e’
RETLW ‘y’
RETLW ‘ ‘
RETLW ‘P’
RETLW ‘r’
RETLW ‘e’
RETLW ‘s’
RETLW ‘s’
RETLW ‘e’
RETLW ‘d’
RETLW ‘:’
RETLW 0 ;End of message marker

Delay_5ms ;Delay loop used to initialize LCD

CLRF Counter1 ;Wipe first counter


MOVLW 1Ah ;Load W with Timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;from constant, above
RETURN

68 Microchip Code ©1998 Sirius microSystems


KEYINT.ASM - Chapter 11 Example Program
;KEYINT.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; Col. 1 2 3 4
; Row +----+----+----+----+
; Port B.0----1---| 1 | 2 | 3 | 4 |
; +----+----+----+----+
; Port B.1----2---| 5 | 6 | 7 | 8 |
; +----+----+----+----+
; Port B.2----3---| 9 | 10 | 11 | 12 |
; +----+----+----+----+
; Port B.3----4---| 13 | 14 | 15 | 16 |
; +----+----+----+----+
; Port B.4----------+ | | |
; | | |
; Port B.5---------------+ | |
; | |
; Port B.6--------------------+ |
; |
; Port B.7-------------------------+
;
; This program demonstrates interrupt driven matrix keypad scanning
; along with LCD output using included subroutine libraries. This
; program is functionally equivalent to KEY.ASM in its operation, but
; puts the microcontroller to sleep in between operations. Sleep mode
; allows for ultra-low power consumption and is useful for extending
; the battery life or portable applications.
;
; The program first initializes the LCD and displays “Key Pressed:”.
; Next, assuming the microcontroller will shortly be sleeping, the
; letters “ZZZ” replace the key code number. Then, port B is
; reconfigured for keypad input with the pull-up resistors enabled.
; Finally, the RB Port Change interrupt is enabled after clearing
; the interrupt flag (just in case). After setting the Global
; Interrupt Enable flag, the microcontroller goes to sleep.
;
; When a key on the keypad is pressed, it pulls one of the RB4-7
; input pins low, generating an interrupt. The microcontroller begins
; to execute the code at 0004h—the interrupt vector. Here, the RB
; port change interrupt is disabled, Port B is used to scan the keys
; for a key press, and the result is converted to ASCII and displayed
; on the LCD. By this point, the user is likely still holding the key
; on, and the microcontroller is once more put to sleep with the RB
; port change interrupt enabled. When the key is released, the code
; at 0004h again executes, updating the display.
;
; This program uses the DS (Define Space) directive instead of EQU
; (Equate) to define RAM registers. The advantage of this approach
; is that hardware registers can be created and removed from this
; program without manually re-locating their addresses. The drawback
; is that the physical location of the register is defined by the
; assembler, not the user.
;
; Also, notice that this program utilizes the space from memory

Program Pull-Out
©1998 Sirius microSystems Microchip Code 69 References
KEYINT.ASM - Chapter 11 Example Program
; location 0000h to the interrupt vector at 0004h. It’s not much
; space, but you can cram an extra 3 words into your program by
; doing this (the 4th word is the GOTO which jumps the interrupt
; vector, and is not really useful as storage).

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; If you are using the EPIC programmer and the In-Circuit programming
; cable, you must remove this cable from the PIC-MDS to ensure proper
; program execution. Otherwise, keys in column 4 will not be read.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘KEYI’

;Hardware Equates

ORG 0Ch ;Start of File register area

;Equates required by KEYPAD.LIB:


Key DS 1 ;Key code return register

;Equates required by BIN2DEC.LIB and DEC2BIN.LIB:


Hundreds DS 1 ;Hundreds digit
Tens DS 1 ;Tens digit
Ones DS 1 ;Ones digit

;Other equates
Counter DS 1 ;character counter for LCD
Counter1 DS 1 ;general purpose counter
Counter2 DS 1 ;general purpose counter
Counter3 DS 1 ;general purpose counter

ORG 00h ;Start program at Reset Vector

CLRF Key ;Clear key storage register


CALL LCD_Port ;Set up ports for LCD use
CALL LCD_Init ;Initialize LCD and clear screen
GOTO Initialize ;Continue with initialize routine

ORG 04h ;Interrupt service routine starts here

Check_RBIF ;When an interrupt occurs, Check_RBIF confirms it was


;generated by RB Port Change. If not, and other interrupts
;are enabled, they must get serviced in the Other_Int
;routine. When a valid key arrives, it gets displayed,
;then the port is re-configured for keypad input. Exiting
;this interrupt service routine, re-enables interrupts.

BTFSS RBIF ;Check for RB port change interrupt

70 Microchip Code ©1998 Sirius microSystems


KEYINT.ASM - Chapter 11 Example Program
GOTO Other_Int ;If cleared, check other interrupts
CALL Delay_5ms ;Wait for key to settle
CALL Delay_5ms ;10 ms should be enough time
CALL KB_Port ;Set up Port B for keypad scanning
CALL KB_Scan ;Scan keys for key press
MOVF Key,0 ;Check Key register for 0 - no key
BTFSC Z ;by testing the Z flag
GOTO Nap_Time ;If no key was returned, user let go
;so we display ZZZ to indicate sleep

CALL BIN_DEC ;If key returned, convert to decimal


CALL LCD_Port ;Set up ports for LCD output
MOVLW 8Dh ;Send address of hundreds digit
CALL LCD_REG ;to display data RAM
MOVLW 30h ;Load constant to convert to ASCII
ADDWF Hundreds,1 ;and add to hundreds digit,
ADDWF Tens,1 ;add to tens digit
ADDWF Ones,1 ;and add to ones digit
MOVF Hundreds,0 ;Gets hundreds digit into W and
CALL LCD_Data ;send it to LCD
MOVF Tens,0 ;Get tens digit into W and
CALL LCD_Data ;send it to LCD
MOVF Ones,0 ;Get ones digit into W and
CALL LCD_Data ;send it to LCD

CALL KB_Port ;Set up Port B for keypad scanning


CLRF PORTB ;and get ready for Port B Change
MOVF PORTB,0 ;Update Port B input latches
BCF RBIF ;Clear the interrupt flag
RETFIE ;and return

Other_Int RETFIE ;Return and enable global interrupts

Initialize CALL DisplayInit ;Display “Key Pressed:” on LCD

Nap_Time MOVLW 8Dh ;Send address of hundreds digit


CALL LCD_REG ;to display data RAM
MOVLW ‘Z’ ;Load ASCII character Z
CALL LCD_Data ;and send it to LCD
MOVLW ‘Z’ ;Re-load ASCII character Z
CALL LCD_Data ;and send it to LCD
MOVLW ‘Z’ ;One more time!
CALL LCD_Data ;and send it to LCD

CALL Init_Port_B ;Get Port B ready for interrupts

Main SLEEP ;Shut down and wait for key press


NOP
GOTO Main

DisplayInit ;Writes ‘Key Pressed:’ to first line of LCD display using


;LCD display library (LCD.LIB).

MOVLW LCDCLR ;Send LCD clear display code


CALL LCD_REG ;to LCD as a command
MOVLW LCDLine1 ;Send LCD line one address to
CALL LCD_REG ;LCD as a command
CLRF Counter ;Reset character counter
Get_Char MOVF Counter,0 ;Get character offset into W
CALL Message ;use it to get character
IORLW 00h ;RETLW won’t affect flags so use OR to
BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Counter,1 ;Add 1 to Counter
GOTO Get_Char ;Do it again for the next character

Program Pull-Out
©1998 Sirius microSystems Microchip Code 71 References
KEYINT.ASM - Chapter 11 Example Program

Message ADDWF PCL ;Offset program conter by adding W


RETLW ‘K’ ;Message
RETLW ‘e’
RETLW ‘y’
RETLW ‘ ‘
RETLW ‘P’
RETLW ‘r’
RETLW ‘e’
RETLW ‘s’
RETLW ‘s’
RETLW ‘e’
RETLW ‘d’
RETLW ‘:’
RETLW 0 ;End of message

Init_Port_B ;Sets Port B up for keypad scanning. RB0-3 are low outputs
;and RB4-7 are inputs with pull-ups enabled. When a key
;press occurs, one of the RB4-7 inputs goes low, generating
;and interrupt.

CALL KB_Port ;Set Port B for keypad scanning


CLRF PORTB ;Make outputs low
MOVLW 08h ;Set only RB port change interrupt
MOVWF INTCON ;and write to interrupt register
RETFIE ;Return and enable interrupts

Delay_5ms ;Delay loop used to initialize LCD

CLRF Counter1 ;Wipe first counter


MOVLW 1Ah ;Load W with timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;from constant, above
RETURN

Include ‘BIN2DEC.LIB’ ;Binary to Decimal conversion routine


Include ‘KEYPAD.LIB’ ;Key pad scanning routines
Include ‘LCD.LIB’ ;LCD subroutine library

72 Microchip Code ©1998 Sirius microSystems


KEYSCAN.ASM - Chapter 9 Example Program
;KEYSCAN.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; Col. 1 2 3 4
; Row +----+----+----+----+
; Port B.0----1---| 1 | 2 | 3 | 4 |
; +----+----+----+----+
; Port B.1----2---| 5 | 6 | 7 | 8 |
; +----+----+----+----+
; Port B.2----3---| 9 | 10 | 11 | 12 |
; +----+----+----+----+
; Port B.3----4---| 13 | 14 | 15 | 16 |
; +----+----+----+----+
; Port B.4----------+ | | |
; | | |
; Port B.5---------------+ | |
; | |
; Port B.6--------------------+ |
; |
; Port B.7-------------------------+
;
; This program demonstrates matrix keypad scanning. Port B.0-3 connect
; to the keypad rows and are set as outputs. Port B.4-7 connect to the
; keypad columns and are set as inputs with the internal pull-up
; resistors enabled. To read the keypad, a row is set low. While the
; row is low, each column input is examined. Columns normally are high
; because of the pull-up resistors. If a column is low, the key at that
; row-column intersection is pressed. If no column is found low, the
; program advances to the next row.
;
; When a key press is detected, that row-column combination assigns a
; number from 1-16 (according to the above diagram) to the Key variable.
; The binary value in the Key variable is displayed on the LEDs. Note
; that the same Port B pins have two functions: most of the time they
; are scanning the keypad, with Port B.4-7 as inputs and Port B.0-3 as
; outputs. When a key is pressed Port B is temporarily set to output to
; display the key value. The key will display for a short period of
; time. When a key is not pressed, you will notice the key scanning
; taking place.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

Program Pull-Out
©1998 Sirius microSystems Microchip Code 73 References
KEYSCAN.ASM - Chapter 9 Example Program

; If you are using the EPIC programmer and the In-Circuit programming
; cable, you must remove this cable from the PIC-MDS to ensure proper
; program execution. Otherwise, keys in column 4 will not be read.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘KSCN’

;Hardware Equates

Counter1 EQU 0Ch ;Delay counter register


Counter2 EQU 0Dh ;Delay counter register
Counter3 EQU 0Eh ;Delay counter register
Key EQU 0Fh ;This register will hold a number from
;0-15 representing the last key pressed

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector

ORG 05h ;One location past Interrupt vector

Initialize BSF RP0 ;Select register page 1


MOVLW 0F0h ;Set keypad column connections to input
;(Port B.4-7) and row connections to
;output (Port B.0-3)
MOVWF TRISB ;Write to Port B tristate register
BSF RBPU ;Enable pull-ups on inputs
BCF RP0 ;Go back to register page 0
CLRF Counter1 ;Clear delay loop counters
CLRF Counter2
MOVLW 08h ;Preload Counter3 delay loop counter
MOVWF Counter3 ;for 1/2 second delay

Main CLRF Key ;Clear Key register and


INCF Key ;Increment Key
MOVLW 0Eh ;Output 0 to first row only,
MOVWF PORTB ;Output to Port B
NOP ;Wait for signals to settle

Col_Check BTFSS PORTB.4 ;Check first column for low


GOTO Dispkey ;and if low, display key
INCF Key ;If no key press, increment key number
BTFSS PORTB.5 ;Check second column for low
GOTO Dispkey ;and if low, display key
INCF Key ;If no key press, increment key number
BTFSS PORTB.6 ;Check third column for low
GOTO Dispkey ;and if low, display key
INCF Key ;If no key press, increment key number
BTFSS PORTB.7 ;Check fourth column for low
GOTO Dispkey ;and if low, display key
INCF Key ;If no key press, increment key number

Row_Set MOVLW 11h ;Load W with number of keys + 1


SUBWF Key,0 ;and compare with current key value
BTFSC Z ;If keys + 1 = current key then
GOTO Main ;no key was pressed

BSF C ;Set carry bit


RLF PORTB ;so that row 1 is high during rotate
GOTO Col_Check ;and check next column

Dispkey BSF RP0 ;Select register page 1


CLRF TRISB ;Set Port B to output
BCF RP0 ;Go back to register page 0

74 Microchip Code ©1998 Sirius microSystems


KEYSCAN.ASM - Chapter 9 Example Program

MOVF Key,0 ;Put value of Key into W


MOVWF PORTB ;and display on LEDs

Delay DECFSZ Counter1 ;3-level nested loop


GOTO Delay ;gives approx. 1/2 second delay
DECFSZ Counter2
GOTO Delay
DECFSZ Counter3
GOTO Delay

GOTO Initialize ;We’re done. Reset Port B and delay


;counters

Program Pull-Out
©1998 Sirius microSystems Microchip Code 75 References
KEYSCLB.ASM - Chapter 10 Example Program
;KEYSCLB.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; Col. 1 2 3 4
; Row +----+----+----+----+
; Port B.0----1---| 1 | 2 | 3 | 4 |
; +----+----+----+----+
; Port B.1----2---| 5 | 6 | 7 | 8 |
; +----+----+----+----+
; Port B.2----3---| 9 | 10 | 11 | 12 |
; +----+----+----+----+
; Port B.3----4---| 13 | 14 | 15 | 16 |
; +----+----+----+----+
; Port B.4----------+ | | |
; | | |
; Port B.5---------------+ | |
; | |
; Port B.6--------------------+ |
; |
; Port B.7-------------------------+
;
; This program demonstrates matrix keypad scanning using calls to an
; included subroutine library. It is functionally equivalent to the
; KEYSCAN.ASM program.
;
; The following description is from KEYSCAN.ASM. Port B.0-3 connect
; to the keypad rows and are set as outputs. Port B.4-7 connect to the
; keypad columns and are set as inputs with the internal pull-up
; resistors enabled. To read the keypad, a row is set low. While the
; row is low, each column input is examined. Columns normally are high
; because of the pull-up resistors. If a column is low, the key at that
; row-column intersection is pressed. If no column is found low, the
; program advances to the next row.
;
; When a key press is detected, that row-column combination assigns a
; number from 1-16 (according to the above diagram) to the Key variable.
; The binary value in the Key variable is displayed on the LEDs. Note
; that the same Port B pins have two functions: most of the time they
; are scanning the keypad, with Port B.4-7 as inputs and Port B.0-3 as
; outputs. When a key is pressed Port B is temporarily set to output to
; display the key value. The key will display for a short period of
; time. When a key is not pressed, you will notice the key scanning
; taking place.
;
; KEYSCLB.ASM differs from KEYSCAN.ASM in that the keypad port control
; and scanning routines are called from KEYPAD.LIB. Since all of the
; actual keypad logic is contained in the KEYPAD.LIB file, KEYSCLB.ASM
; is a much shorter source file than KEYSCAN.ASM. This makes program
; creation simpler, since a programmer needs only to concentrate on
; the ‘real’ logic of the program, and not the nitty-gritty details.
;
; Subroutine libraries often require variables to be defined. Variables
; described in the subroutine library need to be defined in the calling
; program. This way, all variable definitions reside in the calling

76 Microchip Code ©1998 Sirius microSystems


KEYSCLB.ASM - Chapter 10 Example Program
; program.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; If you are using the EPIC programmer and the In-Circuit programming
; cable, you must remove this cable from the PIC-MDS to ensure proper
; program execution. Otherwise, keys in column 4 will not be read.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘KSLB’

;Hardware Equates

Counter1 EQU 0Ch ;Delay counter register


Counter2 EQU 0Dh ;Delay counter register
Counter3 EQU 0Eh ;Delay counter register

;Equates required by KEYPAD.LIB


Key EQU 0Fh ;This register will hold a number from
;0-15 representing the last key pressed

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector

ORG 05h ;One location past Interrupt vector

Include ‘KEYPAD.LIB’ ;KEYPAD.LIB subroutines go here

Initialize CALL KB_Port ;Library call to initialize Port B for


;keypad input
CLRF Counter1 ;Clear delay loop counters
CLRF Counter2
MOVLW 08h ;Preload Counter3 delay loop counter
MOVWF Counter3 ;for 1/2 second delay

Main CALL KB_Scan ;Library call to scan keypad


MOVF Key,0 ;Load value of Key into W
BTFSC Z ;Check for no key
GOTO Main ;If Z set, no key so scan again

Dispkey BSF RP0 ;Select register page 1


CLRF TRISB ;Set Port B to output
BCF RP0 ;Go back to register page 0

MOVF Key,0 ;Put value of Key into W


MOVWF PORTB ;and display on LEDs

Delay DECFSZ Counter1 ;3-level nested loop


GOTO Delay ;gives approx. 1/2 second delay
DECFSZ Counter2
GOTO Delay

Program Pull-Out
©1998 Sirius microSystems Microchip Code 77 References
KEYSCLB.ASM - Chapter 10 Example Program
DECFSZ Counter3
GOTO Delay

GOTO Initialize ;We’re done. Reset Port B and delay


;counters

78 Microchip Code ©1998 Sirius microSystems


NVMEM.ASM - Chapter 13 Example Program
;NVMEM.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This program demonstrates how to use EEPROM.LIB to store important


; data in the PIC16F84’s non-volatile EEPROM memory. NVMEM simply
; displays the contents of the first four EEPROM memory locations on
; the LCD display and expects you to enter a 4-digit number from the
; keypad. This 4-digit number (which could represent a pass-code) is
; stored into EEPROM and a message indicating that you should remove
; power from the PIC-MDS is displayed. Remove power from the PIC-MDS,
; and upon powering up, the number you entered will be displayed.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; If you are using the EPIC programmer and the In-Circuit programming
; cable, you must remove this cable from the PIC-MDS to ensure proper
; program execution. Otherwise, keys in column 4 will not be read.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘NVME’

;Hardware Equates

ORG 0Ch ;Start of File register area

Counter DS 1 ;LCD character counter

Counter1 DS 1 ;LCD delay counter


Counter2 DS 1 ;LCD delay counter

Key DS 1 ;Key return code variable

Digit DS 1 ;ASCII digit counter variable

ORG 00h ;Start program at Reset Vector

Program Pull-Out
©1998 Sirius microSystems Microchip Code 79 References
NVMEM.ASM - Chapter 13 Example Program
CLRF Key ;Clear Key return variable
CLRF Counter1 ;and delay counters
CLRF Counter2
GOTO Initialize ;Continue with initialize routine

ORG 05h ;One location past Interrupt Vector

Include ‘EEPROM.LIB’ ;EEPROM subroutine library


Include ‘KEYPAD.LIB’ ;Keypad scanning subroutine library
Include ‘LCD.LIB’ ;LCD subroutine library

Initialize ;This subroutine initializes the LCD display and writes


;a message on to line 1 and ‘=’ on to line 2. The cursor
;is turned on to indicate where input will be shown.

CLRF Digit ;Clear digit counter


CALL LCD_Port ;Set up ports for LCD use
CALL LCD_Init ;Initialize LCD and clear screen
CALL Disp_Line1 ;Send first line message to LCD

Send_Old ;Reads EEPROM addresses 0-3 and writes the contents to the
;LCD display.

CLRF EEADR ;Select EEPROM address 00


:Loop CALL EE_Read ;Call EE_Read to place data into
MOVF EEDATA,0 ;EEDATA, and read EEDATA into W
CALL LCD_Data ;Copy W to LCD DDRAM
INCF EEADR ;Increment to next EEPROM address
MOVLW 04h ;Load W with number of data bytes
SUBWF EEADR,0 ;and compare with EEADR
BTFSS Z ;by checking Z
GOTO :Loop ;If not at EEADR 04, get next data

Line2 MOVLW LCDLine2 ;Load W with line 2 DDRAM address


CALL LCD_Reg ;and write to LCD
CALL Disp_Line2 ;Send second line message to LCD

MOVLW CursOn ;Load W with Cursor On command


CALL LCD_Reg ;and write to LCD

Get_New ;Wait for key presses and after a debounce delay stores the
;ASCII value of the current key codes in EEPROM memory from
;address 0-3.

CLRF EEADR ;Reset EEADR to the beginning


CALL KB_Port ;Configure Port B for keypad

Get_Key CALL KB_Scan ;Get Key return code


MOVF Key,0 ;Check Key return code
BTFSC Z ;for no key press (0=no key)
GOTO Get_Key ;If no key pressed, try again
CALL Delay_5ms ;Wait for key to settle
CALL Delay_5ms
CALL Delay_5ms
CALL Delay_5ms

CALL KB_Scan ;Read Key code after settling


MOVF Key,0 ;Read Key code into W
CALL Key_Remap ;and Remap key codes

MOVWF EEDATA ;Save new Key code in EEDATA


CALL EE_Write ;Write key data to current EEADR
CALL EE_Wait ;and wait for write to finish

CALL EE_Read ;Read current EEADR to check


;that EEDATA was written properly

CALL LCD_Port ;Configure Ports for LCD

80 Microchip Code ©1998 Sirius microSystems


NVMEM.ASM - Chapter 13 Example Program
MOVF EEDATA,0 ;Get saved Key code from EEPROM
CALL LCD_Data ;and display on LCD

CALL KB_Port ;Set Port B for keypad use


Wait CALL KB_Scan ;Scan keypad
MOVF Key,0 ;Check key for 0
BTFSS Z ;And if Z=1 key has been released
GOTO Wait ;Otherwise, wait for release
CALL Delay_5ms ;Wait for key to settle
CALL Delay_5ms
CALL Delay_5ms
CALL Delay_5ms

INCF EEADR ;Increment to next EEPROM address


MOVLW 04h ;Load W with number of data bytes
SUBWF EEADR,0 ;and compare with EEADR
BTFSS Z ;by checking Z
GOTO Get_Key ;If not at EEADR 04, get next data
CALL LCD_Port ;Reconfigure ports for LCD
MOVLW LCDLine1 ;Load W with line 1 DDRAM address
CALL LCD_Reg ;and write to LCD
CALL Disp_Done ;Display done message
SLEEP

Key_Remap ;Changes key codes into ASCII values.

ADDWF PCL ;Use old Key to offset PC


NOP ;No Key=0 code
RETLW 30h ;key 1 remapped to ASCII 30h ‘0’
RETLW 31h ;key 2 remapped to ASCII 31h ‘1’
RETLW 32h ;key 3 remapped to ASCII 32h ‘2’
RETLW 33h ;key 4 remapped to ASCII 33h ‘3’
RETLW 34h ;key 5 remapped to ASCII 34h ‘4’
RETLW 35h ;key 6 remapped to ASCII 35h ‘5’
RETLW 36h ;key 7 remapped to ASCII 36h ‘6’
RETLW 37h ;key 8 remapped to ASCII 37h ‘7’
RETLW 38h ;key 9 remapped to ASCII 38h ‘8’
RETLW 39h ;key 10 remapped to ASCII 39h ‘9’
RETLW 41h ;key 11 remapped to ASCII 41h ‘A’
RETLW 42h ;key 12 remapped to ASCII 42h ‘B’
RETLW 43h ;key 13 remapped to ASCII 43h ‘C’
RETLW 44h ;key 14 remapped to ASCII 44h ‘D’
RETLW 45h ;key 15 remapped to ASCII 45h ‘E’
RETLW 46h ;key 16 remapped to ASCII 46h ‘F’

Disp_Line1 ;Writes ‘Old Data: ‘ to the first line of the LCD


;display using LCD display library (LCD.LIB).

CLRF Counter ;Reset character counter


:Get_Char MOVF Counter,0 ;Get character offset into W
CALL Message1 ;use it to get character
IORLW 00h ;RETLW won’t affect flags so use OR to
BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Counter,1 ;Add 1 to Counter
GOTO :Get_Char ;Do it again for the next character

Message1 ADDWF PCL ;Offset program counter by adding W


RETLW ‘O’ ;Message1
RETLW ‘l’
RETLW ‘d’
RETLW ‘ ‘
RETLW ‘D’
RETLW ‘a’

Program Pull-Out
©1998 Sirius microSystems Microchip Code 81 References
NVMEM.ASM - Chapter 13 Example Program
RETLW ‘t’
RETLW ‘a’
RETLW ‘:’
RETLW ‘ ‘
RETLW 0 ;End of message

Disp_Line2 ;Writes ‘New Data: ‘ to the second line of the LCD


;display using LCD display library (LCD.LIB).

CLRF Counter ;Reset character counter


:Get_Char MOVF Counter,0 ;Get character offset into W
CALL Message2 ;use it to get character
IORLW 00h ;RETLW won’t affect flags so use OR to
BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Counter,1 ;Add 1 to Counter
GOTO :Get_Char ;Do it again for the next character

Message2 ADDWF PCL ;Offset program counter by adding W


RETLW ‘N’ ;Message2
RETLW ‘e’
RETLW ‘w’
RETLW ‘ ‘
RETLW ‘D’
RETLW ‘a’
RETLW ‘t’
RETLW ‘a’
RETLW ‘:’
RETLW ‘ ‘
RETLW 0 ;End of message

Disp_Done ;Writes ‘Power down now.’ to the first line of the LCD
;display using LCD display library (LCD.LIB).

CLRF Counter ;Reset character counter


:Get_Char MOVF Counter,0 ;Get character offset into W
MOVLW HI Message3 ;Move the High Byte of Message3
;location into W
MOVWF PCLATH ;and Move it into PCLATH
MOVLW Message3+1 ;Move message address + 1 into W
ADDWF Counter,0 ;Calculate offset address and
BTFSC C ;see if it overflows
INCF PCLATH ;If so, increment PCLATH
CALL Message3 ;Jump to the data table

IORLW 00h ;RETLW won’t affect flags so use OR to


BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Counter,1 ;Add 1 to Counter
GOTO :Get_Char ;Do it again for the next character

Message3 MOVWF PCL ;W contains low program counter


;byte and points to next location
;plus Counter offset
RETLW ‘P’
RETLW ‘o’
RETLW ‘w’
RETLW ‘e’
RETLW ‘r’
RETLW ‘ ‘
RETLW ‘d’
RETLW ‘o’
RETLW ‘w’
RETLW ‘n’

82 Microchip Code ©1998 Sirius microSystems


NVMEM.ASM - Chapter 13 Example Program
RETLW ‘ ‘
RETLW ‘n’
RETLW ‘o’
RETLW ‘w’
RETLW ‘.’
RETLW ‘ ‘
RETLW 0 ;End of message

Delay_5ms ;Delay loop used to initialize LCD

CLRF Counter1 ;Wipe first counter


MOVLW 1Ah ;Load W with timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;from constant, above
RETURN

Program Pull-Out
©1998 Sirius microSystems Microchip Code 83 References
OUTPUT.ASM - Chapter 5 Example Program
;OUTPUT.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This program demonstrates port output. It initializes all port B pins


; to be outputs and then places a pattern on port B to illuminate LEDs.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; This is a simple program that requires no prior setup.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘OUTP’

ORG 00h ;Reset Vector location


GOTO Initialize ;Start program after Interrupt vector

ORG 05h ;One location past Interrupt vector

Initialize BSF RP0 ;Select memory register page 1


CLRF TRISB ;Make Port B output by clearing TRISB
BCF RP0 ;Go back to register page 0

Main MOVLW 01010101b ;Move 01010101b into W and


MOVWF PORTB ;output pattern to LEDs on Port

Done SLEEP ;Stop executing the program

84 Microchip Code ©1998 Sirius microSystems


RECV232.ASM - Chapter 15 Example Program
;RECV232.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This program demonstrates serial port polling and software timed


; RS-232 signal reception. Serial characters are received at the serial
; header (H3), translated from RS-232 to TTL levels by the MAX232,
; and routed through the serial Transmit/Receive select jumper (JU5)
; to RA.4 on the PIC. Once characters are received, they are scrolled
; across the LCD display. RA.4 was chosen to receive serial characters
; because it can generate a TMR0 interrupt in response to a change in
; the signal level applied to it.
;
; To ensure accurate serial bit timing, use a crystal oscillator and
; not a ceramic resonator to generate the processor clock.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select RX

;Requirements

; An external RS-232 serial terminal or a computer with an appropriate


; connection to the PIC-MDS serial input header (H3). For testing we
; used a cable wired as follows:
;
; Computer DB-25 PIC-MDS
; Transmit pin 2 —> H3.3 - Rx
; Receive pin 3 —> H3.1 - Tx
; Ground pin 7 —> H3.2 - Gnd

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘232R’

;Hardware Equates

ORG 0Ch ;Start of File register area

;Counter equates
CharAddress DS 1 ;Holds current LCD DDRAM address
CharCounter DS 1 ;Counts characters before scrolling
Counter1 DS 1 ;Delay counter for Delay_5ms

Program Pull-Out
©1998 Sirius microSystems Microchip Code 85 References
RECV232.ASM - Chapter 15 Example Program
Counter2 DS 1 ;Delay counter for Delay_5ms

;Equates required by RS232RX.LIB


Counter DS 1 ;Bit delay counter
BitCounter DS 1 ;RS232 bit counter register
Receive DS 1 ;Received byte storage register

;Other equates
LCD_Length EQU 16 ;Number of characters per LCD line

ORG 00h ;Start program at Reset Vector

CALL LCD_Port ;Set up ports for LCD use


CALL LCD_Init ;Initialize LCD and clear screen
CALL Receive_Port ;Set RA.4 for serial input
GOTO Initialize ;Jump over interrupt vector

ORG 05h ;Program starts after interrupt vector

Include ‘LCD.LIB’ ;LCD subroutine library


Include ‘RS232RX.LIB’ ;RS-232 receive library

Initialize ;Prepare character counters and LCD for data

MOVLW LCD_Length ;Load W with number of LCD characters


MOVWF CharCounter ;and save in CharCounter
DECF CharCounter ;-1 from CharCounter to account for 0
MOVLW CursBlink ;Load W with constant to blink cursor
CALL LCD_Reg ;and write to LCD as a command

MOVLW LCDLine1 ;Load W with DDRAM address of line 1


MOVWF CharAddress ;and save in CharAddress variable
CALL LCD_Reg ;before writing it to the LCD

Main ;Receive serial characters in Receive buffer

CALL Receive_Wait ;Wait for and receive one serial byte

MOVF Receive,0 ;After receiving, check character for


BTFSC Z ;and error (Receive=00h)
GOTO Main ;If no character, wait again

LCD_Write ;Write the character in Receive buffer to LCD display

MOVF Receive,0 ;Move received character into W &


CALL LCD_Data ;write to current DDRAM address
INCF CharAddress ;Add 1 to DDRAM address counter
MOVLW 0A8h ;Load W with last DDRAM address +1
SUBWF CharAddress,0 ;and subtract from CharAddress
BTFSC Z ;to see if 40 characters are full
GOTO Line_Reset ;If so, reset LCD to start of line

MOVF CharCounter,1 ;Check Character counter for end


BTFSC Z ;of visible screen by checking Z
GOTO Scroll ;If at end, scroll display left
DECF CharCounter ;If not, decrement CharCounter
GOTO Main ;and wait for next character

Scroll ;Scroll display left to keep new characters in LCD window

MOVLW LCDLeft ;Load W with LCD shift left command


CALL LCD_Reg ;and send to LCD
GOTO Main ;Wait for next character

Line_Reset ;If 40 characters have been written to DDRAM, scroll the


;display contents left and reset DDRAM to line 1.

86 Microchip Code ©1998 Sirius microSystems


RECV232.ASM - Chapter 15 Example Program

MOVLW LCDLeft ;Load W with LCD shift left command


CALL LCD_Reg ;and write to LCD
MOVLW LCDLine1 ;Load W with first DDRAM address
MOVWF CharAddress ;and save in CharAddress register
CALL LCD_Reg ;before writing it to LCD
GOTO Main ;Wait for more serial data

Delay_5ms ;Delay loop used to initialize LCD

CLRF Counter1 ;Clear Counter1


MOVLW 1Ah ;Load W with timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;from constant, above
RETURN

Program Pull-Out
©1998 Sirius microSystems Microchip Code 87 References
SEETEST.ASM - Chapter 17 Example Program
;SEETEST.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
:at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; SEETEST is a utility to test and program 93LC56 (256 byte) and 93LC66
; (512 byte) serial EEPROMs (SEEPROMs) in the Sirius PICmicro Devemopment
; System. SEEPROM address and data are displayed in Hex on the top line of
; the LCD display. The lower line displays the prompts ‘Dwn Up Sel Chg’.
; The top row of buttons on the keypad acts as soft keys for the prompts
; on the LCD. Selecting the ‘Dwn’ or ‘Up’ buttons decrements or increments
; the SEEPROM address. For each address, the data stored at that address
; is displayed. Pressing ‘Sel’ allows you to enter a 3-digit address (000-
; 1FF) to view or change. Pressing ‘Chg’ allows you to enter a 2-digit hex
; byte into the current address.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select X8
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; If you are using the EPIC programmer and the In-Circuit programming
; cable, you must remove this cable from the PIC-MDS to ensure proper
; program execution. Otherwise, keys in column 4 will not be read.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84, HS_OSC, WDT_OFF, PROTECT_OFF, PWRT_ON


ID ‘SEET’

;Hardware Equates

ORG 0Ch ;Start of File register area

Digit DS 1 ;Hex digit register


Character DS 1 ;LCD message character offset
Counter1 DS 1 ;LCD delay/keystroke delay counter
Counter2 DS 1 ;LCD delay/keystroke delay counter
Delay DS 1 ;Keystroke delay duration
KeyTemp DS 1 ;Temporary Key register

Addrh DS 1 ;Temporary SEEPROM high address byte


Addrl DS 1 ;Temporary SEEPROM low address byte

88 Microchip Code ©1998 Sirius microSystems


SEETEST.ASM - Chapter 17 Example Program

;Equates required by KEYPAD.LIB

Key DS 1 ;Key return code variable

;Equates required by SEEPROM.LIB

SEEAddrh DS 1 ;SEEPROM high address byte


SEEAddrl DS 1 ;SEEPROM low address byte
SEEClock DS 1 ;SEEPROM clock counter register
SEEData DS 1 ;SEEPROM data storage byte

;Software Equates

Menu_Msg EQU 0 ;Menu message offset


Status_Msg EQU 16 ;Status display message offset
Addr_Msg EQU 31 ;”Enter Address” message offset
Data_Msg EQU 47 ;”Enter Data” message offset

Address EQU 5 ;Cursor offset for address display


Data EQU 14 ;Cursor offset for data display

ORG 00h ;Start program at Reset Vector

CLRF Key ;Clear Key return variable


CLRF Counter1 ;and delay counters
CLRF Counter2
GOTO Initialize ;Continue with initialize routine

ORG 05h ;One location past Interrupt Vector

Include ‘SEEPROM.LIB’ ;EEPROM subroutine library


Include ‘LCD.LIB’ ;LCD subroutine library
Include ‘KEYPAD.LIB’ ;Keypad scanning subroutine library

Initialize ;Continue setting variables and initialize the LCD display.

CLRF Digit ;Clear hex digit register


CLRF Addrl ;Clear program low and high address
CLRF Addrh ;bytes to set initial address to 000h

Update_Status ;Displays the current SEEPROM address and data on the top line
;of the LCD and the Menu options on the bottom line.

CALL LCD_Port ;Set up ports for LCD use


CALL LCD_Init ;Initialize LCD and clear screen
MOVLW LCDLine1 ;Send line 1 starting character
CALL LCD_Reg ;address to LCD
MOVLW Status_Msg ;Load W with Status message offset
CALL Disp_Message ;and call display message routine
MOVLW LCDLine1+Address ;Set LCD character position to
CALL LCD_Reg ;start of address display area
MOVF Addrh,W ;Load W with high address byte
ANDLW 0Fh ;Clear upper nybble
CALL Hex_Remap ;and convert to ASCII for LCD
CALL LCD_Data ;and display on LCD
MOVF Addrl,W ;Load W with low address byte
MOVWF Digit ;and save a copy in Digit register
SWAPF Digit,W ;Switch nybbles and copy to W
ANDLW 0Fh ;Clear upper nybble before
CALL Hex_Remap ;converting to ASCII for
CALL LCD_Data ;display on LCD

MOVF Addrl,W ;Load W with low address byte again


ANDLW 0Fh ;Clear upper nybble before

Program Pull-Out
©1998 Sirius microSystems Microchip Code 89 References
SEETEST.ASM - Chapter 17 Example Program
CALL Hex_Remap ;converting to ASCII for
CALL LCD_Data ;display on LCD

CALL SEE_Port ;Set up Port A for SEEPROM use


MOVF Addrl,W ;Copy low address byte to
MOVWF SEEAddrl ;SEEPROM low address byte
MOVF Addrh,W ;Copy high address byte to
MOVWF SEEAddrh ;SEEPROM high address byte
MOVLW SEERead ;Send SEEPROM Read byte command
CALL SEE_Command ;to SEEPROM

CALL LCD_Port ;Set up Ports for LCD use


MOVLW LCDLine1+Data ;Set LCD character position to
CALL LCD_Reg ;start of data display area
SWAPF SEEData,W ;Switch nybbles of SEEPROM data to W
ANDLW 0Fh ;Clear upper nybble before
CALL Hex_Remap ;converting to ASCII for
CALL LCD_Data ;display on LCD

MOVF SEEData,W ;Load W with SEEPROM data byte


ANDLW 0Fh ;Clear upper nybble before
CALL Hex_Remap ;converting to ASCII for
CALL LCD_Data ;display on LCD

MOVLW LCDLine2 ;Send LCD line 2 character address


CALL LCD_Reg ;to LCD as a command
MOVLW Menu_Msg ;Load W with Menu message offset
CALL Disp_Message ;and call display message routine

CALL KB_Port ;Set Port B for keypad use


CALL KB_Scan ;and scan keys for key press
MOVF Key,W ;Load Key return code into W
MOVWF KeyTemp ;and save in temporary register

MOVLW 01h ;Copy short key repeat delay into


MOVWF Delay ;Delay register

Wait_for_Key ;Waits for a top-row key press and determines the action that
;follows the key press.

CALL KB_Scan ;Get Key return code


MOVF Key,W ;Load Key code into W to set flags
BTFSC Z ;and check for 0 (0=no key)
GOTO Wait_for_Key ;If no key pressed, try again

:Key1 DECFSZ Key ;Check for Key=1 by subtracting


GOTO :Key2 ;If not 0, check for Key=2
MOVF KeyTemp,W ;Load W with previous key code
SUBLW 01h ;and check for equality with 1
BTFSC Z ;If not equal, key not held so skip
GOTO :Delay1 ;If equal, key held. Use short delay.
MOVLW 20h ;Copy long delay into
MOVWF Delay ;Delay register
:Delay1 CALL Repeat_Delay ;and wait for delay
CALL Addr_Down ;If 0, decrment SEEPROM address
GOTO Update_Status ;and redisplay Status screen

:Key2 DECFSZ Key ;Check for Key=2 by subtracting


GOTO :Key3 ;If not 0, check for Key=3
MOVF KeyTemp,W ;Load W with previous key code
SUBLW 02h ;and check for equality with 1
BTFSC Z ;If not equal, key not held so skip
GOTO :Delay2 ;If equal, key held. Use short delay.
MOVLW 20h ;Copy long delay into
MOVWF Delay ;Delay register
:Delay2 CALL Repeat_Delay ;and wait for delay
CALL Addr_Up ;If 0, increment SEEPROM address

90 Microchip Code ©1998 Sirius microSystems


SEETEST.ASM - Chapter 17 Example Program
GOTO Update_Status ;and redisplay Status screen

:Key3 DECFSZ Key ;Check for Key=3 by subtracting


GOTO :Key4 ;If not 0, check for Key=4
CALL Addr_Set ;If 0, allow user to set address
CALL KB_Port ;Set Port B for keypad use
CALL Key_Release ;and wait for all keys to be released
GOTO Update_Status ;Redisplay Status screen

:Key4 DECFSZ Key ;Check for Key=4 by subtracting


GOTO Wait_for_Key ;If not 0, ignore other keys
CALL Data_Set ;If 0, allow user to set data
CALL KB_Port ;Set Port B for keypad use
CALL Key_Release ;and wait for all keys to be released
GOTO Update_Status ;Redisplay Status screen

Addr_Down ;Decrements the current 9-bit SEEPROM address.

MOVF Addrl,1 ;Check Addrl for 0 by moving it onto


BTFSC Z ;itself and checking the Z flag
GOTO :Check_Addrh ;If Addrl is 0, check Addrh
DECF Addrl ;Otherwise, decrement Addrl and
RETURN ;return to calling program

:Check_Addrh MOVF Addrh,1 ;Check Addrh for 0 by moving it onto


BTFSC Z ;itself and checking the Z flag
RETURN ;If Addrh=0 & Addrl=0, don’t decrement
DECF Addrh ;Otherwise, decrement Addrh and
DECF Addrl ;Addrl before returning
RETURN

Addr_Up ;Increments the current 9-bit SEEPROM address.

INCF Addrl ;Increment Addrl and check for a


BTFSS Z ;roll-over to 0
RETURN ;If no roll-over, return
MOVF Addrh,1 ;Check Addrh for 0 by moving it onto
BTFSS Z ;itself and chekcing the Z flag
GOTO :Fix_Addrl ;If Addrl=0 & Addrh=1, decrement Addrl
INCF Addrh ;Otherwise, increment Addrh
RETURN ;and return

:Fix_Addrl DECF Addrl ;Decrement Addrl to highest possible


RETURN ;address of 1FF and return

Addr_Set ;Allows the user to enter the 9-bit SEEPROM Address.

CALL LCD_Port ;Set Port A and Port B for LCD use


MOVLW LCDLine2 ;Set LCD charcter position to line
CALL LCD_Reg ;two and send command to LCD
MOVLW Addr_Msg ;Load W with Address message offset
CALL Disp_Message ;and call display message routine

MOVLW LCDLine1+Address ;Set LCD character position to


CALL LCD_Reg ;start of address display area
MOVLW ‘?’ ;Load W with “?” character
CALL LCD_Data ;and send to LCD three times to
MOVLW ‘?’ ;indicate address entry field
CALL LCD_Data
MOVLW ‘?’
CALL LCD_Data
MOVLW LCDLine1+Address ;Set LCD character position to
CALL LCD_Reg ;start of address display area
MOVLW CursBlink ;and set blinking cursor
CALL LCD_Reg ;Send command to LCD

Program Pull-Out
©1998 Sirius microSystems Microchip Code 91 References
SEETEST.ASM - Chapter 17 Example Program

CLRF Addrh ;Clear high and low


CLRF Addrl ;SEEPROM address bytes
CALL KB_Port ;Set Port B for keypad use and
CALL Key_Release ;make sure that no keys are pressed
:Digit1 CALL KB_Scan ;Scan keys for a keystroke
MOVF Key,W ;Load Key into W to check for keypress
BTFSC Z ;and check Z flag
GOTO :Digit1 ;If Z=0, no key pressed. Scan again
CALL Key_Remap ;Convert key stroke to binary nybble
MOVWF Digit ;and save in Digit register
MOVF Digit,1 ;Reread Digit to set flags
BTFSC Z ;Check for Digit=0 by testing Z
GOTO :Store1 ;If Digit was 0, store & display it
DECF Digit,W ;Otherwise, check for Digit=1 by
BTFSS Z ;decrementing and checking Z
GOTO :Digit1 ;If not 0 or 1 wait for valid Digit

:Store1 CALL LCD_Port ;Set Port A and Port B for LCD use
MOVF Digit,W ;Copy saved Digit to
MOVWF Addrh ;Addrh register
CALL Hex_Remap ;and convert to ASCII value
CALL LCD_Data ;Display Digit code on LCD

CALL KB_Port ;Set Port B for keypad use and


CALL Key_Release ;make sure that no keys are pressed
:Digit2 CALL KB_Scan ;Scan keys for a keystroke
MOVF Key,W ;Load Key into W to check for keypress
BTFSC Z ;and check Z flag
GOTO :Digit2 ;If Z=0, no key pressed. Scan again
CALL Key_Remap ;Convert key stroke to binary nybble
MOVWF Digit ;Save result to Digit register and
MOVWF Addrl ;save in top of Addrl register
SWAPF Addrl,1 ;by swapping nybbles of Addrl
CALL LCD_Port ;Set Port A and Port B for LCD use
MOVF Digit,W ;Load W with Digit value
CALL Hex_Remap ;and convert to ASCII
CALL LCD_Data ;Display Digit code on LCD

CALL KB_Port ;Set Port B for keypad use and


CALL Key_Release ;make sure that no keys are pressed
:Digit3 CALL KB_Scan ;Scan keys for a keystroke
MOVF Key,W ;Load Key into W to check for keypress
BTFSC Z ;and check Z flag
GOTO :Digit3 ;If Z=0, no key pressed. Scan again
CALL Key_Remap ;Convert key stroke to binary nybble
MOVWF Digit ;Save result to Digit register and
IORWF Addrl ;save in bottom of Addrl
CALL LCD_Port ;Set Port A and Port B for LCD use
MOVLW CursOff ;Send LCD command to turn off
CALL LCD_Reg ;blinking cursor
MOVF Digit,W ;Load W with Digit value
CALL Hex_Remap ;and convert to ASCII
CALL LCD_Data ;Display Digit code on LCD

RETURN

Data_Set ;Allows the user to enter the 8-bit SEEPROM data.

CALL LCD_Port ;Set Port A and Port B for LCD use


MOVLW LCDLine2 ;Set LCD charcter position to line
CALL LCD_Reg ;two and send command to LCD
MOVLW Data_Msg ;Load W with Data message offset
CALL Disp_Message ;and call display message routine

MOVLW LCDLine1+Data ;Set LCD character position to


CALL LCD_Reg ;start of data display area

92 Microchip Code ©1998 Sirius microSystems


SEETEST.ASM - Chapter 17 Example Program
MOVLW ‘?’ ;Load W with “?” character
CALL LCD_Data ;and send to LCD two times to
MOVLW ‘?’ ;indicate data entry field
CALL LCD_Data
MOVLW LCDLine1+Data ;Reset LCD character position to
CALL LCD_Reg ;start of address display area
MOVLW CursBlink ;and set blinking cursor
CALL LCD_Reg ;Send command to LCD

CLRF SEEData ;Clear SEEPROM data byte


CALL KB_Port ;Set Port B for keypad use and
CALL Key_Release ;make sure that no keys are pressed
:Digit1 CALL KB_Scan ;Scan keys for a keystroke
MOVF Key,W ;Load Key into W to check for keypress
BTFSC Z ;and check Z flag
GOTO :Digit1 ;If Z=0, no key pressed. Scan again
CALL Key_Remap ;Convert key stroke to binary nybble
MOVWF Digit ;Save Key code in Digit register
MOVWF SEEData ;and also in top of SEEData register
SWAPF SEEData,1 ;by swapping nybbles of SEEData
CALL LCD_Port ;Set Port A and Port B for LCD use
MOVF DIgit,W ;Load W with Digit value
CALL Hex_Remap ;and convert to ASCII
CALL LCD_Data ;Display key code on LCD

CALL KB_Port ;Set Port B for keypad use and


CALL Key_Release ;make sure that no keys are pressed
:Digit2 CALL KB_Scan ;Scan keys for a keystroke
MOVF Key,W ;Load Key into W to check for keypress
BTFSC Z ;and check Z flag
GOTO :Digit2 ;If Z=0, no key pressed. Scan again
CALL Key_Remap ;Convert key stroke to binary nybble
MOVWF Digit ;Save Key code in Digit register
IORWF SEEData ;and save in bottom of SEEData
CALL LCD_Port ;Set Port A and Port B for LCD use
MOVLW CursOff ;Send LCD command to turn off
CALL LCD_Reg ;blinking cursor
MOVF Digit,W ;Load W with Digit value
CALL Hex_Remap ;and convert to ASCII
CALL LCD_Data ;Display key code on LCD

CALL SEE_Port ;Configure Port A for SEEPROM


MOVLW SEEEWEN ;Send Erase/Write Enable command
CALL SEE_Command ;to SEEPROM
MOVF Addrl,W ;Copy Addrl byte to
MOVWF SEEAddrl ;SEEAddrl
MOVF Addrh,W ;Copy Addrh byte to
MOVWF SEEAddrh ;SEEAddrh
MOVLW SEEWrite ;Send data write command
CALL SEE_Command ;to SEEPROM
MOVLW SEEEWDS ;Send Erase/Write Disable command
CALL SEE_Command ;to SEEPROM

RETURN

Key_Release ;Waits for the key to be released

CALL KB_Scan ;Scan keys for key press


MOVF Key,W ;Check Key return code for no key
BTFSS Z ;by checking for 0 (0=no key)
GOTO Key_Release ;If key pressed, try again
CALL Delay_5ms ;If key released, wait for debouncing
RETURN ;and return

Hex_Remap ;Changes binary nybble into ASCII Hex value.

Program Pull-Out
©1998 Sirius microSystems Microchip Code 93 References
SEETEST.ASM - Chapter 17 Example Program
MOVWF Character ;Store character offset

MOVLW HI Hex_Code ;Move the High Byte of Hex_Code


;address location into W
MOVWF PCLATH ;and into PCLATH
MOVLW Hex_Code+1 ;Move address + 1 into W
ADDWF Character,W ;Calculate offset address and
BTFSC C ;see if it overflows
INCF PCLATH ;If so, increment PCLATH
CALL Hex_Code ;Jump to the data table

RETURN ;and finish if done

Hex_Code MOVWF PCL ;Use Hex digit to offset PC


RETLW ‘0’ ;0000 remapped to ‘0’
RETLW ‘1’ ;0001 remapped to ‘1’
RETLW ‘2’ ;0010 remapped to ‘2’
RETLW ‘3’ ;0011 remapped to ‘3’
RETLW ‘4’ ;0100 remapped to ‘4’
RETLW ‘5’ ;0101 remapped to ‘5’
RETLW ‘6’ ;0110 remapped to ‘6’
RETLW ‘7’ ;0111 remapped to ‘7’
RETLW ‘8’ ;1000 remapped to ‘8’
RETLW ‘9’ ;1001 remapped to ‘9’
RETLW ‘A’ ;1010 remapped to ‘A’
RETLW ‘B’ ;1011 remapped to ‘B’
RETLW ‘C’ ;1100 remapped to ‘C’
RETLW ‘D’ ;1101 remapped to ‘D’
RETLW ‘E’ ;1110 remapped to ‘E’
RETLW ‘F’ ;1111 remapped to ‘F’

Key_Remap ;Changes key code into binary nybble.

MOVWF Character ;Store character offset

MOVLW HI Key_Code ;Move the High Byte of Hex_Code


;address location into W
MOVWF PCLATH ;and into PCLATH
MOVLW Key_Code+1 ;Move address + 1 into W
ADDWF Character,W ;Calculate offset address and
BTFSC C ;see if it overflows
INCF PCLATH ;If so, increment PCLATH
CALL Key_Code ;Jump to the data table

RETURN ;and finish if done

Key_Code MOVWF PCL ;Use Key code to offset PC


NOP ;No key 0
RETLW 01h ;Key 1 remapped to 0001
RETLW 02h ;Key 2 remapped to 0010
RETLW 03h ;Key 3 remapped to 0011
RETLW 0Ah ;Key 4 remapped to 1010
RETLW 04h ;Key 5 remapped to 0100
RETLW 05h ;Key 6 remapped to 0101
RETLW 06h ;Key 7 remapped to 0110
RETLW 0Bh ;Key 8 remapped to 1011
RETLW 07h ;Key 9 remapped to 0111
RETLW 08h ;Key 10 remapped to 1000
RETLW 09h ;Key 11 remapped to 1001
RETLW 0Ch ;Key 12 remapped to 1100
RETLW 0Eh ;Key 13 remapped to 1110
RETLW 00h ;Key 14 remapped to 0000
RETLW 0Fh ;Key 15 remapped to 1111
RETLW 0Dh ;Key 16 remapped to 1101

Disp_Message ;Copies ASCII data from a look-up table to the current cursor

94 Microchip Code ©1998 Sirius microSystems


SEETEST.ASM - Chapter 17 Example Program
;position of the LCD. Character is loaded with the starting
;offset of the message before calling this routine.

MOVWF Character ;Save offset in Character counter

:Get_Char MOVLW HI Message ;Move the High Byte of Message3


;location into W
MOVWF PCLATH ;and Move it into PCLATH
MOVLW Message+1 ;Move message address + 1 into W
ADDWF Character,W ;Calculate offset address and
BTFSC C ;see if it overflows
INCF PCLATH ;If so, increment PCLATH
CALL Message ;Jump to the data table

IORLW 00h ;RETLW won’t affect flags so use OR to


BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Character,1 ;Add 1 to Character
GOTO :Get_Char ;Do it again for the next character

Message MOVWF PCL ;W contains low program counter


;byte and points to next location
;plus Character offset

RETLW ‘ ‘ ;Menu_Msg Start


RETLW ‘D’
RETLW ‘w’
RETLW ‘n’
RETLW ‘ ‘
RETLW ‘U’
RETLW ‘p’
RETLW ‘ ‘
RETLW ‘S’
RETLW ‘e’
RETLW ‘l’
RETLW ‘ ‘
RETLW ‘C’
RETLW ‘h’
RETLW ‘g’
RETLW 0 ;End of message 1

RETLW ‘A’ ;Status_Msg Start


RETLW ‘d’
RETLW ‘d’
RETLW ‘r’
RETLW ‘:’
RETLW ‘ ‘
RETLW ‘ ‘
RETLW ‘ ‘
RETLW ‘ ‘
RETLW ‘D’
RETLW ‘a’
RETLW ‘t’
RETLW ‘a’
RETLW ‘:’
RETLW 0 ;End of message 2

RETLW ‘E’ ;Addr_Msg Start


RETLW ‘n’
RETLW ‘t’
RETLW ‘e’
RETLW ‘r’
RETLW ‘ ‘
RETLW ‘A’
RETLW ‘d’
RETLW ‘d’
RETLW ‘r’

Program Pull-Out
©1998 Sirius microSystems Microchip Code 95 References
SEETEST.ASM - Chapter 17 Example Program
RETLW ‘e’
RETLW ‘s’
RETLW ‘s’
RETLW ‘ ‘
RETLW ‘ ‘
RETLW 0 ;End of message 3

RETLW ‘E’ ;Data_Msg Start


RETLW ‘n’
RETLW ‘t’
RETLW ‘e’
RETLW ‘r’
RETLW ‘ ‘
RETLW ‘D’
RETLW ‘a’
RETLW ‘t’
RETLW ‘a’
RETLW ‘ ‘
RETLW ‘ ‘
RETLW ‘ ‘
RETLW ‘ ‘
RETLW ‘ ‘
RETLW 0 ;End of message 4

Delay_5ms ;Delay loop used to initialize LCD

CLRF Counter1 ;Wipe first counter


MOVLW 1Ah ;Load W with timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;from constant, above
RETURN

Repeat_Delay ;Long delay loop to for key repeat

CLRF Counter1 ;Wipe Counter1 and


:Set MOVLW 40h ;load W with preset
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement second counter
GOTO :Loop ;256 more times
CALL KB_Scan ;Scan Key codes for release
MOVF Key,W ;Load Key code into W and check
BTFSC Z ;for 0 (0=released)
RETURN ;If released, return early
DECFSZ Delay ;Decrement delay duration counter
GOTO :Set ;based on loaded Delay value
RETURN

96 Microchip Code ©1998 Sirius microSystems


TIMEOUT.ASM - Chapter 18 Example Program
;TIMEOUT.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This program demonstrates how to determine whether a MCLR or Watch Dog


; Timer (WDT) reset was responsible for re-starting program executing in
; the PICmicro. The LCD displays a message indicating the source of the
; reset, either MCLR or WDT. During normal processing the WDT is always
; being reset. By pressing and holding a key for 2-3 seconds, the WDT will
; time out, resetting the PICmicro. Use the reset button to restart the
; program.

; Note that this program also demonstrates a problem that may occur during
; the execution of WDT-enabled programs. Although a user typically presses
; and releases a key, pressing and holding a key in this program will
; cause an unintended reset. Make sure to verify the operation of programs
; that receive an unintended WDT reset!

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; This program has no special requirements.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_ON,PROTECT_OFF,PWRT_ON
ID ‘TOUT’

;Hardware Equates

ORG 0Ch ;Start of File register area

Character DS 1 ;LCD message character offset


Counter1 DS 1 ;LCD delay/keystroke delay counter
Counter2 DS 1 ;LCD delay/keystroke delay counter

;Equates required by KEYPAD.LIB

Key DS 1 ;Key return code variable

Program Pull-Out
©1998 Sirius microSystems Microchip Code 97 References
TIMEOUT.ASM - Chapter 18 Example Program

;Software Equates

Reset_Msg EQU 0 ;Reset source message offset


Pwr_Msg EQU 12 ;Power up message offset
WDT_Msg EQU 29 ;Watchdog timer message offset

ORG 00h ;Start program at Reset Vector

CLRF Key ;Clear Key return variable


CLRF Counter1 ;and delay counters
CLRF Counter2
GOTO Initialize ;Continue with initialize routine

ORG 05h ;One location past Interrupt Vector

Include ‘LCD.LIB’ ;LCD subroutine library


Include ‘KEYPAD.LIB’ ;Keypad scanning subroutine library

Initialize ;Continue by initializing the LCD display.

CALL LCD_Port ;Set up Ports for LCD use

BTFSS TO ;Check WDT Time Out flag and


GOTO WDT_Message ;skip WDT and LCD init if reset by WDT

Init_WDT CLRWDT ;Clear Watchdog Timer


BSF RP0 ;Select register page 1
MOVLW 0FFh ;Set Option register for WDT with
MOVWF Option ;1:128 prescaler (maximum prescaler)
BCF RP0 ;Return to register page 0

Init_LCD CALL LCD_Init ;Initialize LCD and clear screen


MOVLW LCDLine1 ;Send line 1 starting address
CALL LCD_Reg ;to LCD
MOVLW Reset_Msg ;Load W with Reset message offset
CALL Disp_Message ;and call display message routine
MOVLW LCDLine2 ;Send line 2 starting address
CALL LCD_Reg ;to LCD
MOVLW Pwr_Msg ;Load W with power up message offset
CALL Disp_Message ;and display it on line 2 of LCD
GOTO Wait_for_Key ;Continue with main program

WDT_Message MOVLW LCDLine2 ;Send line 2 starting address


CALL LCD_Reg ;to LCD
MOVLW WDT_Msg ;Load W with WDT message offset
CALL Disp_Message ;and display it on line 2 of LCD

Wait_for_Key ;Checks for a key press. If no keys are pressed, WDT is reset.

CALL KB_Port ;Set up Ports for keypad scanning


CALL KB_Scan ;Get Key return code
MOVF Key,W ;Load Key code into W to set flags
BTFSC Z ;and check for 0 (0=no key)
GOTO Reset_WDT ;If no key pressed, reset WDT

Key_Release ;Waits for the key to be released. If a key is held for 2-3
;seconds, the WDT will time out since there is not CLRWDT
;instruction inside this wait loop.

CALL KB_Scan ;Scan keys for key press


MOVF Key,W ;Check Key return code for no key
BTFSS Z ;by checking for 0 (0=no key)
GOTO Key_Release ;If key is held, check again

98 Microchip Code ©1998 Sirius microSystems


TIMEOUT.ASM - Chapter 18 Example Program

Reset_WDT ;Resets the WDT, setting the TO flag.

CLRWDT ;If no key pressed, clear Watchdog


GOTO Wait_for_Key ;and check for another key press

Disp_Message ;Copies ASCII data from a look-up table to the current cursor
;position of the LCD. Character is loaded with the starting
;offset of the message before calling this routine.

MOVWF Character ;Save offset in Character counter

:Get_Char MOVLW HI Message ;Move the High Byte of Message3


;location into W
MOVWF PCLATH ;and Move it into PCLATH
MOVLW Message+1 ;Move message address + 1 into W
ADDWF Character,0 ;Calculate offset address and
BTFSC C ;see if it overflows
INCF PCLATH ;If so, increment PCLATH
CALL Message ;Jump to the data table

IORLW 00h ;RETLW won’t affect flags so use OR to


BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Character,1 ;Add 1 to Character
GOTO :Get_Char ;Do it again for the next character

Message MOVWF PCL ;W contains low program counter


;byte and points to next location
;plus Character offset

RETLW ‘R’ ;Reset_Msg Start


RETLW ‘e’
RETLW ‘s’
RETLW ‘e’
RETLW ‘t’
RETLW ‘ ‘
RETLW ‘f’
RETLW ‘r’
RETLW ‘o’
RETLW ‘m’
RETLW ‘:’
RETLW 0 ;End of message 1

RETLW ‘P’ ;Pwr_Msg Start


RETLW ‘o’
RETLW ‘w’
RETLW ‘e’
RETLW ‘r’
RETLW ‘-’
RETLW ‘u’
RETLW ‘p’
RETLW ‘ ‘
RETLW ‘o’
RETLW ‘r’
RETLW ‘ ‘
RETLW ‘M’
RETLW ‘C’
RETLW ‘L’
RETLW ‘R’
RETLW 0 ;End of message 2

RETLW ‘W’ ;WDT_Msg Start


RETLW ‘a’
RETLW ‘t’
RETLW ‘c’

Program Pull-Out
©1998 Sirius microSystems Microchip Code 99 References
TIMEOUT.ASM - Chapter 18 Example Program
RETLW ‘h’
RETLW ‘d’
RETLW ‘o’
RETLW ‘g’
RETLW ‘ ‘
RETLW ‘t’
RETLW ‘i’
RETLW ‘m’
RETLW ‘e’
RETLW ‘r’
RETLW ‘!’
RETLW ‘!’
RETLW 0 ;End of message 3

Delay_5ms ;Delay loop used to initialize LCD

CLRF Counter1 ;Wipe first counter


MOVLW 1Ah ;Load W with timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;from constant, above
RETURN

100 Microchip Code ©1998 Sirius microSystems


VMETER.ASM - Chapter 16 Example Program
;VMETER.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
:at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This program demonstrates the use of the PIC16C711 A/D converter in a


; voltmeter type application. It samples the voltage on potentiometers
; RA0 and RA1 and displays the binary result as a decimal number on the
; LCD. The RA0 value is then scaled to 5V and displayed as a voltage on
; line 2 of the LCD while the RA1 value is converted into a bar-graph
; display on the LED Bar.
;
; Note: If you use a voltmeter to measure the voltage on RA0 and RA1
; while this program is running, you will not get the same results as
; on the display. The reason for this is that both RA0 and RA1 are
; multiplexed between being digital control lines for the LCD and analog
; inputs for the PIC. An oscilloscope will show the correct analog
; voltage between LCD writes.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 ON
; RA1 ON
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; None

Maclib ‘P71x.INC’ ;Library file for PIC16C711 and PM assembler


;Comment this line out for other assemblers

Device PIC16C711, HS_OSC, WDT_OFF, PROTECT_OFF, PWRT_ON


ID ‘VMET’

;Hardware Equates

ORG 0Ch ;Start of register file memory

Counter1 DS 1 ;LCD/A-D update delay counter


Counter2 DS 1 ;LCD/A-D update delay counter
Counter3 DS 1 ;A-D update delay counter
Character DS 1 ;LCD message character offset
Analog0 DS 1 ;Temporary Analog storage for chan. 0
Analog1 DS 1 ;Temporary Analog storage for chan. 1
Bargraph DS 1 ;Temporary storage for LED bar output

Program Pull-Out
©1998 Sirius microSystems Microchip Code 101 References
VMETER.ASM - Chapter 16 Example Program

;Equates used by BIN2BCD.LIB

HighByte DS 1 ;High byte of number


LowByte DS 1 ;Low byte of number

TenThous DS 1 ;Ten thousands BCD digit


ThouHund DS 1 ;Thousands & Hundreds BCD digit
TensOnes DS 1 ;Tens and Ones BCD digit

ShiftCounter DS 1 ;Counter for BCD conversion shifts

;Software Equates

Channel0_Msg EQU 0 ;’Ch.0:’ message offset


Channel1_Msg EQU 5 ;’Ch.1:’ message offset
Voltage_Msg EQU 10 ;’Ch.0 Voltage:’ message offset
Ch0_Data EQU 4 ;Channel 0 data cursor address
Ch1_Data EQU 12 ;Channel 1 data cursor address
Ch0_Volts EQU 10 ;Channel 0 voltage cursor address

ORG 00h ;Reset Vector

CLRF Counter1 ;Clear delay counters


CLRF Counter2
CLRF Counter3
GOTO Initialize ;Continue with initialization

ORG 05h ;One location past interrupt vector

Include ‘ATOD.LIB’ ;A-D conversion library


Include ‘LCD71.LIB’ ;LCD subroutine library
Include ‘BIN2BCD.LIB’ ;Binary to BCD conversion library

Initialize ;Sets up the LCD and writes messages to line 1 and line 2.

CALL LCD_Port ;Set up ports for LCD use


CALL LCD_Init ;Initialize LCD & clear screen
MOVLW LCDLine1 ;Send line 1 starting address to
CALL LCD_Reg ;to LCD as a command
MOVLW Channel0_Msg ;Load W with channel 0 message offset
CALL Disp_Message ;and call display message routine

MOVLW LCDLine1+8 ;Set LCD address to middle of line 1


CALL LCD_Reg ;and pass to LCD as a command
MOVLW Channel1_Msg ;Load W with channel 1 message offset
CALL Disp_Message ;and call display message routine

MOVLW LCDLine2 ;Send line 2 starting address to


CALL LCD_Reg ;to LCD as a command
MOVLW Voltage_Msg ;Load W with ch 0 voltage_msg offset
CALL Disp_Message ;and call display message routine

Main ;Configures A-D converter by initializing Port A to be


;analogue intsead of digital, setting the clock divider,
;and selecting the A-D channel.

CALL AD_Port ;Initialize A-D converter & Port A


MOVLW ADCLK32 ;Get clock divider for high speed
CALL AD_Clock ;from ATOD.lib and set A-D
MOVLW ADCH0 ;Get channel 0 constant and
CALL AD_Channel ;set A-D channel
MOVF Bargraph,W ;Display Bargraph value on LEDs while

102 Microchip Code ©1998 Sirius microSystems


VMETER.ASM - Chapter 16 Example Program
MOVWF PORTB ;waiting for next conversion

Call Delay_5ms ;Wait for track & hold to settle


CALL AD_Poll ;Start conversion, & wait until done
MOVF ADRES,W ;Load conversion result into W and
MOVWF Analog0 ;save in Analog0 for voltage display

MOVLW ADCH1 ;Get channel 1 constant and


CALL AD_Channel ;set A-D channel
MOVF Bargraph,W ;Display Bargraph value on LEDs while
MOVWF PORTB ;waiting for next conversion

CALL Delay_5ms ;Wait for track & hold to settle


CALL AD_Poll ;Start conversion, & wait until done
MOVF ADRES,W ;Load conversion result into W and
MOVWF Analog1 ;save in Analog1

CALL LCD_Port ;Reconfigure Ports for LCD use


MOVLW LCDLine1+Ch0_Data ;Send channel 0 data starting
CALL LCD_Reg ;address to LCD as a command
MOVF Bargraph,W ;Display Bargraph value on LEDs while
MOVWF PORTB ;waiting for BCD conversion
MOVF Analog0,W ;Load channel 0 result into W and
MOVWF LowByte ;save into LowByte register
CALL Display_Num ;Let Display_Num display BCD digits

MOVLW LCDLine1+Ch1_Data ;Send channel 1 data starting


CALL LCD_Reg ;address to LCD as a command
MOVF Bargraph,W ;Display Bargraph value on LEDs while
MOVWF PORTB ;waiting for bcd conversion
MOVF Analog1,W ;Load channel 1 result into W and
MOVWF LowByte ;save into LowByte register
CALL Display_Num ;Let Display_Num display BCD digits

MOVLW LCDLine2+Ch0_Volts ;Send channel 0 voltage starting


CALL LCD_Reg ;address to LCD as a command
MOVF Bargraph,W ;Display Bargraph value on LEDs while
MOVWF PORTB ;waiting for scaling
CALL Scale_Voltage ;Convert Ch.0 result to voltage and
CALL Display_Volts ;display the result on the LCD

MOVF Bargraph,W ;Display Bargraph value on LEDs while


MOVWF PORTB ;waiting for lookup
RRF Analog1 ;Divide channel 1 result by 2
RRF Analog1 ;again = divide by 4
RRF Analog1 ;again = divide by 8
RRF Analog1 ;again = divide by 16
RRF Analog1 ;again = divide by 32
MOVLW 07h ;Clear upper 5 bits of result by
ANDWF Analog1,W ;ANDing with zero, leave 3 bit result
CALL Bar_Table ;in W to look up 1 of 8 patterns
MOVWF PORTB ;Output LED pattern to LED bar
MOVWF Bargraph ;and to Bargraph register for update

CALL AD_Delay ;Wait to minimize display flicker


GOTO Main ;and do it again

Bar_Table ;Look-up table for bar graph display. Takes a number from
;0 to 7 and determins which LEDs should be on.

CLRF PCLATH ;Clear PCLATH before doing lookup


ADDWF PCL ;PCL=PCL+W to generate offset
RETLW 10000000b ;Bottom LED on
RETLW 11000000b ;Bottom 2 LEDs
RETLW 11100000b ;Bottom 3 LEDs
RETLW 11110000b ;Bottom 4 LEDs
RETLW 11111000b ;Bottom 5 LEDs

Program Pull-Out
©1998 Sirius microSystems Microchip Code 103 References
VMETER.ASM - Chapter 16 Example Program
RETLW 11111100b ;Bottom 6 LEDs
RETLW 11111110b ;Bottom 7 LEDs
RETLW 11111111b ;All LEDs on

Scale_Voltage ;Scales the result of the A/D conversion such that there are
;only 250 states instead of 256. This way the result can be
;multiplied by two to give a result from 0 to 500 representing
;a voltage of between 0.00 and 5.00 volts. For display, a
;decimal point is just inserted after the first digit by the
;Display_Volts subroutine.

MOVF Analog0,W ;Load W with the A/D result and


SUBLW 225 ;check if it’s greater than 225 by
BTFSS C ;testing the Carry flag
DECF Analog0 ;If so, subtract one from the result
MOVF Analog0,W ;Repeat the above process, comparing
SUBLW 175 ;the A/D result with successively
BTFSS C ;smaller values
DECF Analog0
MOVF Analog0,W
SUBLW 125
BTFSS C
DECF Analog0
MOVF Analog0,W
SUBLW 75
BTFSS C
DECF Analog0
MOVF Analog0,W
SUBLW 25
BTFSS C
DECF Analog0

CLRF HighByte ;Clear HighByte register for multiply


MOVF Analog0,W ;Reload W with scaled result and
MOVWF LowByte ;save result in LowByte register
BCF C ;Clear Carry before multiplying by 2
RLF LowByte ;Shift LowByte left to multiply
RLF HighByte ;Shift Carry into HighByte
CALL BIN_BCD ;and convert to BCD
RETURN ;Return when done

Display_Volts ;Displays the result of the BCD scaled voltage as a decimal


;number at the current LCD cursor address.

MOVF ThouHund,W ;Load thousands & hundreds digits in


ANDLW 0Fh ;W and clear thousands nybble
ADDLW 30h ;Add ASCII offset to generate number
CALL LCD_Data ;and display on LCD
MOVLW ‘.’ ;Load W with ASCII code for “.”
CALL LCD_Data ;and display on LCD
SWAPF TensOnes,W ;Load tens & ones digit in reverse
ANDLW 0Fh ;and clear ones nybble
ADDLW 30h ;Add ASCII offset to generate number
CALL LCD_Data ;and display on LCD
MOVF TensOnes,W ;Load tens and ones digits in
ANDLW 0Fh ;W and clear tens nybble
ADDLW 30h ;Add ASCII offset to generate number
CALL LCD_Data ;and display on LCD
MOVLW ‘V’ ;Load W with ASCII code for “V”
CALL LCD_Data ;and display on LCD
RETURN ;Return when done

Display_Num ;Converts the 8-bit A/D result to BCD and displays the
;hundreds, tens and ones digits on the LCD at the current
;LCD cursor address.

104 Microchip Code ©1998 Sirius microSystems


VMETER.ASM - Chapter 16 Example Program

CLRF HighByte ;Clear HighByte before converting


CALL BIN_BCD ;result to BCD
MOVF ThouHund,W ;Load thousands & hundreds digits in
ANDLW 0Fh ;W and clear thousands nybble
ADDLW 30h ;Add ASCII offset to generate number
CALL LCD_Data ;and display on LCD
SWAPF TensOnes,W ;Load tens & ones digit in reverse
ANDLW 0Fh ;and clear ones nybble
ADDLW 30h ;Add ASCII offset to generate number
CALL LCD_Data ;and display on LCD
MOVF TensOnes,W ;Load tens and ones digits in
ANDLW 0Fh ;W and clear tens nybble
ADDLW 30h ;Add ASCII offset to generate number
CALL LCD_Data ;and display on LCD
RETURN ;Return when done

Disp_Message ;Copies ASCII data from a look-up table to the current cursor
;position of the LCD. Character is loaded with the starting
;offset of the message before calling this routine.

MOVWF Character ;Save offset in Character counter

:Get_Char MOVLW HI Message ;Move the High Byte of Message3


;location into W
MOVWF PCLATH ;and Move it into PCLATH
MOVLW Message+1 ;Move message address + 1 into W
ADDWF Character,W ;Calculate offset address and
BTFSC C ;see if it overflows
INCF PCLATH ;If so, increment PCLATH
CALL Message ;Jump to the data table

IORLW 00h ;RETLW won’t affect flags so use OR to


BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Character,1 ;Add 1 to Character
GOTO :Get_Char ;Do it again for the next character

Message MOVWF PCL ;W contains low program counter


;byte and points to next location
;plus Character offset

RETLW ‘C’ ;Channel0_Msg Start


RETLW ‘h’
RETLW ‘0’
RETLW ‘:’
RETLW 0 ;End of message 1

RETLW ‘C’ ;Channel1_Msg Start


RETLW ‘h’
RETLW ‘1’
RETLW ‘:’
RETLW 0 ;End of message 2

RETLW ‘C’ ;Voltage_Msg Start


RETLW ‘h’
RETLW ‘0’
RETLW ‘ ‘
RETLW ‘V’
RETLW ‘o’
RETLW ‘l’
RETLW ‘t’
RETLW ‘s’
RETLW ‘:’
RETLW 0 ;End of message 2

Program Pull-Out
©1998 Sirius microSystems Microchip Code 105 References
VMETER.ASM - Chapter 16 Example Program

AD_Delay ;25ms delay between A-D conversions.

MOVLW 5 ;Load Counter3 with number of times


MOVWF Counter3 ;to execute 5ms LCD delay loop

:Loop CALL Delay_5ms ;Wait 5 ms


DECFSZ Counter3 ;Decrement counter 3 and check for 0
GOTO :Loop ;If not 0, wait again
RETURN ;otherwise, return

Delay_5ms ;Delay loop used to initialize LCD.

CLRF Counter1 ;Wipe first counter


MOVLW 1Ah ;Load W with timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement second counter
GOTO :Loop ;from constant, above
RETURN

106 Microchip Code ©1998 Sirius microSystems


WDTIMER.ASM - Chapter 18 Example Program
;WDTIMER.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This program demonstrates the use of the Watch Dog Timer (WDT) to wake
; the PICmicro from Sleep in order to continue processing. This is useful
; in reducing power consumption while periodically resuming processing
; without using interrupts. By putting the PICmicro to Sleep, the WDT does
; not reset the microcontroller. This is demonstrated by clearing the
; Wake_Upx counters during a reset, but not during the WDT wake up (See
; the data sheets for more information).
;
; The program displays a 16-bit count indicating the number of times that
; the PICmicro has been awakened since the last reset. The display also
; indicates whether the PICmicro is Sleeping or Processing.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select N/A

;Requirements

; This program has no special requirements.

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_ON,PROTECT_OFF,PWRT_ON
ID ‘WDTM’

;Hardware Equates

ORG 0Ch ;Start of File register area

Character DS 1 ;LCD message character offset


Counter1 DS 1 ;LCD delay/keystroke delay counter
Counter2 DS 1 ;LCD delay/keystroke delay counter
Wake_UpH DS 1 ;Wake-up event counter high byte
Wake_UpL DS 1 ;Wake-up event counter low byte

;Equates required by BIN2BCD.LIB

TenThous DS 1 ;Ten thousands register

Program Pull-Out
©1998 Sirius microSystems Microchip Code 107 References
WDTIMER.ASM - Chapter 18 Example Program
ThouHund DS 1 ;Thousands and hundreds register
TensOnes DS 1 ;Tens and ones register
HighByte DS 1 ;High byte of binary number
LowByte DS 1 ;Low byte of binary number
ShiftCounter DS 1 ;BCD shift counter

;Software Equates

Wake_Up_Msg EQU 0 ;Wake-up message offset


Sleep_Msg EQU 11 ;Sleeping message offset
Proc_Msg EQU 22 ;Processing message offset

Wake_Ups EQU 8Bh ;Wake-up counter position on LCD

ORG 00h ;Start program at Reset Vector

CLRF ShiftCounter ;Clear BCD shift counter


CLRF Counter1 ;and delay counters
CLRF Counter2
GOTO Initialize ;Continue with initialize routine

ORG 05h ;One location past Interrupt Vector

Include ‘LCD.LIB’ ;LCD subroutine library


Include ‘BIN2BCD.LIB’ ;Binary to BCD conversion library

Initialize ;Continue by initializing the LCD display.

CLRF Wake_UpH ;Continue clearing registers


CLRF Wake_UpL
CALL LCD_Port ;Set up Ports for LCD use

Init_WDT CLRWDT ;Clear Watchdog Timer


BSF RP0 ;Select register page 1
MOVLW 0FEh ;Set Option register for WDT with
MOVWF Option ;1:64 prescaler
BCF RP0 ;Return to register page 0

Init_LCD CALL LCD_Init ;Initialize LCD and clear screen


MOVLW LCDLine1 ;Send line 1 starting address
CALL LCD_Reg ;to LCD
MOVLW Wake_Up_Msg ;Load W with Wake-up message offset
CALL Disp_Message ;and call display message routine

Main MOVLW LCDLine2 ;Send line 2 starting address


CALL LCD_Reg ;to LCD
MOVLW Proc_Msg ;Load W with Processing message offset
CALL Disp_Message ;and display it on line 2 of LCD

MOVLW 1 ;Increment Wake-Up counter low byte


ADDWF Wake_UpL ;using Add instruction
BTFSC C ;Check Carry for roll-over
INCF Wake_UpH ;and increment high byte if set

MOVF Wake_UpL,W ;Copy Wake-Up counters to LowByte and


MOVWF LowByte ;HighByte for BCD conversion
MOVF Wake_UpH,W
MOVWF HighByte

CALL Bin_BCD ;Convert to BCD

MOVLW Wake_Ups ;Send starting address of wake-up


CALL LCD_Reg ;counter to LCD
MOVF TenThous,W ;Load W with lower nybble of
ANDLW 0Fh ;Ten thousands digit

108 Microchip Code ©1998 Sirius microSystems


WDTIMER.ASM - Chapter 18 Example Program
ADDLW 30h ;Convert it to ASCII and
CALL LCD_Data ;display it on the LCD

SWAPF ThouHund,W ;Load W with upper nybble of


ANDLW 0Fh ;thousands and hundreds digits
ADDLW 30h ;Convert it to ASCII and
CALL LCD_Data ;display it on the LCD

MOVF ThouHund,W ;Load W with lower nybble of


ANDLW 0Fh ;thousands and hundreds digit
ADDLW 30h ;Convert it to ASCII and
CALL LCD_Data ;display it on the LCD

SWAPF TensOnes,W ;Load W with upper nybble of


ANDLW 0Fh ;tens and ones digit
ADDLW 30h ;Convert it to ASCII and
CALL LCD_Data ;display it on the LCD

MOVF TensOnes,W ;Load W with lower nybble of


ANDLW 0Fh ;tends and ones digit
ADDLW 30h ;Convert it to ASCII and
CALL LCD_Data ;display it on the LCD

MOVLW LCDLine2 ;Send line 2 starting address


CALL LCD_Reg ;to LCD
CALL Delay_5ms ;Add a 20ms pause to see Processing mesg
CALL Delay_5ms
CALL Delay_5ms
CALL Delay_5ms

MOVLW Sleep_Msg ;Load W with Sleeping message offset


CALL Disp_Message ;and display it on line 2 of LCD

SLEEP ;Sleep until WDT expires


NOP ;
GOTO Main ;On WDT wake-up, display next count

Disp_Message ;Copies ASCII data from a look-up table to the current cursor
;position of the LCD. Character is loaded with the starting
;offset of the message before calling this routine.

MOVWF Character ;Save offset in Character counter

:Get_Char MOVLW HI Message ;Move the High Byte of Message3


;location into W
MOVWF PCLATH ;and Move it into PCLATH
MOVLW Message+1 ;Move message address + 1 into W
ADDWF Character,0 ;Calculate offset address and
BTFSC C ;see if it overflows
INCF PCLATH ;If so, increment PCLATH
CALL Message ;Jump to the data table

IORLW 00h ;RETLW won’t affect flags so use OR to


BTFSC Z ;check for end of message
RETURN ;and finish if done
CALL LCD_Data ;If not done, send character to LCD
INCF Character,1 ;Add 1 to Character
GOTO :Get_Char ;Do it again for the next character

Message MOVWF PCL ;W contains low program counter


;byte and points to next location
;plus Character offset

RETLW ‘W’ ;Wake-up_Msg Start


RETLW ‘a’
RETLW ‘k’
RETLW ‘e’

Program Pull-Out
©1998 Sirius microSystems Microchip Code 109 References
WDTIMER.ASM - Chapter 18 Example Program
RETLW ‘-’
RETLW ‘u’
RETLW ‘p’
RETLW ‘ ‘
RETLW ‘#’
RETLW ‘:’
RETLW 0 ;End of message 1

RETLW ‘S’ ;Sleep_Msg Start


RETLW ‘l’
RETLW ‘e’
RETLW ‘e’
RETLW ‘p’
RETLW ‘i’
RETLW ‘n’
RETLW ‘g’
RETLW ‘ ‘
RETLW ‘ ‘
RETLW 0 ;End of message 2

RETLW ‘P’ ;WDT_Msg Start


RETLW ‘r’
RETLW ‘o’
RETLW ‘c’
RETLW ‘e’
RETLW ‘s’
RETLW ‘s’
RETLW ‘i’
RETLW ‘n’
RETLW ‘g’
RETLW 0 ;End of message 3

Delay_5ms ;Delay loop used to initialize LCD

CLRF Counter1 ;Wipe first counter


MOVLW 1Ah ;Load W with timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;from constant, above
RETURN

110 Microchip Code ©1998 Sirius microSystems


XMIT232.ASM - Chapter 15 Example Program
;XMIT232.ASM v1.2 Last modified on August 31, 1998

;These program subroutines were written for the Sirius microSystems PICmicro
;development system. For more information contact Sirius microSystems by phone
;at 519-886-4462, or on the Internet at http://www.siriusmicro.com .

;Sirius microSystems provides this software on an “as is” basis, without any
;warranty, either expressed or implied. All Sirius microSystems software is
;provided for educational use only, and Sirius microSystems does not assume
;any liability for damages, either incidental or consequential, arising out of
;the application, use, or misuse of any of its software or hardware products.
;Sirius microSystems reserves the right, without further notice, to make
;changes to any of its software or hardware referred to in this program or
;library program in order to improve its function, design or reliability.

;Description

; This program demonstrates software timed RS-232 signal transmission.


; The keypad is scanned and whenever a key is pressed, the key return
; code along with some text is transmitted through H3, the serial
; header. The MAX232 translates the signal on RA.4 to RS-232 levels
; after it passes through the serial Transmit/Receive select jumper
; (JU5).
;
; To ensure accurate serial bit timing, use a crystal oscillator and
; not a ceramic resonator to generate the processor clock.

;Jumper Settings

; JU2 5VDC internal/external select REG


; JU1 Variable DC internal/external select REG
; JU3 Processor power select jumper RUN
; JU4 EEPROM X8/X16 organization select N/A
; JU6 Port A LED output and analog input RA0 OFF
; RA1 OFF
; RA2 ON
; RA3 OFF
; RA4 OFF
; JU5 RS-232 receive/transmit select TX

;Requirements

; An external RS-232 serial terminal or a computer with an appropriate


; connection to the PIC-MDS serial input header (H3). For testing we
; used a cable wired as follows:
;
; Computer DB-25 PIC-MDS
; Transmit pin 2 —> H3.3 - Rx
; Receive pin 3 —> H3.1 - Tx
; Ground pin 7 —> H3.2 - Gnd

Maclib ‘PF8x.INC’ ;Library file for PIC16F84 and PM assembler


;Comment this line out for other assemblers

Device PIC16F84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_ON
ID ‘232T’

;Hardware Equates

ORG 0Ch ;Start of File register area

;Equates required by BIN2DEC.LIB:


Hundreds DS 1 ;Hundreds digit
Tens DS 1 ;Tens digit
Ones DS 1 ;Ones digit

;Equates required by KEYPAD.LIB:

Program Pull-Out
©1998 Sirius microSystems Microchip Code 111 References
XMIT232.ASM - Chapter 15 Example Program
Key DS 1 ;Key return code register

;Equates required by RS232TX.LIB:


Counter DS 1 ;Serial bit delay counter
BitCounter DS 1 ;RS232 bit counter register
Transmit DS 1 ;Transmit byte storage register

;Other equates:
CharCounter DS 1 ;Message character counter
Counter1 DS 1 ;Delay counter variable
Counter2 DS 1 ;Delay counter variable

ORG 00h ;Start program at Reset Vector

CALL Transmit_Port ;Configure PortA.4 as serial output


CALL KB_Port ;Configure Port B for keypad scanning
GOTO Get_Key ;Jump over interrupt vector

ORG 05h ;Program starts after interrupt vector

Include ‘BIN2DEC.LIB’ ;Binary to decimal conversion library


Include ‘KEYPAD.LIB’ ;Keypad scanning subroutine library
Include ‘RS232TX.LIB’ ;RS232 serial transmission library

Get_Key ;Wait for a key stroke, debounce it and convert it to three


;decimal digits.

CALL KB_Scan ;Get Key return code


MOVF Key,0 ;Check Key return code
BTFSC Z ;for no key press (0=no key)
GOTO Get_Key ;If no key pressed, try again

CALL Delay ;Wait for key to settle


CALL KB_Scan ;Read Key code after settling
MOVF Key,0 ;Read Key code into W
CALL Bin_Dec ;and convert to decimal

Convert_ASCII ;Add 30h to offset the BCD numbers into ASCII.

MOVLW 30h ;Load ASCII offset into W and


ADDWF Tens ;add to Tens and
ADDWF Ones ;Ones registers to make ASCII numbers

Transmit_Key ;Transmit the word ‘Key ‘

MOVLW ‘K’ ;Load W with ASCII code for ‘K’ and


CALL Transmit_Data ;send out of serial port
MOVLW ‘e’ ;Load W with ASCII code for ‘K’ and
CALL Transmit_Data ;send out of serial port
MOVLW ‘y’ ;Load W with ASCII code for ‘K’ and
CALL Transmit_Data ;send out of serial port
MOVLW ‘ ‘ ;Load W with ASCII code for ‘K’ and
CALL Transmit_Data ;send out of serial port

Transmit_Num ;Transmit the two key return code ASCII digits.

MOVF Tens,0 ;Load W with ASCII Tens digit and


CALL Transmit_Data ;send out of serial port
MOVF Ones,0 ;Load W with ASCII Ones digit and
CALL Transmit_Data ;send out of serial port

Transmit_Mesg ;Transmit the word ‘ Pressed’, followed by the character


;codes for carriage return (13) and line feed (10).

CLRF CharCounter ;Clear message character counter


Get_Char MOVF CharCounter,0 ;Get current character count in W
CALL Message ;and retrieve message character

112 Microchip Code ©1998 Sirius microSystems


XMIT232.ASM - Chapter 15 Example Program
MOVWF Transmit ;Store returned character in Transmit
MOVF Transmit,1 ;and check transmit for end of
BTFSC Z ;message marker by checking Z
GOTO Wait ;If message done, wait for key release
CALL Transmit_Data ;If not, send current character
INCF CharCounter ;Increment the character counter
GOTO Get_Char ;and get the next character

Wait ;Wait until the user releases the pressed key.

CALL KB_Scan ;Scan keypad


MOVF Key,0 ;Check key for 0
BTFSS Z ;And if Z=1 key has been released
GOTO Wait ;Otherwise, wait for release
CALL Delay ;Wait for key to settle
GOTO Get_Key ;Wait for next key

Message ADDWF PCL ;Offset program counter by W


RETLW ‘ ‘ ;to Return Message characters
RETLW ‘P’
RETLW ‘r’
RETLW ‘e’
RETLW ‘s’
RETLW ‘s’
RETLW ‘e’
RETLW ‘d’
RETLW 13 ;Carriage Return character
RETLW 10 ;Line Feed character
RETLW 0 ;End of Message marker

Delay ;Provides a debounce delay for the keypad.

CLRF Counter1 ;Wipe first counter


MOVLW 80h ;Load W with timer Constant
MOVWF Counter2 ;for Counter2

:Loop DECFSZ Counter1,1 ;Decrement first counter


GOTO :Loop ;256 times
DECFSZ Counter2,1 ;Decrement, second counter
GOTO :Loop ;from constant, above
RETURN

Program Pull-Out
©1998 Sirius microSystems Microchip Code 113 References
114 Microchip Code ©1998 Sirius microSystems

Vous aimerez peut-être aussi