PIC LAB Project Experiments 1 To 12

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

http://www.talkingelectronics.

com/

PIC LAB-1
P1 - top half of page!

Go to "21" a strategy game

     
 

Where to start?
This site is enormous. It's equivalent to over 100 text-book
pages. Start by glancing through it quickly and come back. You
will then have some idea of its content and how it will help you
with PIC programming.  It's the most advanced course ever-
devised, taking you from the absolute beginning and supplying
everything you need to get into programming. 
After a quick read-through you will see the photos of the PIC
LAB-1 project, the Multi Chip Programmer, the programming
files the range of experiments as well as the other modules in
the series.
You can then settle down for the absorption-process.

1
Do not use: EditPad. Your program will not assemble!!

This project is not only for experimenting. It can be programmed as


a module for counting, displaying or detecting a number of
quantities and the extra-pages section (pages 6 to 19+) shows how
to adapt the board (and add extra circuitry) to create very
impressive projects.
The concept of this project is very powerful. It outstrips anything
similar using a PIC16F84 chip in a "stand-alone" module.
We have a new module on the drawing board using the upgraded
version of the '84 - the PIC16F628, with experiments to cover the
features of the PIC16F628.
Another module is called PIC Lick-1. As the name implies, it licks
anything you have seen to date; in size, price and capability. It has
zero overhead, no loss of features and can be used directly in a
wide range of products. Anything you design with it can be
implemented at the lowest cost possible.
Then there's PIC Robot-1. A small module with 3 inputs (two
amplifiers for sonic direction-finding) and one amplifier for infrared
control via a TV remote control. Two H-bridges provide
forward/reverse for two motors. It's designed to fit any wheeled
vehicle you provide.
Register your email address and you will be informed when new
projects are added.

This project covers two fronts. It provides a totally new design for
constructors as well as covering a large amount of electronics
theory. The project is full and complete on this site but if you want
additional theory, it is provided in our BEC course, in the Library of
Routines as well as PIC Programming. 

MODIFICATIONS
Modifications will be posted here
 MOD 1: Take the 47k microphone load resistor to the 4v2 produced
by the two green LEDs. This can be done on the underside of the
board. 

Click for the PIC Micro Webring

LIST OF EXPERIMENTS
All the files for the experiments are contained in:   .hex
or individual files:      Expmts-all
Experiment 1 Turning on a LED
Experiment 1a LED on for 0.5sec - without debounce
Experiment 1b LED on for 0.5sec - with debounce
Experiment 1c Two pushes to turn LED on for 0.5sec
Experiment 1d LED turns on for 0.5sec after button released
Experiment 1e LED ON for 0.5s more than button-press time
Experiment 1f Flash a LED
Experiment 2 Toggle a LED

2
Experiment 3 Running LEDs
Experiment 4 Counting on the 7-segment display
Experiment 4a Binary Counting
Experiment 4b Binary Counting - up/down
Experiment 4c Letters on 7-segment display
Experiment 4d Displaying WORDS
Experiment 4e Push "A" to display a word
Experiment 5 Creating a tone
Experiment 6 Creating a tune
Experiment 7 Siren Sound
Experiment 7a Hee Haw Sound
Experiment 8 A to D Conversion
Experiment 8a Measuring Resistance
Experiment 9 Pulse Detection with a coil
Experiment 10 Temperature Detection
Experiment 11 Sound Detection
Experiment 11a Sound-to-Frequency
Experiment 11b Whistle-On  Whistle-Off
Experiment 12 Light Detection
"21 Matches" A strategy game  - shows the power of programming.
The following pages of  experiments, theory and expansions are on
our pay-site. More details can be found HERE
Page 6 The Piezo diaphragm as an input and output device
Page 7 NITINOL wire
Page 8 Poling - looking at an input
Page 9 3-digit Counter   A-to-D Converter - Measuring Resistance
Pages 10a,b,c,d Library of Routines. This is the secret behind our 
"Cut-and-Paste" concept to create your own programs.
Page 11 Timing and Delays. Creating a program to control up to 8
devices.
Page 12 Adding extra inputs and outputs
Page 13 Advanced Programming and Clever Commands
Page 14 Test 1 on basic electronics for the PIC LAB-1  
Page 15 Test 2 on basic electronics for the PIC LAB-1
Page 16 Test 3 on basic programming
Page 17 Test 4 on programming
Page 18 Test 5 on programming
Page 19 Selecting programs via the scale around a pot. 
 
Rock, Paper, Scissors. A game showing how to create "effects"
 
This is a joint project from POPTRONICS magazine, and POPTRONICS
Interactive Edition. It is  presented by Colin Mitchell Editor,
POPTRONICS Interactive Edition. 

3
The 5 Input devices and the PIC LAB-1 complete
The 5 input devices are: diode, 10k pot, microphone, coil, photo transistor, 

This is our first project to span two media. It is designed around the "beginners" PIC chip, the PIC16F84 and
is the first project you should build (after a PIC programmer) if you want to learn how a PIC microcontroller
works.
PIC LAB-1 article is fairly large in content. Due to the limitation of space in the magazine POPTRONICS, the
outline has been presented on the printed page, while the full article is here, on the website. 
That's one of the advantages of the web, the page is endless. And that's exactly what we need when
producing an instructional article like this.  
Over 25 experiments have been prepared to cover the basic concepts of programming and the interfacing of
a number of devices. 
There are lots of other advantages of the web, including the ease of downloading text and programs for
burning into the chip. 
The experiments can be pasted into your text editor without the time-consuming task of typing.
This is a new concept and we are sure it will continue in the future.
Another big advantage is linkability. Throughout the article we will be providing links to data, information and
theory. Some of these links will take you to POPTRONICS Interactive Edition, the pay-per-issue e-
magazine that supports this site. Click HERE to subscribe.
The enormous amount of work that goes into the presentation of the FREE projects section is covered by
readers who subscribe to the e-magazine as well as those who purchase the kits for each project. If you want
to succeed in this area, you will need to be involved in the practical side by building the project and carrying
out programming.  
You are invited to subscribe and also click the button below to buy a kit and join the thousands of readers
who have purchased a kit from Talking Electronics. 
All the articles, kits and electronics courses provided by Talking Electronics have been  presented in a
completely different way to anything you have seen before. 
Everything fits together to create an enormous educational encyclopedia to get you from the beginning of
electronics to a level that can make you readily employable. 
We have documentary proof where readers have skipped over more than 50 other applicants by merely
stating they had read Talking Electronics books and built a number of their projects. By taking some of our
projects to the interview, your acceptance is virtually guaranteed. 
Take this project as a typical example. After studying the PIC LAB-1 project and carrying out the
experiments, you will be capable of writing your own programs and understanding how to interface devices to
a microcontroller. Showing this type of project, with a laboratory book of say 25 -30 experiments and
explaining your understanding of the concepts, will advance your presentation at least three rungs up the
ladder of acceptance.   
A special Readers Experiments section has been provided on the site map above, where you can add
4
projects you have created for PIC LAB-1.  Simply email them to Colin Mitchell. 
This project is only the beginning. Its potential is almost limitless and it's up to you to create your own
programs and ideas.

Now for the article . . .

But just before we start, I received an email outlining a program that helps programmers write a program via
ICONS. Read my comments about this program HERE.

If you have ever wondered where to start with PIC microcontrollers, this is it. 

Lots of PIC Programmers and projects using PIC chips have been presented in books and magazines, but
nothing in the middle - nothing to help the beginner DEVELOP A PROJECT.  
PIC LAB-1 shows you how to create programs that collect information from the outside world and display it
on an output device.
It uses the "beginners" microcontroller, a PIC16F84. This chip can be re-programmed about 1,000 times and
is ideal for developing a project.  
Projects such as code locks, robot control, vending machine applications, monitoring, motor control,
animation, displays, tones, tunes, invalid aids, games and signaling are just a few ideas that are ideal for this
chip.  
But before you can launch into writing a program, you need to be thoroughly familiar with the operation of the
chip and how to write instructions.
This project has all you need but if you want to know more about how to write a program, we have a
comprehensive course called PIC PROGRAMMING COURSE on the website. You can see the course later.
There will come a time when your will need to see the additional information but for the moment we will cover
as much as possible to get you started. 
If you have never written a single PIC instruction, click HERE for your first lesson. 
Our method of loading values into a file uses Hexadecimal. Learn about Hex HERE. 
First we start with a pinout of the chip:

The simplest circuit to connect it to the power rails is shown below. The two components on the clock line
(4k7 and 22p) make the chip oscillate at 4MHz and any instructions programmed into  memory will be
executed at the rate of 1 million per second. Pin 4 needs to be taken HIGH. When taken LOW, the chip
resets. Pin 6 is the lowest output line of Port B. 
The program in the chip flashes a LED and this is covered in Experiment 1f, on the following page. 

5
 

It may seem overkill to use a microcontroller to blink a LED but this is an example to show how to program
the chip. We must start somewhere and to carry out a simple operation such as this you will need to have a
list of instructions for the chip. Click here for the set of instructions for a PIC16F84. We have laid them out in
a completely different way to that supplied by the manufacturer of the chip. Our list is much more
understandable and information has been included to help you choose the right instruction.
More information on the operation of the chip is provided in our PIC PROGRAMMING COURSE. This is on
the pay-site: POPTRONICS Interactive Edition and you need to subscribe for this section.   
This course represents 2 years of collecting information and solving problems during the designing of projects
and is invaluable to help you create a program. 

THE PC BOARD
The PIC LAB-1 Printed Circuit Board is very neatly laid out. It has two amplifying stages so an input of the
microcontroller (called an input line) can be connected to a coil, microphone, piezo, photo-transistor,
potentiometer or a diode (for temperature detection), as well as a push-button. The output has a row of 8
LEDs and a 7-segment display to show the result of the information. A complete Multi Chip Programmer (with
software) is available on this site as well as a blank programming template to assist you with creating your
own programs. MPASM is also available on the website to take your .asm file and assemble it to produce a
.hex file for the Multi Chip programmer. 
In all, it's a complete package. 
It gets you from the absolute beginning, to the stage of producing your own programs and projects with ease
and efficiency. It is not in competition with anything else on the market as it has been designed to teach
PROGRAMMING - at the least cost. 

To Top     Go to the lower half of page 1

PIC LAB-1
P1 - lower half

THE PIC LAB-1


The PIC LAB-1 printed circuit board can be divided into three sections: 
1: Amplifying (or interfacing) circuitry for the input devices, 
2: The microcontroller, and 
3: Output devices.

6
Top view of PIC LAB-1
The top socket (Pot) is the A-to-D conversion input, the middle socket (mic/coil) is the analogue input and the
Probe socket detects temperature. 

THE OVERLAY

The overlay (also called the LEGEND) for the PIC LAB-1 Printed Circuit Board

The overlay for the board clearly shows where each component is placed. The advantage of buying a kit is
each component is designed to fit the board. Click the "Buy Kit" button on the left-hand side of the page and
the kit will be sent the same day. All boards have a screened top layer showing the position of the
components and the underside is solder-masked so that only the lands are exposed and tinned without any
blocked holes. Four corner mounting holes allow the board to be fixed to the top surface of a box or lid for
demonstration purposes or class project etc. 
To read my comments about making your own PC board, click HERE. 

INPUT DEVICES
Many input devices cannot be connected directly to a microcontroller. They either produce a very small AC
voltage or a change in resistance. These devices must be connected via an amplifier.   
The amplifier increases the amplitude of the signal to a DIGITAL LEVEL. In the case of a change in

7
resistance, the device is connected to the supply rail via a resistor and the change in voltage across the
resistor (you can also say "the change in voltage across the device") is amplified (via a transistor) and passed
to the microcontroller. If the device produces a voltage or resistance that changes over a long period of time,
other interfacing circuitry must be used. This will also be covered in the project. 
It is the job of the program to detect a signal from the device and process it correctly. In our case this involves
turning on LEDs, showing the result on a 7-segment display and/or producing a tone from a piezo
diaphragm. 
  
THE MICROCONTROLLER
The PIC16F84 microcontroller has 13 lines that can be programmed as inputs or outputs ( in ANY
combination). 
It has a code-protection feature, so the program cannot be "looked at" by any outsider and thus any project
you design can be protected. 
The microcontroller we are using may be considered very simple and limited when compared to some of the
larger microcontrollers, but its capability will certainly allow quite impressive projects to be developed. And
most-importantly, it allows you to start at the beginning. 
One of the aims of this course is to steer you into programming and designing. For this, we need to start at
square-one, and talk about complexities, later.  

OUTPUT DEVICES
The output devices on PIC LAB-1 consist of a set of 8 LEDs and a 7-segment display, as well as a piezo
diaphragm. A buffer transistor allows a relay, globe, motor or speaker to be connected.
This gives a large number of combinations for outputting the data. 

Before we go any further, you will need two other things:


 A PIC16F84 chip and a Programmer to program the chip. 

Talking Electronics has produced a Multi-Chip Programmer suitable for programming the PIC16F84. It can
be assembled in less than an hour and comes with a serial cable (in kit form) to connect to the serial port of
your computer. The PIC16F84 chip comes with the PIC LAB-1 kit. It can be re-programmed about 1,000
times.

With a Programmer, Chip and PIC LAB-1 you have the equipment needed to study the concepts of writing
PIC programs and developing quite complex projects. 
Many projects presented in books and magazines, using ordinary logic chips and discrete components, can
be converted to a PIC design and the "building blocks" on PIC LAB-1 will help create a micro controlled
project. 
This will be the discussion for an article in the future (we have already produced other modules using this
chip). For the moment we need to explain how to create some of the simplest routines. 
But the first thing to do is assemble PIC LAB-1. This has been made easy with a fully-detailed printed circuit
board. All the components are clearly identified and the kit contains the smallest, neatest, components
available. The supplier of the kit is TALKING ELECTRONICS. The cost is less than if the components were
bought separately and we suggest you invest in a kit.
To order, simply click the button.
You can buy the kit or a "Ready Built and tested" version.

Using a PC board prevents a wiring mistake and assembling a kit means you have the highest chance of
success. The kit comes with a pre-programmed chip with a Test Routine and a section on "If it Doesn't
Work" is included below, to help with any problems that may arise. 
The board has been designed for both functionality and presentation. It should NOT be housed in a box as
you need to access the buttons and IC. The chip is transferred to and from the Multi Chip Programmer in a
"carrier." This is an 18 pin IC socket fitted to the base of the chip. The two are moved as a "unit." This makes
the chip easy to insert and remove from the socket on the PC board and prevents the pins stabbing your
fingers. 
Simply move the chip sideways and it will come out of the socket. You don't need an expensive ZIF socket!  
The PIC chip in the kit contains a special TEST ROUTINE to test each of the input and output devices. 
Once the kit is assembled, insert the chip and switch ON. Go to the Test Routine section for further details. 
The project is now ready.  
The site contains over 25 programs, including the HEX listing for the Multi-Chip Programmer and this will
provide you with the basics to produce routines for your own projects and ideas.   
8
CONSTRUCTION
Construction is made very easy by referring to the overlay on the PC board. It shows exactly where each
component is placed and its orientation. Fine solder is included in the kit to make the overall appearance of
each joint very clean. Fine solder makes an enormous difference to the quality of the joint and you need a
low-wattage iron for the delicate work. Low-wattage does not mean low-temperature (at the tip) and if the
solder smokes as soon as you apply it, the iron is too hot. 
A power-diode in series with one lead will reduce the temperature to the
correct value. Get a qualified person to add the diode for you - he will
understand its function.
Clean the tip of the iron with fresh solder before starting a connection (if the
iron has been left standing for any length of time) and tap off any excess. Add
more solder when the iron is actually heating the component-lead. Make sure
the joint is bright and shiny after completion, before going to the next
connection. Do not touch or wiggle the joint until it has thoroughly cooled
down.
Only add one or two components to the board at a time and snip the leads
after each operation. These are the basics you MUST adhere to. 
There are many ways to fill the board. You can start with the high
components, such as the IC sockets and then the small components, or move across the board from left-to-
right, fitting each component as you come to it. The best way is to add the IC socket first, to fill the majority of
holes.  The most important point is to hold the component in your fingers while soldering
and if it gets too hot to hold, you are taking too long. The author always holds each
component to make sure nothing is damaged by overheating.
Push the components up to board before soldering, except the transistors and LEDs.
These should be 1/4" (3mm) from the board to prevent heat running up the leads and
damaging the semiconductor material inside.
The 7-segment display is identified by the decimal point at the base of the display. 
The final item to fit is the battery snap.
Fit the pre-programmed PIC chip and the project is ready for testing.   
The input devices such as the microphone, coil,  photo-transistor and potentiometer, are connected to the
board via small 2-pin plugs. These fit into sockets made from machine-pins.   These plugs and sockets are
cut from a strip by scoring between the pins with a sharp knife and breaking with your fingers. The
microphone and darlington photo-transistor must be plugged-in around the correct way and if they are
soldered to the plug and bent as shown in the photos, they cannot be plugged-in around the wrong way. 
They will not be damaged if reversed, however it is best to make sure they are connected correctly. They can
be connected via a short lead if required.
The potentiometer and diode are also connected to the board via a 2-pin plug.

By bending the microphone, diode and photo-transistor to 90°, the plug is effectively 'polarised,' it can only be
fitted around one way.

CONNECTING THE INPUT DEVICES


The input devices are soldered to machine pins that fit into
a machine socket on the PC board. The orientation of
some input devices is important as they will not work when
connected around the wrong way. The diagram below
shows how to connect each item:

The 10mH choke (coil) must be wound on the ferrite


former, using the .005" (5 thou) wire provided. The number
of turns is not important, however it is best to wind as
many turns as possible on the former until the winding is
flush with the outer edge. This will produce a coil with
about 300 turns and it will have a resistance of about 15
ohms. The resistance is not important, however each turn
will increase the voltage generated when a magnet is passed across the end of the former.
Fit the sleeve over the winding and shrink with a hot flame such as a match or cigarette lighter.
Clean the ends of the fine wire with a blade and solder to the ends of the thick wires where they emerge from

9
the former. Bend one lead over to produce a one-ended inductor. Cut both leads to the same length and
solder them to the machine pins provided, to produce a plug.

TEST ROUTINE
PIC LAB-1 kit comes with a pre-programmed chip containing the TEST ROUTINE. Turn the project ON
and the row of 8 LEDs will scan across and back. The individual segments of the 7-segment display will also
turn ON. Push button "A."
The letters "Pb" will show on the 7-segment display - for "Push button."
Push button "A" again and the top 4 LEDs will blink, followed by the lower 4 LEDs. Push button "A" again.
The letters "AUdiO" will show on the display. Push button "A" again.
Fit a microphone to the 2-pin plug marked "MIC" and talk or whistle. The lowest LED will turn ON to indicate
audio. Push button "A" again. 
The letters POt will flash on the 7-segment display. Push button "A" again.
Insert a potentiometer into the 2-pin plug labelled "Pot" and rotate it in both directions. The 7-segment display
will indicate rotation. 
All the input and output devices are now tested. 
Push button "A" to repeat the sequence.

IF IT DOESN'T WORK
If the project doesn't work, there are 4 areas to investigate. 
They are:
The INPUT, the MICROPROCESSOR, the OUTPUT, the PROGRAM.
These notes apply to a project that has assembled from a kit with the pre-programmed PIC chip fitted to the
board. Anything built on matrix board, using junk-box parts, may have any number of other introduced faults.
99% of faults eventually boil down to the builder using non-kit components and failing to let us know. After
dozens of emails we finally realise he has used "odd-ball" components. 
A capacitor may appear to be "22" but is really "2.2"  A resistor may appear to be 100k, but is really a 1%
type and the colours have been read incorrectly. 
Here is a resistor colour-code calculator for 1% types  and  5% types.

THE INPUT
If the operation of pushing the switch does not work in the TEST ROUTINE, It may be faulty, fitted to the
board incorrectly or not soldered. The 47k resistor may be missing or not soldered. Measure pin 17 of the
chip and make sure it goes HIGH when the switch is pressed.
The TEST ROUTINE may not be responding to the switch. You can try Experiment 1, if you think the Test
Routine is faulty. 

THE MICROCONTROLLER
If the 8 LEDs do not illuminate, you will need to test pin 14 for approx 5.4v  Also check pin 16 for approx 5.4v
(clock in).
The most likely fault is the chip failing to "clock." Check the 22p. The chip has been pre-programmed and
checked in a PIC LAB-1 project, before it is sent with the kit, so it will NOT be faulty. 
The main problem will be the 22p and the impedance of the circuit. At 4MHz the chip is operating at its
maximum frequency and if the circuit is not "tight" the chip will fail to oscillate. The answer is to reduce the
frequency at which the chip will be oscillation, by adding a 22p to 100p across the  22p. You should also
make sure the batteries are fresh. 
To reduce the impedance of the circuit you can add another 100n across the rails NEAR the chip. 
You can also check for shorts and dry joints around the chip as well as incorrect component values,
especially the 4k7 and 22p on the oscillator input to the chip. 
Do not operate the project from a power supply or use long leads to the batteries. These tend to increase the
impedance of the supply and can result in the chip not oscillating. 
Any project built on a "home-brew" board or matrix board can suffer from a very "loose" supply rail called a
high-impedance rail. This will prevent the chip oscillating. 
It's a bit like getting 4 people to hold a trampoline in the air while you bounce on it. You can see exactly what
would happen. You would not be able to get any spring into the air. 
The same happens with the internal oscillator of the chip. If the supply rails are loose, the chip fails to
oscillate.

THE OUTPUT
If some LEDs do not illuminate, they may be around the wrong way. If the display is up-side-down, only the
10
end LED will illuminate. If the LEDs are damaged by excess heat during soldering, the output will be very
weak. 

THE PROGRAM
If a program from one of the experiments does not work, you will have to go over all the steps involved in
producing the program. 
The hardware side of the project is operational as it has been tested via the TEST ROUTINE. 
If this is the first program you have "burnt" into the chip, you will need to check the Multi Chip Programmer
project and the serial cable. 
You can read and verify the program in the chip via the Multi Chip Programmer to see if it has been loaded
correctly. 
Also check the config settings. These are also called "fuses" and will also prevent the chip operating if not set
correctly. If the chip is set to operate with a Xtal, it will not "clock" with RC components. In the top right-hand-
side window, make sure RC is showing in the window.
For the experiments in this project, the fuse settings (WDT, PWRT and CP) must be turned off (unclicked) in
IC-Prog. 
 
HOW THE CIRCUIT WORKS
The circuit consists of three sections. The input device and its associated amplifying circuitry, the
microcontroller and the output device. 
One or more input devices can be connected to the circuit at the same time and the program (in the
microcontroller) detects the presence of the device and produce an output to activate one or more display
devices.
The main purpose of the input-amplifier is to increase the amplitude of a signal to a level called DIGITAL
LEVEL. This is an amplitude of at least 75% of rail voltage and a minimum of about 10%. This is needed to
make sure the micro detects a HIGH and LOW. 
A waveform below Digital Level is called an ANALOGUE waveform and the amplifier that converts (amplifies)
the signal is called an Analogue-to-Digital stage, or A-to-D amplifier. It is given this reference-name to show
the stage must have sufficient amplification to produce a digital signal. 
We have provided sufficient gain for all the devices in the experiments with a two-stage amplifier and the
actual term is OVER-AMPLIFICATION. This is to ensure the signal is at a digital level. The first stage is a
self-biased common emitter stage with a gain of about 70. It feeds a second stage and this is where the
clever design is evident. This stage is biased OFF, with approx 500mV on the base. It only needs approx
250mV signal through the 100n capacitor to turn it on. The collector voltage will change from rail voltage to
about 300mV. The result is a fairly clean square wave for the input of the microcontroller. 
More details on designing A-to-D amplifiers is provided on other pages in our site. 

TEMPERATURE PROBE
The circuitry for the temperature probe is a little more complex. The probe is a diode and the voltage across it
changes by -2mV per degree centigrade. This means the voltage across it reduces as the temperature
increases. This is not a problem as the circuit and program can be adjusted for any situation. This is a fairly
small voltage change and we have opted to amplify the change by using a transistor to detect the voltage
across the diode. 
To turn the transistor ON, a voltage divider made up of a 22k and 1k has been added in series with the diode.
Any variation in supply voltage will alter the amplification of the transistor considerably and so a constant
supply voltage has been obtained by using the constant-voltage characteristics of two green LEDs in series.
This provides a supply rail of  2.1v + 2.1v = 4.2v for the base of the transistor. 
As the temperature of the diode changes, the voltage on the base of the transistor alters and this modifies the
effective resistance between the collector-emitter terminals of the transistor. 
The micro charges a 100n capacitor via a 1k, 10k and collector-emitter resistance. As the capacitor charges,
the voltage on Pin1 reduces. The micro detects the time for the voltage to fall to the lower threshold voltage
of an input line and this time is referenced to a table to determine the temperature detected by the probe. 

RESISTANCE
Resistance is measured by a series RC circuit called a TIME DELAY circuit. 
The time taken for a capacitor to charge is detected by the micro and can be referenced to a table to
determine the value of resistance in the circuit. 
 
OUTPUT DEVICES
The output devices are connected to the output port and the program can be designed to give a reading on
11
the row of 8 LEDs, the 7-segment display or drive the output transistor to operate a piezo diaphragm, or other
device connected to the output terminals.

THE RESET CIRCUIT

To reset the program in the PIC chip, the reset button is pressed momentarily. The
program will then start at location "000" 
For the reset to work, the program must have instructions in SetUp to clear (zero) files
and turn off any outputs. Files are not emptied by the action of Reset and it will
appear that "reset" is not working if the files are not emptied in SetUp. 
File 06 must be cleared or loaded with a starting value so that the program appears to
be reset when the button is pressed. 
 

  THE CIRCUIT:

Inputs detected: push-switch, microphone, piezo, coil and photo-transistor


Note the modification above to make the microphone input less sensitive to noise.
Take the 47k microphone dropper-resistor to the 4v2 provided by the two green LEDs.

Inputs detected: temperature via diode, resistance via potentiometer

  

12
The pin-outs for some of the devices used in this project

PARTS LIST
  Kits for this project are available from Talking Electronics.

PIC LAB-1 
PARTS LIST
au$49.90 plus $4.40 post
Order kit

8 - 150R     all  1/4 watt    5% resistors


2 - 1k
1 - 2k2
2  - 4k7
3 - 10k 
3 - 22k 
3 - 47k 
1 - 1M 
1 - 2M2 
1 - 10k mini trim pot with shaft 
1 - 22p NPO ceramic 
3 - 100n monolithic capacitors "monoblock" 
2 - 1u 16vw electrolytics 
1 - 100u 16vw electrolytic 
9 - 3mm red LEDs 
2 - 3mm green LEDs 
1 - 7-segment display   FND 500 or equiv.
1 - 1N4148 signal diode 
1 - 1N 4004 power diode 
4 - BC 547 transistors or similar 
1 - mini PCB piezo diaphragm
1 - electret microphone insert
1 - MEL-12 photo Darlington transistor
1  -  black sleeve for MEL-12
1 - 10mH choke
1 - ferrite magnet
1 - SPDT mini slide switch
2 - PC mount tactile push switch
1m - very fine solder 
1 - strip of 18 machine pins
2 - 18pin IC sockets (put PIC chip in one!)
1 - PIC16F84 chip (with Test Routine)

13
1 - Battery Snap
1 - 4-AA cell battery holder
4 - AA cells
1 - PIC LAB-1 PC board

Kits for PIC LAB-1 can be obtained from


Talking Electronics:
http://www.talkingelectronics.com

THE EXPERIMENTS
There are more than 25 experiments for the PIC LAB-1 and the project must be working correctly before they
can be loaded. 
Don't forget to test the project with the TEST ROUTINE (in the PIC chip that comes with the kit) before
starting the experiments. 
Each experiment (in a group) starts with the simplest for a particular device and gradually increases in
complexity. They start on the next page and you can see the list of experiments above. But first you have to
know how to burn a program into a PIC chip.

BURNING A PROGRAM
Each experiment on the pages that follow is shown in a layout very similar to a text-editor. But it cannot be
copied and loaded into a program for burning into a PIC chip as it contains hidden formatting. 
To burn the experiments into a PIC chip, the files have been zipped for downloading. 
The extension you need for the burning process is .hex and these files can be found by clicking: 
PIC LAB-1 Expmts-hex. You can also see:  PIC LAB-1 Expmts-all
Go to the menu of your computer and create a new folder: PIC LAB-1  
Download the .zip file(s) into PIC LAB-1 folder.
You will also need a programmer to "burn" the PIC chip. 
We say "burn" to identify the operation of putting a program into the chip, rather than "program the chip" as
we use "program" in the context of writing a program.
The PIC Programmer designed by Talking Electronics is Multi Chip Programmer. 
Build the Programmer, test it and have it ready. 
You will also need the software to transfer the information from a .hex file to the programmer. 
The software is: ICPROG.
Download IC-Prog.exe  and a help file: ICPROG-Help (IC-Prog.chm)
Extract all the files into PIC LAB-1 folder.  Place ICPROG.exe into your desktop folder and it will appear on
your screen.  
Go you your front-screen (desktop) and open ICPROG.
On the window showing the types of chips the programmer is able to program, select PIC 16F84. 
In the oscillator window, select RC. 
In the fuses windows, remove all the ticks. 
Click the "open file" icon on the left hand side of the screen. Find Expt1.hex and load it into the programmer.
A tick will appear in the WDT window to indicate a file has been loaded. Remove the tick. 
Make sure the Multi Chip Programmer has been fitted to "Com1" via a serial cable and the red LED on the
Multi Chip Programmer is active.
Click on the IC Icon with the "lightening" and a dialog box with "Do you really want the program the device?"
will appear. Click "yes" and the orange and green LEDs will illuminate and the screen will indicate the chip
has been programmed correctly.   
Remove the chip and fit it to the PIC LAB-1 project. Fit any necessary input devices and switch ON. The
LEDs on the output will respond.   
If every thing has gone successfully, you will have "burnt" your first routine. 
Read the instructions for each experiment carefully and follow them to see exactly how the program is
constructed and executed. 
As soon as you get to the stage of writing your own programs, send them in and we will add them to the
Readers Experiments Section. 

14
PIC LAB-1
P3

EXPERIMENT 4
Counting on the 7-segment display
This experiment uses the push-button to increment the count on the 7-segment display. The count-value is
stored in a file and this value is incremented by the program each time the push button is pressed. The count-
value is used to look-up a table to pick up the display-value for the 7-segment display. 
Additional experiments on the website include a count-down routine, a 00 to 99 counter using a single display
and others. 
The Table: The first value in a table is accessed when the Program Counter has an addition of "0" because it
naturally increments to the next location in memory. In the routines below, the number if items in the table are
counted and used to determine "end of table."  The reason is the jump-value is incremented before it is
compared.  

                    ;Expt4.asm
                    ;Project: Counting on 7-segment display
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0  ;This is the start of memory for the program.
SetUp BSF 03,5  ;Go to Bank 1
CLRF 06  ;Make all port B output
MOVLW 01  ;Load W with 0000 0001
MOVWF 05  ;Make RA0 input
BCF 03,5  ;Go to Bank 0 - the program memory area.
MOVLW 3Fh  ;
MOVWF 06  ;Put "0" on display at reset
CLRF 1E  ;Clear the count file
CLRF 1F  ;Clear the button-press file
GOTO Main

Table ADDWF 02h,1  ;Add W to the Program Counter to create a jump. 


NOP      ;    format= gfedcba
RETLW 06h  ;1    If any table value has a leading letter, it must be
RETLW 5Bh  ;2    preceded with a "0."   E.g: 0A3h, 0FFh, 0CCh
RETLW 4Fh  ;3
RETLW 66h  ;4
RETLW 6Dh  ;5
RETLW 7Dh  ;6
RETLW 07h  ;7
RETLW 7Fh ;8
RETLW 6Fh  ;9 
RETLW 3Fh    ;0

15
Delay MOVLW 0A  ;Create 1mS debounce delay
MOVWF 1B
Del1 NOP 
DECFSZ 1A,1
GOTO Del1
DECFSZ 1B,1
GOTO Del1
RETURN

Main Main CLRF 1E  ;1E holds the count-value. Next increment: file=1
Main1 BTFSS 05,0  ;Test the input line on port A
GOTO Main2  ;Button not pressed
CALL Delay  ;Debounce the button
BTFSC 1F,0  ;Button pressed first time?
GOTO Main1  ;Button already pressed
INCF 1E,1  ;First time button pressed. Increment count.
MOVLW 0B  ;Has count reached eleven?
XORWF 1E,0  ;Compare file 1E with eleven
BTFSC 03,2  ;Check the zero flag in Status file
GOTO Main  ;
MOVF 1E,0  ;Copy count into W
CALL Table  ;W will return with display-value
MOVWF 06  ;Output display value
BSF 1F,0  ;Set button-press flag
GOTO Main1  ;Loop Main1
Main2  CALL Delay  ;Button not pressed. Call Delay
BCF 1F,0  ;Clear button-press flag
GOTO Main1  ;Loop Main1

END  ;Tells assembler end of program

EXPERIMENT 4a
Binary Counting
This experiment produces a binary count on the 8 LEDs.  The output will always show the content of file 06.
File 06 can be incremented, decremented, and shifted, etc just like any of the other files. The program
increments the count in file 06 and shows it for 0.5sec, before incrementing to the next value. A files will show
values in binary, from 00 to 127, making a total of 128 for each cycle of the file. 

                    ;Expt4a.asm
                    ;Project: Binary Counting
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 06 ;Turn off all LEDs
GOTO Main

Delay NOP ;Create approx 250mS delay


DECFSZ 1A,1
GOTO Delay
DECFSZ 1B,1
GOTO Delay
RETURN

16
Main CALL Delay ;Show LEDs for 250mS
CALL Delay ;Show LEDs for 250mS
INCF 06 ;Increment the count in file 6
GOTO Main ;Loop 

END ;Tells assembler end of program

EXPERIMENT 4b
Binary Counting - up/down
This experiment counts up and down in binary. A push button reverses the count. 
It is very interesting to see how a file increments and decrements. This will help you understand binary
numbers. The numbers increment at 4 counts per second. At the same time you will see all combinations of
segments on the 7-segment display. 

                    ;Expt4b.asm
                    ;Project: Binary Counting up/down
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
MOVLW 01 ;Load W with 0000 0001
MOVWF 05 ;Make RA0 input
CLRF 06 ;Make all port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 06 ;Turn off all LEDs
CLRF 1F ;Clear the button-press file
GOTO Main

Delay NOP ;Create approx 250mS delay


DECFSZ 1A,1
GOTO Delay
DECFSZ 1B,1
GOTO Delay
RETURN

Main CALL Delay ;Show LEDs for 250mS


INCF 06,1 ;Increment the count in file 6
BTFSS 05,0 ;Push-button pressed?
GOTO MainA ;No
BTFSS 1F,0 ;Test button-press flag
GOTO Main2 ;First pass for button?
BSF 1F,0
GOTO Main
MainA BCF 1F,0
GOTO Main

Main2 CALL Delay ;Show LEDs for 250mS


DECF 06 ;Decrement the count in file 6
BTFSS 05,0 ;Push-button pressed?
GOTO MainB ;No
BTFSS 1F,0 ;Test button-press flag
GOTO Main ;First pass for button?
BSF 1F,0
GOTO Main2
MainB BCF 1F,0
GOTO Main2

17
END ;Tells assembler end of program

EXPERIMENT 4c
Producing letters on the 7-segment display
This experiment shows letters of the alphabet on the 7-segment display. Almost all the letters can be
displayed except k, m, v, w, x, z. Sometimes only a capital or small can be displayed and this results in a
mixture for some words. However it is nearly always possible to use words that can be easily displayed.  To
produce a word, the letters are flashed on the display for a short period of time with a brief blank between
each letter. This allows doubles to be displayed, especially double numbers for telephone numbers etc.  The
following routine  automatically displays all the letters. Experiment 4 has the hex values for the numbers 0-9.
Some of the other difficult letters can be created on the display and if readers accept them as readable, they
will be added to the list. 
The program displays each letter for 0.75sec and turns the display off for 0.25sec.  No input button is
required for the execution of the program. 

                    ;Expt4c.asm
                    ;Project: Displaying letters
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.
GOTO Main

Table ADDWF 02h,1 ;Add W to the Program Counter to create a jump. 


RETLW 77h ;A    This is jump=0 location.   format= gfedcba
RETLW 7Ch ;b       
RETLW 39h ;C
RETLW 5Eh ;d
RETLW 79h ;E
RETLW 71h ;F
RETLW 6Fh ;g
RETLW 76h ;H
RETLW 06h ;I
RETLW 1Eh ;J
RETLW 38h ;L
RETLW 37h ;N
RETLW 3Fh ;O
RETLW 73h ;P
RETLW 67h ;q
RETLW 50h ;r
RETLW 6Dh ;S
RETLW 78h ;t
RETLW 3Eh ;U
RETLW 6Eh ;y

Delay NOP ;Create approx 250mS delay


DECFSZ 1A,1
GOTO Delay
DECFSZ 1B,1
GOTO Delay
RETURN

18
Main CLRF 1E ;File 1E holds the jump-value for the table
Main1 MOVF 1E,0 ;Copy the jump-value into W
CALL Table ;W will return with display-value
MOVWF 06 ;Output display value
CALL Delay ;Display for 0.25sec
CALL Delay ;Display for 0.25sec
CALL Delay ;Display for 0.25sec
CLRF 06 ;Clear the display
CALL Delay ;Blank the display for 0.25sec
INCF 1E,1 ;Increment jump-value to look at next table value
MOVLW 14h ;The number of table-values (in hex)
XORWF 1E,0 ;Has the jump-value reached 14h?
BTFSS 03,2 ;Test the zero bit in the Status register
GOTO Main1 ;Loop to display next value 
GOTO Main ;Start again

END ;Tells assembler end of program

EXPERIMENT 4d
Displaying WORDS
This experiment shows "PUSH BUttON" on the 7-segment display. The sub-routine is called "Word1" and can
be called from Main. You can add this sub-routine to any of your programs. A second word can be created by
calling "Word2"  etc. If a number of words are needed, the structure of the program can be altered so that a
standard word calling routine is used that picks up a word from a table and looks for FF to end the word. 

                    ;Expt4d.asm
                    ;Project: Displaying WORDS
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.
GOTO Main

Table1 ADDWF 02h,1 ;Add W to the Program Counter to create a jump. 


RETLW 73h ;P    This is jump=0 location.   format= gfedcba
RETLW 3Eh ;U    This is jump=1 location.   
RETLW 6Dh ;S    This is jump=2 location.
RETLW 76h ;H
RETLW 00h ;blank
RETLW 7Ch ;B
RETLW 3Eh ;U
RETLW 78h ;t
RETLW 78h ;t
RETLW 3Fh ;O
RETLW 37h ;N
RETLW 00h ;blank

Delay NOP ;Create approx 250mS delay


DECFSZ 1A,1
GOTO Delay
DECFSZ 1B,1
GOTO Delay
RETURN

19
Word1 MOVF 1E,0 ;Copy the jump-value into W
CALL Table1 ;W will return with display-value
MOVWF 06 ;Output display value
CALL Delay ;Display for 0.25sec
CALL Delay ;Display for 0.25sec
CALL Delay ;Display for 0.25sec
CLRF 06 ;Clear the display
CALL Delay ;Show display for 0.25sec
INCF 1E,1 ;Increment jump-value to look at next table value
MOVLW 0Ch ;The number of table-values (in hex)
XORWF 1E,0 ;Has the jump-value reached 0Ch?
BTFSS 03,2 ;Test the zero bit in the Status register
GOTO Word1 ;Loop to display next table-value 
RETURN ;Start again

Main CLRF 1E ;File 1E holds the jump-value for the table


CALL Word1
GOTO Main

END ;Tells assembler end of program

EXPERIMENT 4e
Push "A" to display a word
This experiment shows "ENtEr" on the 7-segment display, after button "A" is pressed. The experiment shows
how to combine two sub-routines. The program is constantly POLLING button "A" and when it is pushed, a
flag is set and the micro returns to Main. The flag file is 1F and the flag bit is bit0. In Main, the flag bit is
checked and if it is set, the micro goes to Word1 to display "ENtEr," from Table1.

                    ;Expt4e.asm
                    ;Project: Push "A" to display a word
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 1F ;Clear the button-press file
GOTO Main

Table1 ADDWF 02h,1 ;Add W to the Program Counter to create a jump. 


RETLW 79h ;E    This is jump=0 location.   format= gfedcba
RETLW 37h ;N    This is jump=1 location.   
RETLW 78h ;t      This is jump=2 location.
RETLW 79h ;E
RETLW 50h ;r
RETLW 00h ;blank

Delay NOP ;Create approx 250mS delay


DECFSZ 1A,1
GOTO Delay
DECFSZ 1B,1
GOTO Delay
RETURN

Sw BTFSS 05,0 ;Test the push-button input

20
RETURN ;Sw NOT pushed
BSF 1F,0 ;Switch pushed. Set button flag.
RETURN

Word1 MOVF 1E,0 ;Copy the jump-value into W


CALL Table1 ;W will return with display-value
MOVWF 06 ;Output display value
CALL Delay ;Display for 0.25sec
CALL Delay ;Display for 0.25sec
CALL Delay ;Display for 0.25sec
CLRF 06 ;Clear the display
CALL Delay ;Show display for 0.25sec
INCF 1E ;Increment jump-value to look at next table value
MOVLW 06h ;The number of table-values (in hex)
XORWF 1E,0 ;Has the jump-value reached 06h?
BTFSS 03,2 ;Test the zero bit in the Status register
GOTO Word1 ;Loop to display next table-value 
RETURN

Main CLRF 1E ;File 1E holds the jump-value for the table


CALL Sw ;Poll (look at) push-button "A"
BTFSC 1F,0 ;Has switch been pushed?
CALL Word1 ;Yes. Display "ENtEr"
BCF 1F,0 ;Clear button flag
GOTO Main

END ;Tells assembler end of program

EXPERIMENT 5
Creating a tone
This experiment creates a tone. A tone is simply the action of turning on an output, executing a delay, turning
off the output, executing a delay, then repeating the sequence.
This action produces a square-wave and the microcontroller activates a driver transistor that drives a piezo
diagram to produce the characteristic harsh sound. 
The microcontroller can drive a piezo diaphragm directly but we have opted to add a driver transistor so the
circuit can also drive a mini speaker, if needed. Place your finger on and around the components to see how
the resistance of your finger affects the performance of the circuit. This indicates the sensitive components. 
Once you know how to produce a tone, the whole world opens up to sounds, noises, tones and tunes. 

                    ;Expt5.asm
                    ;Project: Creating a tone
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 06 ;Clear outputs of junk
GOTO Main

Delay NOP ;Create 1mS delay


DECFSZ 1A,1
GOTO Delay
RETURN

BSF 06,7 ;Turn on driver transistor

21
Main CALL Delay ;Create ON time
BCF 06,7 ;Turn off driver transistor
CALL Delay ;Create OFF time
GOTO Main ;Loop

END ;Tells assembler end of program

EXPERIMENT 6
Creating a tune
This experiment creates a tune. It is an extension of experiment 5. 
A sequence of tones is produced by making a table containing a pair of values for each note. The first value
produces the time-delay between the high and low of the output and thus creates the frequency of the tone.
The second value creates the length of time for the note. 
This value is a little bit more complex than first appears. 
Suppose we want to reproduce a middle C minum:
The tune "Hey Jude" is played at at speed know as "Allegro." This has a metronome rate of between 120 and
160. Suppose we choose the centre-value of 140. This is 140 beats per minute and represents the time taken
to play a minum or half-note. (A minum is a hollow oval with a plain riser). You may recall, a metronome
beats or "clicks" each time it moves to the left and to the right. The time between the "click-click" is 1/140
minute. This gives 430mS for a minum. A Crotchet is a solid oval with a riser and takes 215mS. A Quaver
has a flag on the riser and takes 107mS. A semi-quaver has two flags and takes 53mS. 
Middle C is 262Hz. From this we know the length of the delay between the high and low output, to produce
one cycle. 
The other value we need to know is the number of cycles of middle-C in 430mS. The answer is 112.
For each frequency we need to work out the number of cycles for each length of note. 
With this we can create a table of values. The program will pick up a pair of values and play the note for the
correct duration.   The end of the table is assigned FF. The program looks for FF to repeat. 

                    ;Expt6.asm
                    ;Project: Creating a tune
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 06 ;Clear outputs of junk
SetUp1 MOVLW 01
MOVWF 0Ch
GOTO Main

Table ADDWF 02h,1


RETLW 0A8h ;duration - 168 loops
RETLW 5Bh ;G - 392Hz 1.27mS HIGH,LOW - 91 loops
RETLW 0FAh ;duration - 250 loops
RETLW 6Bh ;E - 330Hz 1.51mS HIGH,LOW - 107 loops
RETLW 46h ;duration - 70 loops
RETLW 6Bh ;E - 330Hz
RETLW 54h ;duration - 84 loops
RETLW 5Bh ;G - 392Hz
RETLW 5Eh ;duration - 94 loops
RETLW 51h ;A - 440Hz - 1.13mS HIGH,LOW - 81 loops
RETLW 0FCh ;duration - 252 loops
RETLW 7Ah ;D - 292Hz - 1.71mS HIGH,LOW - 122 loops
RETLW 0FFh ;End of table
RETLW 0FFh ;End of table

22
Delay NOP ;Create 10uS delay
NOP
NOP
NOP
NOP
NOP
RETURN

Delay2 CALL Delay ;Create 3mS delay


DECFSZ 1A,1
GOTO Delay2
RETURN

Delay3 NOP ;250mS delay


DECFSZ 1A,1
GOTO Delay3
DECFSZ 1B,1
GOTO Delay3
RETURN

Main DECF 0C,1 ;Dec jump value to re-look at values


MOVF 0Ch,0 ;Copy jump-value into W
CALL Table ;Return with table-value in W
MOVWF 0F ;Length of note into file 0F
INCF 0Ch,1 ;Increment the table-value
MOVF 0Ch,0 ;Copy jump-value into W
CALL Table ;Return with table-value in W
Main1 MOVWF 0D ;Frequency of note into file 0D
MOVWF 0E ;Frequency of note into file 0E
Main2 BSF 06,7
CALL Delay ;Create HIGH time
DECFSZ 0D,1 ;Each loop = 14uS
GOTO Main2
Main3 BCF 06,7
CALL Delay ;Create LOW time
DECFSZ 0E,1
GOTO Main3
DECFSZ 0F,1 ;Length of note
GOTO Main1
BCF 06,7
CALL Delay2 ;3mS between notes
CALL Delay2 ;3mS between notes
CALL Delay2 ;3mS between notes
INCF 0Ch,1 ;Increment pointer to next value in table
MOVF 0Ch,0 ;Copy jump-value into W
CALL Table ;Return with table-value in W
MOVWF 10h ;Put "end of table" into file 10h
MOVLW 0FFh ;Check for 'end of table'
XORWF 10h,0 ;Compare file 10h with FF (result in W)
BTFSC 03,2 ;Look at Zero flag in status file
GOTO Main4 ;Start again
INCF 0Ch,1 ;Increment the table-value
GOTO Main ;Go to next note
Main4 CALL Delay3
CALL Delay3
CALL Delay3
GOTO SetUp1

23
END ;Tells assembler end of program

EXPERIMENT 7
Siren Sound
This experiment creates a Siren sound.
It can be added to an alarm and when played through an 8-watt horn speaker, the output can be ear-
shattering. 
The program shows how the instructions create a delay between the output being HIGH and LOW, to
produce one cycle. When this is repeated, a tone is produced. It is actually a square-wave output. As the
delay between the HIGH and LOW is reduced or increased, the tone rises or falls. Additional alarm sounds
are described on the website.

                    ;Expt7.asm
                    ;Project: Siren Sound
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 06 ;Clear display
GOTO Siren

Siren MOVLW 80h ;Number of cycles for each tone


MOVWF 0Eh
MOVWF 10h
MOVLW 50h ;Number of steps 
MOVWF 0Fh ;File 0F holds the number of steps
MOVLW 50h ;Determines frequency
MOVWF 0Ch ;File 0C determines the frequency
Repeat MOVF 0C,0  ;File 0C is moved to W
MOVWF 0D ;W is moved to file 0D for decrementing
BSF 06,7 ;Length of HIGH time to Piezo 
On DECFSZ 0D,1
GOTO On
MOVWF 0Dh ;W is moved to file 0D again
BCF 06,7 ;Length of LOW time to Piezo
Off DECFSZ 0D,1
GOTO Off
DECFSZ 10h,1 ;Number of cycles for each tone
GOTO Repeat
DECF 0C,1 ;HIGH and LOW is shortened -tone rises 
INCF 0E,1 ;Increase the number of cycles
MOVF 0E,0 ;File 0E to W
MOVWF 10h ;W to file 10h
DECFSZ 0F,1 ;Number of steps
GOTO Repeat 
GOTO Siren

END ;Tells assembler end of program


PIC LAB-1
P4

24
 

EXPERIMENT 7a
Hee Haw Sound
This experiment creates a Hee Haw sound for an alarm. The diagram shows the number of cycles for the
HEE and the time taken for each cycle, equates to a certain length of time. The frequency of the HAW is
lower and the number of cycles must be worked out so that the time for the HAW is equal to the time for the
HEE.
This is simple when writing the program. The values loaded into the two files for the HEE are reversed for the
HAW.
The routine consists of two sections: HEE and HAW. Each section has two  nested loops. The inner loop
creates the length of time for the HIGH and LOW to produce a single cycle and the outer loop creates the
number of cycles.  

                    ;Expt7a.asm
                    ;Project: Hee Haw Sound
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 06 ;Clear display
GOTO Hee1

Hee1 MOVLW 0FFh ;Number of loops


MOVWF 14h ;The loop file
Hee2 MOVLW 0C0h  ;Duration of HIGH
BSF 06,7 ;Turn on piezo
Hee3 NOP
DECFSZ 15h,1 ;Create the HIGH time
GOTO Hee3
MOVLW 0C0h  ;Duration of the LOW
MOVWF 15h ;The LOW file
BCF 06,7 ;Turn off piezo
Hee4 NOP
DECFSZ 15h,1 ;Create the LOW time
GOTO Hee4

25
DECFSZ 14h,1 ;Decrement the loop file
GOTO Hee2 ;Do more cycles

MOVLW 0C0h ;Number of loops


MOVWF 14h ;The loop file
Haw1 MOVLW 0FFh
MOVWF 15h
BSF 06,7 ;Turn on piezo
Haw2 NOP
DECFSZ 15h,1 ;Create the HIGH time
GOTO Haw2
MOVLW 0FFh ;Duration of the LOW
MOVWF 15h ;The LOW file
BCF 06,7 ;Turn off piezo
Haw3 NOP
DECFSZ 15h,1 ;Create the LOW time
GOTO Haw3
DECFSZ 14h,1 ;Decrement the loop file
GOTO Haw1 ;Do more cycles 
GOTO Hee1

END

EXPERIMENT 8
A to D Conversion
This experiment shows 0-256 parts of a 10k potentiometer on the 8 LEDs. It is not accurate, but shows the
concept of A to D conversion. 
Many microcontrollers have an input that can read any value of voltage from 0v to 5v (and higher by using a
voltage divider network). Normally there are 256 steps in this range to produce a resolution of approx 20mV
for 0-5v scale.  This is called an A to D input (A to D
converter - analogue input) and is ideal for measuring
voltages and other values that are classified as
ANALOGUE. A very simple external circuit can be added
to measure different parameters such as the change in
resistance of a temperature probe and other analogue
devices. 
The PIC16F84 does not have an internal A to D converter,
however we can create an A to D feature by using two
lines and a sub-routine. 
To create an analogue input, a capacitor "C" is connected
in series with an unknown resistor (R) and charged via one
of the lines of the microcontroller. The diagram below shows how this is done.

The first diagram shows a resistor and capacitor connected in series. This is called a TIME DELAY circuit.
The capacitor is initially uncharged and the resistor charges the capacitor to a specified value. The time taken
to reach this value is called the Time Delay. 
The mid-point of the two components is called the "detection point." 
It does not matter if the resistor is above the capacitor or below. The same Delay Time (or a similar time) will
be produced.
In the second diagram the capacitor is above the resistor and if the top line is taken HIGH, the voltage at the
detection point will fall to a specified value after a Delay Time. 
If the value of the resistor is changed, the time taken for the voltage at the detection point to reach a specified
value will alter. 
That's exactly what happens in the third circuit above. 
The micro monitors the voltage on the detection point and when it reaches the lower threshold for the input
line, the program displays the "count-value" on the 8 LEDs. 
The other feature that has to be worked out is the time taken for the capacitor to charge. In our circuit, the
capacitor has charged before 255 loops have been executed (when the pot is at maximum resistance) and

26
we cannot same at a faster rate, so the maximum display-value is "DF." To obtain a full reading, the capacitor
will need to be increased in value. 

                    ;Expt8.asm
                    ;Project: 0-256 parts of an input
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
MOVLW 1F
MOVWF 05 ;Make port A input
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 06 ;Clear display
GOTO Main

Delay MOVLW 80h  ;Create 100mS delay


MOVWF 1B 
DelayA DECFSZ 1A,1
GOTO DelayA
DECFSZ 1B,1
GOTO DelayA
RETURN

Delay2 NOP  ;Create approx 250mS delay


DECFSZ 1A,1
GOTO Delay2
DECFSZ 1B,1
GOTO Delay2
RETURN

Look CLRF 0C   ;Count-down file


BSF 06,7  ;Take cap HIGH
Look2 NOP ;Look2 is the counting and looking loop
INCF 0C,1
BTFSC 05,4  ;Is input LOW?
GOTO Look2
Look3 MOVF 0C,0  ;Put file 0C into W
MOVWF 06   ;Output to 8 LEDs
CALL Delay2
CALL Delay2
CALL Delay2
BCF 06,7  ;Take cap low 
CALL DelayA  ;100mS delay
RETURN

Main CALL Look


GOTO Main

END ;Tells assembler end of program

EXPERIMENT 8a
Measuring Resistance
This experiment measures resistance. You can get very low-cost digital multimeters to measure resistance
and display the value on a four digit display. We cannot compare with cost and complexity of this type of
27
display, but our circuit has other features. It will activate a device when a particular value of resistance is
detected. This allows measurement of degrees of rotation of a potentiometer or the conductivity of a liquid
(via two probes), plus many other areas where resistance values change. 
Our demonstration program uses a potentiometer to detect resistance in the range  0k to 10k however any
other range can be read, by changing the value of C. The accuracy of the circuit is determined by the
tolerance of C (most capacitors are 10%). The time taken to produce a low on the input is used as a jump
value in a look-up table and a display-value is obtained for the 7-segment display. For simplicity, the values 0
to 9, plus "-" overflow, are displayed. Further experiments show two and three-digit accuracy. 

                    ;Expt8a.asm
                    ;Project: Resistance Scale:0-9
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
MOVLW 1F
MOVWF 05 ;Make port A input
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 06 ;Clear display
GOTO Main

Table ADDWF 02h,1  ;Add W to the Program Counter to create a jump.


RETLW 3Fh  ;0    format= gfedcba
RETLW 06h  ;1    If any table value has a leading letter, it must be
RETLW 5Bh   ;2 preceded with a "0." E.g: 0A3h, 0FFh, 0CCh
RETLW 4Fh  ;3
RETLW 66h  ;4
RETLW 6Dh  ;5
RETLW 7Dh  ;6
RETLW 07h  ;7
RETLW 7Fh  ;8
RETLW 6Fh  ;9
RETLW 40h  "-" overflow

Delay MOVLW 80h  ;Create 100mS delay


MOVWF 1B 
DelayA DECFSZ 1A,1
GOTO DelayA
DECFSZ 1B,1
GOTO DelayA
RETURN

Delay2 MOVLW 20h  ;Create "Look" delay


MOVWF 1A 
DelayB DECFSZ 1A,1
GOTO DelayB 
RETURN

Look CLRF 0C  ;Count-down file 


BSF 06,7  ;Take cap HIGH
Look2 CALL Delay2  ;This produces a long delay between looks
BTFSS 05,4  ;Is input LOW?
GOTO Look3
INCF 0C,1
GOTO Look2
Look3 MOVF 0C,0  ;Put file 0C into W

28
CALL Table 
MOVWF 06  ;Output to 7-Segment display
CALL Delay
BCF 06,7  ;Take cap low 
CALL Delay  ;100mS delay
RETURN
Main CALL Look
GOTO Main

END

EXPERIMENT 9
Pulse Detection with a coil
This experiment uses a coil to detect pulses. A magnet is moved past a coil and this creates a voltage in the
turns of the coil. 
This is ideal for picking up the rotation of a shaft. It is non-mechanical and will have an infinite life. 
Reed switches have a very short life when used rapidly to detect shaft rotation and have a fairly low speed of
operation. 
The output voltage of a coil is fairly low and needs two stages of amplification for the signal to be large
enough to be detected by the input of a microcontroller.
The clever arrangement on the front end of the analogue amplifier of the PIC LAB-1 board allows a
microphone or coil to be fitted. The coil does not require the resistor, (it is required by the electret
microphone) however it does not affect the operation.  This demonstration program increments the 7-
segment display. 
This allows a count-of-ten however experiments on the web include a 2 and 3-digit readout from the 7-
segment display and an RPM counter.  
The advantage of a magnetic pickup is the lack of switch-noise.  The pulses from the pick-up are very clean
but must be debounced for low-speed detection. The 2-stage amplifier increases the sinewave signal and
over-amplifies it to produce a rail-to-rail signal commonly called a square-wave or digital signal.

                    ;Expt9.asm
                    ;Project: Pulse Detection with a coil
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
MOVLW 02 ;Load W with 0000 0010
MOVWF 05 ;Make RA1 input
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 1F ;Clear the button-press file
CLRF 06 ;Clear display
GOTO Main

Table ADDWF 02h,1 ;format= gfedcba


RETLW 3Fh ;0      If any table value has a leading letter, it must be 
RETLW 06h ;1       preceded with a "0."   E.g: 0A3h, 0FFh, 0CCh
RETLW 5Bh ;2
RETLW 4Fh ;3
RETLW 66h ;4
RETLW 6Dh ;5
RETLW 7Dh ;6
RETLW 07h ;7
RETLW 7Fh ;8
RETLW 6Fh ;9 

29
Delay NOP ;Create 1mS delay
DECFSZ 1A,1
GOTO Delay
RETURN

Main CLRF 1E ;Holds the count-value


Main1 BTFSS 05,0 ;Test the input line on port A
GOTO Main2 ;LOW detected
BTFSC 1F,0 ;HIGH detected. First pass of routine?
GOTO Main1 ;HIGH already detected
INCF 1E,1 ;First time detected. Increment count.
MOVLW 0A ;Has count reached ten?
XORWF 1E,0 ;Compare file 1E with ten
BTFSC 03,2 ;Check the zero flag in Status file
GOTO Main ;Count has reached ten
MOVF 1E,0 ;Copy count into W
CALL Table ;W will return with display-value
MOVWF 06 ;Output display value
CALL Delay ;Debounce the coil
BSF 1F,0 ;Set detection flag
GOTO Main1 ;Loop Main1
BCF 1F,0 ;Clear detection flag
Main2 GOTO Main1 ;Loop Main1

END ;Tells assembler end of program

EXPERIMENT 10
Temperature Detection
There are many expensive devices to detect temperature (thermal probes) but the cheapest is an ordinary
diode. 
The voltage across a diode decreases 2mV for each °C rise in temperature. Providing a sensitive circuit is
connected to the diode, a temperate change can be detected. 
There is a problem with temperature-detecting circuits. The transistors in the circuit also have semiconductor
junctions and the voltage across them changes at the same rate as the diode. This will upset the detecting
process if the circuit and the detector are increasing in temperature at the same time and if some form of
compensation is not included.
The amplifying circuit must be protected from a temperature-rise or some form of thermal cancelling must be
included, if you want an accurate readout. 
For simplicity, we have not provided any stabilizing circuit in this project. We are assuming the interfacing
circuitry is not subject to temperature variations. On the PIC LAB-1 PC board, the base-bias circuit for the
amplifying stage (for the "temp probe") has a fixed reference voltage produced by the natural characteristic of
2.1v across a green LED, making a total reference voltage of 4.2v.
This goes part-way to the design of a stable amplifying stage. 
The display shows in binary on the 8 LEDs. This gives a readout of 255 divisions and the circuit is so stable
that the display will remain static. 
The first thing you can do is fit the 10k pot to the "Temp Probe" input and rotate the shaft. 
You will need to turn the shaft very slowly until you see the display begin to change. As the resistance of the
pot is reduced, the display will start to fill up and at FF, it will be full. If the resistance is reduced further, the
counter-file 0C will fill for the second time and produce a false reading. This is something that has to be
prevented in a final version. 
The pot has only a very small range where it is effective as it is simulating the voltage across a forward-
biased diode and our tests showed this to be 500mV at room temperature. Remove the pot and fit the diode.
A readout of approx mid-range will be produced.
The readout on the display increases as the temperature increases since the program INCrements the count-
file 0C. By DECrementing the counter-file 0C, the display will decrease as the temperature rises. 
The diode is so sensitive that a slight amount of warm air over to it will alter the display. 
If you touch one leg of the diode, the heat of your finger will also alter the display. 
Try not to touch both leads at the same time as the resistance of your fingers will upset the reading. Bring a
hot soldering iron near the diode will cause the display will change - proving the diode is very sensitive to
30
temperature change. 
The display is not graduated and this is something we will provide in a future experiment.   There are two
parts of the program that will need to be worked on, to produce a display.  One part determines the
temperature and the other determines the resolution - in other words the number of increments (or divisions)
for each degree C or F. 
The results are then placed in a table. 

                    ;Expt10.asm
                    ;Project: Temperature Detection
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
MOVLW 04 ;Load W with 0000 0100
MOVWF 05 ;Make RA2 input & RA3 output
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 06 ;Clear display
GOTO Main

Delay NOP  ;Create approx 250mS delay


DECFSZ 1A,1
GOTO Delay
DECFSZ 1B,1
GOTO Delay
RETURN

Delay2 MOVLW 02h   ;Create 9uS delay


MOVWF 1A  
DECFSZ 1A,1 
DelayB GOTO DelayB  
RETURN 

CLRF 0C  ;Count-down file 


Look BSF 05,3  ;Take cap HIGH
CALL Delay2  ;15uS delay between looks
INCF 0C,1 
Look2 BTFSC 05,2  ;Is input LOW?
GOTO Look2
MOVF 0C,0  ;Put file 0C into W
MOVWF 06   ;Output to 8 LEDs
Look3 CALL Delay    
BSF 03,5  ;Go to Bank 1 
MOVLW 00  ;Load W with 0000 0000
MOVWF 05  ;Make RA2 output & RA3 output
BCF 03,5  ;Go to Bank 0 - the program memory area. 
BCF 05,3 ;Take cap low
NOP
BCF 05,2  ;Discharge capacitor
CALL Delay  ;250mS delay
BSF 03,5  ;Go to Bank 1 
MOVLW 04  ;Load W with 0000 0100
MOVWF 05  ;Make RA2 input & RA3 output
BCF 03,5  ;Go to Bank 0 - the program memory area. 
RETURN

CALL Look

31
Main GOTO Main

END ;Tells assembler end of program

EXPERIMENT 11
Sound Detection
There is an enormous range of possibilities with this application. You may want to detect a low-frequency
sound, a specific frequency, a length of tone or a combination of audio signals. 
All these applications are possible with a microcontroller as the program does all the "sorting out" and you
can display the result on a LED or a piezo. 
Sometimes the design of the amplifying stages can assist in detecting a particular frequency or amplitude.
More details are provided on the website.
To see the display respond to sounds picked up by the microphone, load the program for Experiment 9 and fit
the microphone to the "mic/coil" input. The 7-segment display will increment rapidly when HIGH's and LOW's
are being detected. 
Experiment 11 is an improvement on Experiment 9. A LED is turned on for 1mS each time a HIGH is
detected.  
Any noise picked up by the microphone is amplified by two transistor stages and converted to a digital
signal. The signal is OVER-AMPLIFIED (to a point of distortion - but this does not matter as we are not
listening to it as an audio signal) so that the amplitude is guaranteed to pass the upper and lower thresholds
of the input. 
The program detects a rise and fall in amplitude of the signal to identify a complete cycle. The program
actually detects NOISE and further programs on the web detect frequency (such as a whistle) to produce a
result.  

                    ;Expt11.asm
                    ;Project: Sound Detection
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
MOVLW 02 ;Load W with 0000 0010
MOVWF 05 ;Make RA1 input
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 1F ;Clear detection flag
CLRF 05 ;Clear the display
CLRF 06 ;Clear the display
GOTO Main

Delay NOP ;Create 1mS delay


DECFSZ 1A,1
GOTO Delay
RETURN

Main BTFSS 05,1 ;Test the input line on port A


GOTO Main1 ;LOW detected
BTFSC 1F,0 ;HIGH detected. First pass of routine?
GOTO Main ;HIGH already detected
BSF 06,0 ;Turn on LED
CALL Delay
BCF 06,0 ;Turn off LED
BSF 1F,0 ;Set the detection flag
GOTO Main
Main1 BCF 1F,0 ;Clear the detection flag
GOTO Main

32
END ;Tells assembler end of program

EXPERIMENT 11a
Sound-to-Frequency
This experiment converts Sound (such as a whistle) to Frequency. The row of 8 LEDs show the frequency as
a binary value. The scale is not calibrated. The program shows the application of the internal timer (TMR0). It
is set to count in the background (with a pre-scaler). The pre-scaler divides the clock frequency by 256 in our
case and when the timer rolls over from FF to 00, the timer overflow flag (T0IF) is SET. This flag is checked
in the program for a "time-up" signal.   

                    ;Expt11a.asm
                    ;Project: Sound to Frequency
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 00  ;Start of memory for program.
SetUp BSF 03,5  ;Go to Bank 1
CLRF 06  ;Make all port B output 
MOVLW 02  ;Load W with 0000 0010
MOVWF 05  ;Make RA1 input
BCF 01,5  ;Make sure timer is incremented via internal clock
BCF 01,3  ;Make sure Prescaler is assigned to TMR0
BSF 01,0  ;PS0 (OPTION) Timer0 rate 1:256 (256x256uS)
BSF 01,1  ;PS1 when PS0, PS1 and PS2 are SET
BSF 01,2  ;PS2
BCF 03,5  ;Go to Bank 0 - the program memory area. 
BCF 0B,7  ;Disable all interrupts 
BCF 0B,5   ;Disable the TMR0 Interrupt
CLRF 05  ;Clear display
CLRF 06  ;Clear display
GOTO Main

Delay MOVLW 64h  ;Load with 100. Create 100mS delay


MOVWF 1B
DelayA NOP 
DECFSZ 1A,1
GOTO DelayA
DECFSZ 1B,1
GOTO DelayA
RETURN

Delay1 MOVLW 10 


MOVWF 1A  ;Tells assembler end of program
DelayB DECFSZ 1A,1
GOTO DelayB
RETURN 

Display BSF 0B,2  ;reset the "time-up" flag


MOVF 0C,0  ;Put count file into W
MOVWF 06  ;Display the count on 8 LEDs 
CALL Delay 
GOTO Main

Main CLRF 0Ch  ;Holds the count


BTFSS 05,1  ;Test input line on port A
GOTO Main  ;LOW detected

33
CLRF 01  ;clear TMR0 register 
BCF 0B,2  ;Clear TMR0 overflow interrupt flag 
Main1 CALL Delay1  ;Reduce the number of "looks" per sec
INCF 0C,1  ;Increment the count
Main2 BTFSC 05,1  ;Test input line on port A
GOTO Main2  ;Input is still HIGH 
Main3 CALL Delay1  ;Reduce the number of "looks" per sec
BTFSS 05,1  ;Test input line on port A
GOTO Main3  ;Still LOW 
BTFSS 0B,2  ;Check the "time-up" flag
GOTO Main1  ;HIGH detected 
GOTO Display 

END

PIC LAB-1
P5

 
When you have finished the experiments, go to "21" a strategy game.

EXPERIMENT 11b
Whistle-On  Whistle-Off
This experiment turns on a LED when a whistle is detected. The LED turns off when the whistle is detected
for the second time.  
                    ;Expt11b.asm
                    ;Project: Whistle-On  Whistle-Off
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 00  ;Start of memory for program.
SetUp BSF 03,5  ;Go to Bank 1
CLRF 06   ;Make all port B output
MOVLW 02  ;Load W with 0000 0010
MOVWF 05  ;Make RA1 input 
BCF 03,5  ;Go to Bank 0 - the program memory area. 
CLRF 1F  ;Clear flag file
CLRF 05  ;Clear the display
CLRF 06  ;Clear the display
GOTO Main

Delay NOP  ; Create 1mS delay


DECFSZ 1A,1
GOTO Delay
RETURN

Delay1 MOVLW 40h

34
MOVWF 1B
DelayA DECFSZ 1A,1
GOTO DelayA
DECFSZ 1B,1
GOTO DelayA
RETURN

Look BCF 1F,0  ;Clear the "whistle" flag


MOVLW 040h  ;Number of loops
MOVWF 0E  ;Loops file
CLRF 0Ch  ;Holds the LOW count 
Look1 CALL Delay
BTFSC 05,1 
GOTO look2
INCF 0Ch,1  ;LOW detected
Look2 DECFSZ 0E,1
GOTO Look1
MOVLW 18h
SUBWF 0Ch,0
BTFSS 03,0  ;Test Carry flag. If set C=more than 10h 
RETURN
BSF 1F,0  ;Whistle detected
RETURN 

Main CALL Look


BTFSS 1F,0
GOTO Main  ;No whistle
MOVLW 04  ;Whistle - turn on display
MOVWF 06
Main1 CALL Delay1 
CALL Look 
BTFSC 1F,0
GOTO Main1  ;whistle
Main2 CALL Delay1
CALL Look
BTFSS 1F,0
GOTO Main2  ;No whistle
MOVLW 00  ;Whistle - turn off display
MOVWF 06
Main3 CALL Delay1 
CALL Look 
BTFSC 1F,0
GOTO Main3   ;whistle
GOTO Main  ;no whistle

END

EXPERIMENT 12
Light Detection
This experiment detects the presence of light. A photo-darlington transistor is connected to the circuit via a
plug and socket and exposed to light. The change in resistance of the photo-darlington transistor creates a
voltage change across it and this is amplified by the circuit and delivered to an input of the
microcontroller. The program turns on the 8 LEDs when the photo-darlington transistor detects change in
illumination. 
The photo-darlington transistor is connected to the circuit via a capacitor and only CHANGES in illumination
are detected. 
If the illumination is decreased, a point will be obtained where the circuit is sensitive to the changes in supply
rail voltage. At this point the circuit will start to oscillate or MOTOR-BOAT. 
The circuit must be re-designed to prevent this from occurring.  
35
If the photo-darlington transistor is placed in a room with incandescent lighting, the 50 or 60Hz from the light
will be detected. These pulses must be dealt with by the program to obtain a reliable HIGH/LOW pulse. 

                    ;Expt12.asm
                    ;Project: Light Detection
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0  ;This is the start of memory for the program.
SetUp BSF 03,5  ;Go to Bank 1
CLRF 06  ;Make all port B output
MOVLW 02  ;Load W with 0000 0010
MOVWF 05  ;Make RA1 input
BCF 03,5  ;Go to Bank 0 - the program memory area. 
CLRF 06  ;Clear display
GOTO Main

Main BTFSS 05,1  ;Test the input line on port A


GOTO Main1  ;
MOVLW 00h  ;
MOVWF 06  ;Turn off LEDs 
GOTO Main
Main1 MOVLW 0FFh  ;
MOVWF 06  ;Turn on LEDs 
GOTO Main

END ;Tells assembler end of program

GOING FURTHER
Once you complete the experiments in this project, you will want to write your own programs. 
The website includes a PIC template called "Blank_84.asm" This is a blank template with the set-up code
and headings, in place. 
The template can be found by clicking "Blank_84.asm" for the file. Put it into a text program such as
TEXTPAD,  WORDPAD or EditPad. EditPad is on the site for downloading and is by far the best text
program.
Copy "Blank_84.asm" and give it another name so the original is available again. 
Simply delete any code that is not needed and add your code to the sub-routines provided on the template.  
It is best to use the pre-formatted template as it is important not to have any hidden formatting code to upset
the assembler when it is being assembled.  
If a program fails to assemble, re-type the faulty lines onto the template and re-assemble, as it may have
picked up some hidden tabulating code or imaginary spaces. This is something that took us hours to locate.
The assembler was looking for a label with an extra three spaces!
The "Burn" program for the Multi-Chip Programmer is included on the website as a .zip file and full
instructions are given for setting up the Multi-Chip Programmer.   

PIC LAB-1 FOR SCIENCE QUEST


The experiments in this article represent the starting-point in each group. It's possible to expand any of the
applications to incorporate monitoring or recording an event or combining two or more to create a completely
new operation. 
On the website we have added a page for Reader Experiments. You are invited to send in your  ideas and
programs and we will add them so you can share your ideas with with others.  
PIC LAB-1 is ideal as the foundation for a Science Quest project. The applications are almost limitless and
the design of the PC board makes them very easy to implement. The secret is the microcontroller. It removes
the need for lots of individual chips for counting, timing, displaying etc and reduces the complexity of a
circuit. 
If you intend entering a project for a quest, it is essential to prove the concept has been developed by
yourself. The only way to do this is to keep your notes and prototypes and hand them in with the final design. 
You can detect pulses from a switch, magnet, light-source, as well as audio frequencies, temperature (via a
36
diode), degrees of rotation of a potentiometer, resistance, voltage, magnetism (hall effect device or coil) and
others. The output can be on the 7-segment display or something you have added. 
But the most impressive part of your project will be to do something new. 
It may be to detect a scent, bacteria growth, onset of a fainting spell or epileptic fit, water purifying through a
natural reed-bed, removing odours from a car in heavy traffic, guiding a wheelchair in a straight line,
preventing super-market shopping carts being stolen, preventing cars colliding in the fog, guiding survivors
through a smoke-filled building, making a sucking/blowing device for bed-ridden patients to operate
equipment, TV's etc. or one of a million applications needing processing power.  There are thousands of
simple requirements for invalid people, and this is where recognition will be highlighted.
You only need to design to the stage of preliminary findings. This will make your entry unique and you can
take on further development at a later date. 
It is the concept that will win you an award and PIC LAB-1 can help with many of these ideas.    

WRITING A PROGRAM
To write a program for the PIC16F84 microcontroller, or modify any of the programs we have written,  you will
need the instruction-set. This consists of about 35 "English-like" instructions, that are able to be read by you
as well as a program that will convert them into machine-code numbers for the microcontroller. 
These "English-like" instructions are called mnemonics and the Instruction-Set for the PIC16F84 is available
by clicking: F84INSTRUCTION-SET. 
Definitions for each instruction plus articles on PIC Programming are available in the "PIC PROGRAMMING
COURSE." This is on the POPTRONICS Interactive Edition website.  Easy subscribing details are provided
on a link. 
Go to the menu of your computer and create a new folder called Experiments. Place it inside your  PIC LAB-
1 folder.
You will need blank template on which you will be able to write your own programs.
Download the blank template zip file into Experiments folder. Extract it to produce BlankF84.asm
Open a text editor program such as TEXTPAD or NOTEPAD and open the file BlankF84.asm   Rename it to
Expt-1.asm  or the name of your new project.
Edit the code on the template and add your own code to perform a simple operation that takes an input signal
from a switch and outputs the result to a LED (copy some of the code from an experiment and add a few lines
of your own).
Save the file. Make sure it is saved as .asm as the text editor will naturally save it as a .txt file.
Go to the Site Map above and click on MPASM
Move MPASM.exe to your desktop folder.
It will appear on your front screen. 
Click on the Icon on your desktop and MPASM v02.70 will appear. Make sure the Radix is Hexadecimal,
Warning Level: All Messages, Hex Output: INHX8M, Generated Files: List File, Case Sensitive: NOT Ticked,
Macro Expansion: Default, Processor: 16F84, Tab Size: 8, Save Settings on Exit: TICKED. 
Press Browse to locate Expt-1.asm file. The file name will appear in the top address box. Press Assemble it
to get a small dialog box with NO error and no warnings. This will produce a .cod  .hex and .lst in the same
directory as .asm   
If you get an error, the .hex file will not be generated, so go to your Text Editor and load the .lst file. 
Read the .lst file and it will explain where the fault is located. 
Go to the .asm file and make the correction(s). 
Re-assemble the file again. 
Here's a tip: To make sure you are actually assembling the corrected version, I suggest you save the file as:
Expt-1a.asm   
When the file assembles correctly and a green background appears on the dialog box after assembly, you
will have a .hex file in the same directory. 
You now need a program to take the .hex file and burn it into the chip using the Multi Chip Programmer. 
The software program is: ICPROG.
See IC-Prog.exe  and a help file: ICPROG-Help (IC-Prog.chm).
 Place ICPROG.exe into your desktop folder and it will appear on your screen.  
Go you your front-screen (desktop) and open a text editor program such as TEXTPAD or NOTEPAD. Open
the file to be burnt, such as:  Expt-1.hex
Open ICPROG.
On the small window showing the types of chips the programmer is able to program, select PIC 16F84. 
In the oscillator window, select RC. 
In the fuses windows, remove all the ticks. 
Click on the "open file" icon on the left hand side of the screen. Find Expt1.hex and load it into the

37
programmer. A tick will appear in the WDT window to indicate a file has been loaded. Remove the tick. 
Make sure Multi Chip Programmer has been fitted to "Com1" via a serial cable and the red LED on the Multi
Chip Programmer is active.
Click on the IC Icon with the "lightening" and a dialog box with "Do you really want the program the device?"
will appear. 
Click "yes" and the orange and green LEDs will illuminate on the Multi Chip Programmer and the screen will
indicate the chip has been programmed correctly.   
Remove the chip and fit it to the PIC LAB-1 project. Fit any necessary input devices and switch the project
ON. The LEDs on the output will respond.   
If every thing has gone successfully, you will have "burnt" your first program.
Only some of the steps above will have to be repeated, but this is how the program comes along. 
Add only a few lines at a time so that fault-finding will be limited to a small part of the program. 
Once you get the basics working you can add add sub-routines for counting, displaying, etc and gradually
build up the project to impressive dimensions.
You will find  many of your requirements can be met with the components on the PIC LAB-1 and by simply
adding a sub-board, a more-advanced project can be created. 
When you get the design working, you can CAD the artwork for the board. Don't forget to include a top layer
or legend. This is absolutely essential if you want to produce a quality item - but is not essential for a Science
Project. 
All the programs needed to create a Printed Circuit Board are available on the web. 

CREATING A PROJECT
To create a project you need to follow a few simple steps. 
But before you start, there is one factor you must remember. Everything you do must consist of small
increments and it is essential to start at the beginning with something very simple. This is the only way to
create a program. 
As each stage of a program works correctly, it can be saved with its own reference number so that you can
go back to it if a problem develops further down the track. 
But writing a program is not the first step.  
A circuit needs to be developed. You should look through books and magazines to see how it has been done
using discrete technology.  Collect as much information as possible to help you with your design and see the
complexity of the circuit.
Projects requiring 3 or more chips will be in the "economics zone" as well as those requiring more features
than already available.   
The aim will be to use as many of the "building blocks" on the PIC LAB-1 as possible. They can be modified
and extended to suit your application.
The circuit is initially laid out as BLOCKS showing the input, the micro and output sections. Pin numbers and
component values do not have to be worked out until later. 
Start with a simple part of the circuit such as turning on a LED when a switch, is pressed. 
Write a program to make sure the micro is detecting the input device and outputting the result on the LED.  
Pick out any of the experiments we have designed for the PIC LAB-1 and see how we have written the
instructions. Add instructions of your own. 
Make sure this part is working before adding another section.
Gradually build up the operation of the project by adding a small section at a time. It's a slow process but it's
sure. 
Quite often you can borrow previous routines to speed up the process and eventually the project is complete. 

CONCLUSION
This is not the end. It's just the beginning. Your rewards are just about to start. 
There are so many things you can do. 
We have covered many ideas in this project and it's just a matter of looking into something that "sparks an
interest" and running with it. 
Everything you need is on the site and we have produced more pages to show how to go further with more
advanced programming. 
   
The next Pages . . .
The next pages explain the theory behind some of the input/output devices and how to connect them to a
microcontroller.
We also have many more experiments involving more-complex programming with two or more elements. 
38
Also included is a complete LIBRARY OF ROUTINES for the PIC LAB-1, arranged in alphabetical order. 
Each time you need a step in the development of a program, go to the library for suggested instructions. This
will help you build a program very quickly and up to 80% to 90% of most programs can be created this way. 

The next page has a strategy project called "21". It is the old 21 matches game where you take 1, 2, or 3
matches, leaving your opponent with the last match. It shows programming to a tee. Especially the "strategy"
section, where all the "thinking" takes place. 
This is possibly the most complex type of project to be covered, using a PIC16F84 chip but the straight-
forward layout will help you work through each of the sections.

Reader Experiments

This page is dedicated to Reader Feedback in the form of experiments and ideas. 
The first program was sent in by Miroslav Kostecki of elabtronics (www.labtron.com.au)  the designers of
Icon Assembler. 
I asked him for a program that incremented the 7-segment display. I expected a program similar to
Experiment 4: Counting on the 7-segment display.  I actually asked for a program in Icon Assembler so I
could compare the ease of understanding the Icon Assembler approach. I received the Icon program and
loaded it into Icon Assembler but it was so over-the-top that I closed the program and realised it was not for
me. 
The Icon program was spread over 3 pages and was filled with circles and triangles and half-finished words
that made the concept 10 times more complex than the hand-assembly approach I am advocating. 
I don't mind if someone comes up with something that makes writing a program easier and more
understandable, but to add to the complexity by 1,000% and attempt to hood-wink me with the suggestion
that the new approach is the way to go, I think not. 
However, here's the first readers program. Copy it, put it into a text editor, burn it into a PIC chip, and put it in
the PIC LAB-1 project. 
This program serves as a very good example of how other people work and think. Miroslav Kostecki is a
brilliant programmer and operates at a very high level of thought. Even a simple program such as the one
below uses a higher level of thought than we have provided in our set of experiments, and is more complex
than expected.  
But this is very important. When you see a combination of reasoning from different minds, you can combine
the common points and see how to tackle a specific problem from different stand-points. 
The first thing you will notice is the layout. 
It is different to our recommended format and the inclusion of the interrupt vector adds to the complexity. The
interrupt instructions are not functional as the interrupt has not been set up, and maybe this program is left-
over from a larger example.
All programs naturally starts at address "000" where it sees the instruction GOTO 5. The instruction ORG 0,
does not have to be included as the assembler naturally starts programming at this address. This causes the
micro to jump over the instruction GOTO Interrupt, at location 4, and operate on the instruction __CONFIG
0Bh, at address 5.  This configuration turns off the watchdog timer, invokes the external RC oscillator mode,
and turns on code-protect.
The instruction: MOVLW  B'10000000'   OPTION    puts the value 80h into the OPTION register to disable
the pull-ups on port B. This feature only applies when any of port B lines are INPUT, and does not apply to
this program - another unnecessary instruction. 
The programmer has used the TRIS operation to determine which lines of each port will be input or output. 
The micro then continues directly to Start, where it clears the count file (file 12h) and then goes to Main1.
The output port is initially cleared and so the program starts with a blank display. 
The program basically consists of two loops. The "button not pressed" loop is in dloop, where the last value
placed in file 06 will appear on the screen. The "button pressed" loop is Main1 and this includes CALL
display. 
If the button is NOT pressed, the micro carries out the first and third instructions of Main1 and then goes to
dloop where it carries out the first and second instructions, in a continuous loop. The screen will display the
last value placed in file 06.
When the button is pressed, the first instruction in dloop gets the micro out of the loop and back to Main1,
where the micro goes to display. The instruction incf count,f in display increments the "jump value" for the
table, performs a SUB and  looks in the STATUS file to see if the zero flag has been set. If this flag is SET,
the 'end of table' has been reached and the jump value is zeroed. 
A display value is obtained from the table and passed to port B for outputting to the display. This action is
repeated and the display is changed very rapidly to produce a "figure-8." 
39
As soon as the button is released, the micro goes to the above-mentioned routine with the last display-value
appearing on the 7-segment display. 
This is not what I requested and the program should be called RANDOM NUMBER or DICE. 
By changing the values in the table to include only the numbers 1 to 6, and limiting the jump value to 6, a
DICE program can be produced.  
GOTO $ is also not used (it is a BASIC language instruction meaning GOTO String Data) and is only
included to confuse you. All these misleading instructions from a pioneer of a program designed to help
beginners understand programming!  If someone can convince me that Icon Assembler is easier to
understand than hand-assembly, I will offer a $10,000 prize! 
My challenge to Icon Assembly is a program similar to Expt1 test  but with lines of code that can be changed
on the screen. It can have circles and triangles to make the program colourful and fancy but really only needs
each instruction to be taken from a library and dragged into place. This concept will make a superb assembly
program where you can see the whole program at a glance and the endless page allows you to scroll down
the whole program.
The 7-segment program supplied by elabtronics is already 3 pages long in Icon Assembly and trying to
follow the flow of the program is absolutely impossible. 
The program below is already more complex than our layout, so you can imagine adding 1,000% more
complexity to this is going to make it an Archimedean entanglement! 

;Reader1.asm
;Project: Button increments 7-seg
LIST p=16C84,r=DEC ; Put assembler into PIC16C84 mode.
; r=DEC means decimal numbers are
; assumed if 'B' or 'h' not specified
;include "p16f84.inc"

;**************Declare Variables************************
count equ 12
x equ 13
;**************Initialise interrupt subroutine**********
goto 5
ORG 4
goto interrupt
ORG 5
;**************Initialise Ports*************************
__CONFIG 0Bh
MOVLW B'10000000'
OPTION
CLRF 5
MOVLW B'00011111'
TRIS 5
CLRF 6
MOVLW B'00000000'
TRIS 6

;**************Start Of Main Program********************


Start ; Button Increments a Seven Segment Display
; PORTA,0 is connected to the button
; PORTB to display, format=gfedcba0

clrf count ;count = 0


Main1 btfsc 5,0 ;If PORTA Bit 0 OFF Skip Next
call display
call Delay
goto Main1
goto $ ;Safety Caching Loop

;**************Subroutines******************************

40
interrupt
retfie ;Interrupt

Delay
dloop btfss 5,0 ;If PORTA Bit 0 ON Skip Next
goto dloop
decfsz x,f ;x = x -1 , Skip Next If Zero
goto dloop
return ;Return

display
incf count,f ;count = count + 1
movlw 0Ah ;w = 10
subwf count,w ;w = count - w
btfsc 3,2 ;If STATUS Bit2 OFF Skip Next
clrf count ;count = 0
movf count,w ;w = count
call table
movwf 6 ;PORTB = w
return ;Return

table addwf 2,f ;PCL = PCL + w


retlw H'3F' ;w = H'3F'
retlw H'06' ;w = H'06'
retlw H'5B' ;w = H'5B'
retlw H'4F' ;w = H'4F'
retlw H'66' ;w = H'66'
retlw H'6D' ;w = H'6D'
retlw H'7D' ;w = H'7D'
retlw H'07' ;w = H'07'
retlw H'7F' ;w = H'7F'
retlw H'6F' ;w = H'6F'

End

;Reader 2.asm
;Project: To come
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
MOVLW 01 ;Load W with 0000 0001
MOVLW 05 ;Make RA0 input
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 1F ;Clear the button-press file
CLRF 06 ;Blank the display
GOTO Main

Delay NOP ;Create approx 250mS delay


DECFSZ 1A,1
GOTO Delay
DECFSZ 1B,1
GOTO Delay
RETURN

Delay2 NOP ;Create 1mS debounce delay

41
DECFSZ 1A,1
GOTO Delay2
RETURN

Sw BTFSS 05,0 ;Test the push button


GOTO Sw3 ;Button not pressed
BTFSC 1F,2 ;Test end-of-flash flag
RETURN
BTFSC 1F,0 ;First pass?
RETLW 00 ;No
BTFSS 1F,1 ;Test first-press flag
GOTO Sw2 ;First press
BSF 06,0 ;Button has been pressed twice. Illuminate LED
CALL Delay ;Keep LED on
CALL Delay ;Keep LED on
BCF 1F,1 ;Clear second-push flag bit
BSF 1F,2 ;Set end-of-flash flag
BCF 06,0 ;Turn LED off
RETURN
BSF 1F,1 ;Set the first-press flag
BSF 1F,0 ;Set button pass flag bit
RETURN
BCF 1F,0 ;Clear button pass flag bit
BCF 1F,2 ;Clear end-of-flash flag
RETURN

Main CALL Sw
CALL Delay2
other instructions ;Carry out other instructions
other instructions
BCF 1F,0 ;Clear first-push flag bit
GOTO Main

END ;Tells assembler end of program

"21"
P5a  

This is the old game of "21 MATCHES." 


It's a very simple game in which 21 matches are laid on the table in a row and each player can take 1, 2, or 3
matches. The player taking the last match loses. 

It's one of the games that can be adapted for the PIC LAB-1 to show the concept of strategy and
"intelligence." 
It's YOU against the COMPUTER. 
The player goes first and takes 1, 2 or 3 matches by pressing the button 1, 2 or 3 times. On each press, the
number on the screen decrements. 
The screen shows: 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1.  
You can use matches or pen-and-paper to follow the game and try to work out the strategy used in the
program. 
The routines are fully documented in the program below but the actual strategy is not revealed. It's shown,
42
but not explained.  
We have especially done this to force you to sit down and follow the instructions. 
Now it's your turn to do some study. 
Computers are one of the most amazing things in the field of ARTIFICIAL INTELLIGENCE. 
By the mere fact that they are able to process information at an extremely rapid rate, the outcome can appear
as INTELLIGENCE. This program is the simplest example of this concept. It will beat you on your first few
games and hopefully you will "home-in" on the secret. 
Apart from providing the concept of "intelligence," the program shows how to create a number of sub-routines
to perform specific operations. Some of the routines have already been covered in our experiments, while the
strategy sub-routine is new. The program will work with any number of matches (at the beginning of a game)
and this can be altered by changing the value loaded into 0Ch in Main.

MACHINE CODE
"21" highlights the advantage creating a project with a microcontroller. The game requires a number of sub-
routines that perform operations similar to "thinking."
Try to carry out thinking routines with individual chips; you will need quite a number.
We say the PIC16F84 is equivalent to about 8 discrete chips, but in our case it would exceed 20!
As you build up a program, many sub-routines will need to carry out operations already produced by sub-
routines you have already created and it is simply a matter of adding a single line such as CALL Convert, or
CALL Display to take advantage of them. 
Providing you stick to our convention of using files 0C to 19h for general purpose use, files 1A, 1B, 1C, 1D,
1E for decrementing (for use in Delays) and file 1F for flags, you will be able to recognise the grouping for
each file.
The only major problem with Machine Code is identifying a value (such as 06) being loaded into a file  and
differentiating this from the name of a file (such as file 06). After a few hours of programming you will be able
to read the code without a mistake. 
But the main advantage of Machine Code is clarity. You are able to read the program exactly as the micro
will carry out the instructions and nothing is "hidden" behind an "interpreter" program. 
The complexity of "21" is about the highest you can get for microcontrollers in this range, and if you can follow
the routines in "21," you are well on the way to advanced programming. 
As you go to larger processors and controllers, remembering the names of the files and ports is quite difficult
and some form of assistance is needed. 
This is when you will be introduced to a system called "equates" where files are allocated names and these
names are used when programming. You will also need a higher-level language. 
But that's for the next microprocessor. We still haven't used one-quarter the memory in our device and as you
get larger and larger programs, many of the sub-routines will CALL previous sections and a program with
twice the complexity of say "21" may only occupy 10% more memory.  
1k of memory can hold a lot of sub-routines and a very impressive program can be produced. If you think 1k
or 2k is a small memory, try to fill it! 
It is interesting to note that a complete CHESS game has been produced in 1k of memory, with 4 levels of
play and a challenge factor of  7. It had very simple graphics but was one of the first programs to be produced
on a computer (the ZX80) - and this was nearly 30 years ago!

STRATEGY ALGORITHM
An algorithm is a program or routine that solves a problem in a finite number of steps. 
To be able to design a strategy routine or algorithm, you have to know all the combinations and permutation
of a particular operation. These are then condensed into a set of rules and a sequence of instructions is
produced to execute the requirements. 
There are different levels of programming and an algorithm is the highest. It needs to take into account all
the possible choices and come up with the best decision. Obviously we are not making the decisions
equivalent to a game of chess but there is still a choice to be made and an algorithm shows how to go about
creating a routine that covers "all bases."
There are different ways to do this. 
1. You can write a single routine to encompass all the possibilities of the game. 
        This is an  algorithm.
2. You can advance down the program and create a new set of decisions for the situation at-hand.
        This is called the linear method.
3. You can provide a table that produces an output for each possibility. 
        This is the table method. 
The table method is the simplest and the linear method is the next simplest. 

43
But our approach is to use an algorithm to cover all possibilities. This is the hardest and involves the most
complex programming.
No matter which arrangement is decided on, producing this section of a program is the most rewarding of all.
It gives a feeling of feedback and activity.
The three methods show that even the most complex part of a program can be carried out with very simple
programming steps or very advanced programming. 
Simple steps may take a few extra lines of code but when you have plenty of program-space, don't worry
about the "waste." 
Many of the experiments we have produced in this course carry out operations in a very simplistic way and
are not representative of advance-programming. But if the end result is the same, don't create complexities. 
In advanced-programming, there are a number of LOGIC commands that can be used to perform very
impressive operations in a very small number of steps. There are operations such as: SUBWF, ADDWF,
XORLW, XORWF etc and sometimes you have to carry out a bit-for-bit comparison to see exactly what has
been performed with each instruction.  

Download the program below into the PIC LAB-1 and play the game a number of times to get a feeling of the
sequence.  
The flow of the strategy algorithm is explained later. For now, try to work out as much of the program as you
can. 
The files for "21Match" can be found HERE.
Click and a window will open with the files. Locate Notepad.exe in the window and click on it.  Notepad will
open. Click on the file you want to open and slide it across to the Notepad window. The file will appear!

                    ;21Match.asm
                    ;Project: "21-MATCHES" Game
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;Start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
MOVLW 03 ;Load W with 0000 0011
MOVWF 05 ;Make RA0, RA1 input
CLRF 06 ;Make all port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 11h ;Clear the random number file
CLRF 14h ;Clear the "3-times button pressed" file
CLRF 1F ;Clear the button-press file
GOTO Main

Table ADDWF 02h,1 ;Add W to the Program Counter to create a jump.


RETLW 3Fh ;0    format= gfedcba
RETLW 30h ;1
RETLW 5Bh ;2
RETLW 4Fh ;3
RETLW 66h ;4
RETLW 6Dh ;5
RETLW 7Dh ;6
RETLW 07h ;7
RETLW 7Fh ;8
RETLW 6Fh ;9
RETLW 6Eh ;y
RETLW 3Fh ;O
RETLW 3Eh ;U
RETLW 00h ;
RETLW 38h ;L
RETLW 3Fh ;O
RETLW 6Dh ;S
RETLW 79h ;E

44
RETLW 00h ;
RETLW 0FFh ;End of message

;This sub-routine works out the "Computer No of


;matches." The number of matches (file 0C) is loaded
;into file 0F. The ;number of matches to be removed is
;worked-out and put into file 10h.

Comp MOVF 0C,0 ;Move file 0C to W


MOVWF 0F ;Move W to file 0F for this operation 
CompA MOVLW 02
XORWF 0F,0
BTFSS 03,2
GOTO Comp1
MOVLW 01
MOVWF 10h ;"Computer takes 1"
RETURN
Comp1 MOVLW 03
XORWF 0F,0
BTFSS 03,2
GOTO Comp2
MOVLW 02
MOVWF 10h ;"Computer takes 2"
RETURN
Comp2 MOVLW 04
XORWF 0F,0
BTFSS 03,2
GOTO Comp3
MOVLW 03
MOVWF 10h ;"Computer takes 3"
RETURN
Comp3 MOVLW 05
XORWF 0F,0
BTFSS 03,2
GOTO Comp4
MOVF 11h,0 ;Put random number into W
MOVWF 10h ;"Computer takes Random number">
RETURN
Comp4 DECF 0Fh,1 ;File 0F is greater than 5 so reduce it by 4
DECF 0Fh,1
DECF 0Fh,1
DECF 0Fh,1
GOTO CompA

;This sub-routine converts the hex value in file 0C to


;decimal values in files 0D and 0E. 
;File 0D is the "units" and file 0E is the "tens"

Convert CLRF 0D
CLRF 0E
MOVF 0C,0 ;Move file 0C to W
MOVWF 0F ;Move W to file 0F for decrementing
INCF 0F,1 ;To account for the next two lines
Conv1 DECFSZ 0F,1 ;Decrement file 0F
GOTO Conv2
RETURN
Conv2 INCF 0D,1
MOVLW 0A

45
XORWF 0D,0
BTFSS 03,2 ;Test the zero flag for "ten"
GOTO Conv1
INCF 0E,1 ;Increment the "tens"
CLRF 0D ;Zero the "units"
GOTO Conv1 ;Do another conversion

Delay MOVLW 60h


MOVWF 1B
DelA NOP
NOP
DECFSZ 1A,1
GOTO DelA
BTFSC 05,0 ;Look at push button
GOTO DelC
BCF 1F,0
DelB DECFSZ 1B,1
GOTO DelA
RETURN
DelC BTFSC 1F,0 ;Test the button-press flag
GOTO DelB
INCF 14h ;Increment "3-times pressed" file
BTFSS 14h,2 ;Button pressed too many times
DECF 0C,1 ;Decrement the count file
MOVLW 04
MOVWF 13h ;Number of loops of display before computer turn
BSF 1F,1 ;Set the flag for above loop
BSF 1F,0 ;Set the button-press flag
GOTO DelB

Display MOVLW 00 ;Blank the leading "0"


XORWF 0Eh,0 ;    "       "        "
BTFSC 03,2 ;    "       "        "
GOTO Disp1 ;    "       "        "
MOVF 0Eh,0 ;Move file 0E to W. Show "tens"
CALL Table
MOVWF 06 ;Show value on 7-segment display
CALL Delay
CLRF 06 ;Blank the display
CALL Delay
MOVF 0Dh,0 ;Move file 0D to W. Show "units"
CALL Table
MOVWF 06 ;Show value on 7-segment display
CALL Delay
CLRF 06 ;Blank the display 
Disp CALL Delay
CALL Delay
CALL Delay
RETURN
Disp1 MOVF 0Dh,0 ;Move file 0D to W. Show "units"
CALL Table
MOVWF 06 ;Show value on 7-segment display
GOTO Disp

;"Mess1" shows on 7-segment display: "I Lose"

Mess1 MOVLW 40h ;Show "-"


MOVWF 06

46
CALL Show
CALL Show
MOVLW 06 ;Show the letter"I"
MOVWF 06
CALL Show
CALL Show
CALL Show
CALL Show
MOVLW 0Dh
MOVWF 12h ;Jumper for table
Mess1A CLRF 06
CALL Show
MOVF 12h,0
CALL Table
MOVWF 06 ;Output to display
MOVLW 0FFh ;Detect end of Table
XORWF 06,0
BTFSC 03,2
GOTO Main ;End of Table detected
INCF 12h,1 ;Jump to next letter
CALL Show
CALL Show
GOTO Mess1A

;"Mess2" shows on 7-segment display: "You Lose"

Mess2 MOVLW 0Ah


MOVWF 12h ;Jumper for table
GOTO Mess1A

Show NOP ;Create 250mS delay


DECFSZ 1A,1
GOTO Show
DECFSZ 1B,1
GOTO Show
RETURN

;"Value" displays the number of matches the computer


;will remove. It is displayed on the 8 LEDs as one LED,
;two LEDs or three LEDs. File 10h is computer number.

Value MOVLW 01
XORWF 10h,0
BTFSS 03,2
GOTO Val1
MOVLW 80h
MOVWF 06
GOTO Val3
Val1 MOVLW 02
XORWF 10h,0
BTFSS 03,2
GOTO Val2
MOVLW 0C0h
MOVWF 06
GOTO Val3
Val2 MOVLW 0E0h
MOVWF 06
Val3 MOVLW 0Ah ;Create 2 sec delay to show
MOVWF 1C ;             computer value on 8 LEDs

47
Val4 NOP
DECFSZ 1A,1
GOTO Val4
DECFSZ 1B,1
GOTO Val4
DECFSZ 1C,1
GOTO Val4
RETURN

Main MOVLW 16h  ;15h = 21 16h = 21


MOVWF 0Ch
Main1 INCF 11h,1 ;Increment the random number
MOVLW 04
XORWF 11h,0
BTFSC 03,2 ;Test zero bit for match 
GOTO Main4
Main2 CALL Convert
CALL Display
BTFSS 1F,1 ;Has button been pressed?
GOTO Main1
DECFSZ 13h,1 ;Decrement the 4-loop file before computer turn
GOTO Main1
CLRF 14h ;Clear the "3-times button pressed" file
MOVLW 00
XORWF 0Ch,0
BTFSC 03,2 ;Test zero flag for match
GOTO Mess2 ; "You lose" 
MOVLW 01
XORWF 0Ch,0
BTFSC 03,2 ;Test the zero flag
GOTO Mess1 ; "I Lose"
CALL Comp ;Go to "Computer Turn" for No of matches to remove
CALL Value ;Display computer value for 2 secs
Main3 CALL Convert
CALL Display
DECF 0Ch,1
DECFSZ 10h,1 ;Decrement the "computer matches" value.
GOTO Main3
BCF 1F,1 ;Clear the loop flag 
GOTO Main1
CLRF 11h
Main4 INCF 11h
GOTO Main2

END  ;Tells assembler end of program

THE PROGRAM 
The program is designed to work with any number of matches. If it starts with 21, the random number section
will not be needed. If it starts with 22, you will be able to see the random number feature come into operation.
Let's go though the program, one section at a time. 
The first section is the first 11 instructions in Main (actually instructions 3 -11). It does three things:
1. The Random Number file is incremented (it must be 1, 2 or 3). 
2.  The Convert sub-routine is executed to convert the number of matches (in hex) is converted to a decimal
number. 
3. The Display sub-routine is executed to show the number of matches on the 7-segment display. 
The flow chart for this is:

48
In the flow chart above, the program is looping, waiting for the switch to be pressed. The random number file
is here as human involvement will create an unknown value in the file. It is cleared in SetUp. When it reaches
4, it is cleared and loaded with 1. In this way it will only contain 1, 2 or 3. 
The Convert routine takes the number of matches (in hex) and converts it to a decimal number. 
The decimal number will be placed in files 0D and 0E. These two files are cleared at the beginning of the sub-
routine and the hex value in file 0C is placed in file 0F as a temporary file so that file 0C will not be altered.
The hex value is transferred to the two decimal files by a process called decrementing. The units file is
incremented in a loop and at the same time, file 0F is decremented. 
On each loop, the units file is tested to see if it has reached "10" (0A). If it has, it is zeroed and the tens file is
incremented. When file 0F is zero, the transfer is complete.

The micro then returns to Main and goes to Display.  


The Display sub-routine shows the "tens" and "units" on a 7-segment display. 
The routine firstly checks the value of the file by comparing it to 00. If it is zero, the routine displays only the
"units." To display a value, the decimal value is used as a jump value for a Table and the program returns
with the display-value. This value is outputted to port 06.  
A Delay is then called to allow the value to appear on the display. 
The display is then blanked and Delay is called to create separation between digits in case the same numeral
needs to be displayed as the "units."

Since the micro will be spending most time in the Delay routine, this is where the switch commands are
placed and it requires some detailed analysis:

The instruction to "look at push button" is in the inner loop and it


is accessed every millisecond. 
If the button is pressed, a bit in the flag file is SET. (1F,0) and the
micro decrements the number of matches, loads a counter with 4
for the number of loops of the display before the computer has
its turn and sets the button-press flag. 
If the button is pressed more than 3 times, the routine jumps
over the instruction to decrement the number matches.
It then completes the delay routine and returns to Main. 
The button-press routine must be placed where it will receive
immediate attention and that's why the Delay routine is ideal. 
In computer-terms, the button will be pressed for a long time
and the delay routine will loop many times while the button is
pressed. 
As soon as the button is recognised, the match-number is
decremented and flag 1F,0 is set, so that the match-count is
not decremented again, until the button is released. 
The Delay takes approximately 250mS to execute and if the
button is pressed a number of times during this execution, the
match-count will be decremented accordingly. It is an
important feature to fetch the button-presses. 
The 1mS delay between each look at the button is called
"switch debounce" and is extremely important. This 1mS is the
time taken to decrement file 1A. 
The Delay routine also re-sets the 4-loop counter for the
display so that the player can view the screen after each press
of the button. 
The placement of an instruction in a routine is very important.
For instance, the 4-loop counter must be placed so that is gets
re-set each time the button is pressed. 

The micro returns to Main and the button-press flag 1F,1 tells
the micro that the button has been pressed. The 4-loop
counter (file 13h) is decremented and when it is zero, the micro clears the flag that prevent more than 3
button-presses and tests to see if the number of matches is zero. 

49
This test is done before the computer has its turns and if no matches are left, it means the player has taken
the last match and forfeited his ability to win the game. 
If 1 match is left, the computer loses. 
The program then calls "Comp."

The first thing Comp does is put the number of matches into file 0F to save file 0C. It then reduces the
number of matches to 2, 3, 4, or 5. It does this by looking to see if the number is 2. If not, it looks to see if the
number is 3, 4, or 5. If it is above 5, it removes 4 matches and starts the routine again. 
If the number is 2, it will remove 1 match, and this number is placed in file 10h. It does a similar process for 3
and 4 matches.
If the number is 5, the computer is on a losing streak and it must take a random number. This is the "thinking"
part of the program and the random number is obtained from file 11h. 
The micro exits with a "computer number" in file 10h. 
 
The next sub-routine is very simple. It displays the "computer number " on the 8 LED display as one LED, two
LEDs or three LEDs. A 2-second delay is then executed to show the value. 

At Main 3, the number of matches in the game is shown again and the program loops this section and
decrements the number of matches for the "computer turn." 
The micro is taken to main 1 and sits in a holding loop for the player to take another turn. 

THE STRATEGY ALGORITHM


Do not read this until you have played the game and need to know the inner working of the "decision
routine."
The thing that makes computers impressive is a feeling of intelligence. 
When feedback comes in the form of  a response to a game, a challenge is apparent. 
The routine creating the algorithm in the game above, is "Comp." 
"Thinking" routines can be based on one of three approaches:
1. They can be directly linked (on a one-to-one basis) to the input information via a table or sequence or
mathematical equation. 
2. They can be linked after assessing a number of input values - the algorithm approach,
3. They can be linked via a random number generator. 

Every situation is different and the aim is to create a decision of  "THE BEST RESULT."
This obviously means avoiding a silly result but if the situation is "hopeless," a result must still be generated.
This is where the "last resort" of a random number comes in. 
This introduces variations to the game and provides the concept of "thinking."

The most important part of creating a Strategy Routine is to "cover all bases." In other words, all possibilities
must be covered. The only way to prove this is to "play the game." We have produced a program for TIC TAC
TOE (in another project) and the only way to produce the strategy section was to play the game many times
and see if a "loop-hole" existed. It was then necessary to have other members of staff play the game to see if
thinking by a different player was also accounted for. 

Now we come to the strategy behind "21."


One interesting aspect of the program is its ability to cater for any number of matches. The point we didn't
mention is the outcome. 
Different numbers of matches have a different outcome (when the player is aware of the strategy behind the
game).
A program can also be designed to allow the computer to make the first move, but most players want to play
the first hand - they think they have more control over the outcome. In some cases, they do. It depends on
the number of matches in the game. 

The basis behind "21" is to divide the matches into groups of 4. If the player takes one match, the computer
takes 3. If the player take 2 matches, the computer takes 2. If the player takes one match, the computer takes
3. 
This means we can "chop-off" blocks of 4 matches since we know what to do with each block of 4, provided
we get into the right position as soon as possible. 
With 21 matches we knock off "blocks of 4" and get 5 remaining matches. If the player takes 1 match. The
computer takes 3 matches and wins. If the player takes 2 matches in his first turn, the computer takes 2
50
matches, and wins. 
If the player takes 3 matches, the computer takes 1 match and wins. 
In other words, the player cannot win with a game of "21." 

"22"
If the game is extended to 22 matches, a different situation is produced. 
If the player knows the strategy behind the game, he will be able to see the RANDOM NUMBER come into
operation.
At the start of the game, if the player takes 1 match, the computer takes a random number. If the player
knows the strategy, the computer cannot win, however if the player does not take the correct number of
matches during each turn, "a winning sequence" may be presented to the computer and it will then fall into
the sequence of removing matches according to the pattern outlined above. 
The program has been supplied as "22" in the .zip files, to see the "thinking" come into operation. 
 

PIC LAB-1
Extra Pages

All the pages and experiments we have presented for this project show you how to produce routines for the
PIC16F84 microcontroller. With these routines you will be able to create projects to rival almost anything you
have seen to date.
We have shown how to design programs with the most efficient instructions (called machine code) and at a
cost below anything else available
This has broken new ground in getting the absolute beginner to a point where a software designer has said it
would take the average programmer 5 years to produce programs equal to those we have presented.
I think we have proven them wrong. With our layout and terminology we have made it "straight sailing" and if
you have read to here, you will be well on the way to producing programs that are "ripe" for the consumer
market.

Here are some of the features of the "Extra Pages." They contain more than the short description indicates.
They are also in the contents on the left. 
 

Page 6 The Piezo diaphragm as an input and output device


Page 7 NITINOL wire
Page 8 Poling - looking at an input
Page 9 3-digit Counter   A-to-D Converter - Measuring Resistance
Page 10 Library of Routines. This is the secret behind our  "Cut-and-
Paste" concept to create your own programs.
Page 11 Timing and Delays. Creating a program to control up to 8
devices.
Page 12 Adding extra inputs and outputs
Page 13 Advanced Programming and Clever Commands
Page 14 Test 1 on basic electronics for the PIC LAB-1  
Page 15 Test 2 on basic electronics for the PIC LAB-1
Page 16 Test 3 on basic programming
Page 17 Test 4 on programming
Page 18 Test 5 on programming
Page 19 More to be added here

The Library of Routines is a very large file. It contains routines for almost every requirement. As you create
a program, simply think of suitable words for the next operation, go to the Library of Routines and read the
comments. Open it in a separate TEXTPAD program so that the associated lines of code can be copied and
pasted into your program. 
Some of the terms include: Beep, CALL Table, Debounce a Switch, Decrement, Delay, Increment, Input,
Load a File, Loop, Mask, Move, Nested Delay, Output, Poll, Random Number, SetUp, Stop, Table, Toggle,
Tone, TRIS, Zero. 

51
PIC LAB-1
P6

THE PIEZO DIAPHRAGM

INTRO
 The "piezo" is everywhere. Its uses are endless, from musical cards, watch alarms, tone producers for
dialling phone numbers, to alarms, glass-break detectors and sirens and although it appears to be very
simple, its principle of operation is quite complex.  The secret is piezo-electric material glued to  the
diaphragm. This material increases and decreases in size when a voltage is applied to it and this causes the
metal diaphragm to bend like a saucer.  Up to now we have seen piezo-electric crystals in record players, gas
lighters and other devices where the crystal is bent or struck and it produces a voltage. But in the piezo
diaphragm, it works in reverse. A voltage is applied to it and the crystal changes in shape. The manufacture
of a piezo diaphragm is quite complex. Depending on the quality of manufacture, the result can be quite
sensitive or insensitive. 
"Hobby" piezos are mostly junk and have very poor output. Quality devices are available from recognised
wholesalers and are far superior. But unless you know how to test them, you will not be able to pick the good
from the bad. The word "piezo" is used for a whole family of piezos and this is where the confusion comes in.
One type of piezo is simply an element or diaphragm and requires an external driving circuit for it to emit a
sound. The other has the drive circuit incorporated in the case, along with the piezo diaphragm, and this
allows it to produce a tone, beep or chirp, (according to the complexity of the electronic circuit driving it)
simply by connecting it to a DC supply. There isn't an easy way of telling one from the other, if you can't see
inside the case, so you have to know what to do. This article will help. 

TYPES OF PIEZO
The piezo is sometimes called: "piezo," "buzzer," "piezo buzzer," "piezo tweeter" or "piezo siren."  
They are not all the same type of device. 
There are two groups. 
One consists of a piezo diaphragm with built-in circuitry to activate the diaphragm to produce a sound or tone
when a DC voltage is applied. 
The other consists of ONLY a diaphragm and requires an AC waveform or pulsed-DC to produce a
sound. This is the type of piezo we will be describing. 
It is called a PIEZO DIAPHRAGM. The symbol for a PIEZO DIAPHRAGM is shown below:

A piezo diaphragm is not an active device. It does not produce a sound when DC is applied. It requires an AC
signal.
It has infinite resistance but is seen by a circuit as a capacitor of about 22n (10n to 60n depending on size).
When a signal is delivered at the operating frequency it is seen by the circuit as an IMPEDANCE of about
500 ohms. 
The piezo consists of a thin brass plate with a thin layer of ceramic material glued on one side. On the other
side of the ceramic is a very thin layer of metal to create the top plate (called an electrode). The brass
diaphragm forms the other terminal. This is shown in the diagram below:

When voltage is applied so that one electrode is positive and the other negative, the ceramic material
increases in size. Since it is glued to the side of the metal disc, it causes the disc to bend or "dish." When the
52
voltage is removed, the plate returns to its flat condition. 
If the voltage is now applied in the opposite direction, the plate "dishes" in the opposite direction. 
If this process is repeated at a vary fast rate, the plate produces a characteristic sound.
If the voltage is increased, the "dishing is greater and thus the sound intensity increases. 
If the frequency of the signal (the voltage) is altered, the resulting frequency produced by the piezo is altered. 

By holding the outside of the diaphragm rigid and enclosing it in a resonant chamber, the sound is
mechanically amplified and the result is very impressive - although very annoying! We are all familiar with the
beeps and tunes that piezos produce from watches and musical cards and although they sound very "tinny,"
we have to live with the fact that they are very efficient producers of sound. 
The output from a piezo depends on the applied voltage and also the quality of the piezo substrate. This
substrate is polarised (not polarised according to positive and negative voltage but according to direction of
expansion and contraction) and the degree of polarisation determines the amount of movement for the
voltage applied. 
It must be remembered that a piezo element is a passive device and cannot produce a tone by itself. It
requires a drive circuit from a computer or a transistor oscillator for it to function. Also, the quality (especially
music or voice) is dependent on the thickness of the diaphragm and piezo substrate.  
The overall loudness depends on the applied voltage and the size of the diaphragm.

A piezo diaphragm can be used as an input  or output device. The diagrams below show how to connect it
to a transistor as an input device and to the output of a microcontroller, as an output device. 

The animation above shows the piezo diaphragm in a housing. This housing makes the diaphragm robust
and improves its output.
There are two modes of operation for the device.
1. A sine-wave voltage (called an AC voltage) can be applied to the leads and the diaphragm will respond.
2. A "whistle" (commonly called AUDIO) can be delivered to the diaphragm and an output will be produced. 
If an AC voltage is applied to the device, (one lead is called the "reference lead" or "earth lead" or "0v lead"
and the other lead traces the waveform shown above), the diaphragm will "dish" (move) as shown in the
animation. When the waveform goes "positive," the dish bends in one direction. When the waveform goes
"negative," the diaphragm bends in the other direction. 
If a CRO is "hooked-up" to the two leads, it will display the waveform shown above.
If the AC voltage is removed (the CRO remains connected), and a  whistle is applied through the hole in the
top of the device, the output will be as shown in the animation.  As the metal diaphragm moves in response to
the whistle, the ceramic material will produce a voltage (a waveform) as shown above. 

RESONANT FREQUENCY 
This frequency is determined by the size and thickness of the diaphragm and also the quality of the substrate
and cannot be changed by the user. Resonant values are obtained from the specification sheet that comes
with all good quality piezos. It is necessary to select the correct value of inductance to get the maximum
53
output for the frequency it is operating at, and this is generally found from data sheets or by trial and error. 

3 LEADED PIEZOS 
Most piezos have 2 leads, but some have 3. The third lead is connected to an electrically isolated silvered
terminal on the substrate and it sees a small sample of the signal on the piezo. This lead is called a feedback
line and is connected to the input of an oscillator to produce positive feedback to maintain frequency. This
type of diaphragm is usually placed in a package containing the "exciting" (oscillating) circuitry. It is effectively
equal to a small capacitor connected to one of the plates. The diagram below shows a 3-leaded piezo. We
will not be covering this type of diaphragm. 

A 3-leaded piezo diaphragm

MAXIMUM VOLTAGE 
All piezos have a maximum voltage that can be placed across the terminals before the substrate breaks
down. The only way to see the driving voltage is to use a CRO. This is important when designing a new
circuit to make sure the voltage does not puncture the piezo-electric material. 

BE CAREFUL 
To get the maximum output from a piezo diaphragm it is necessary to hold the outside rim firmly so that the
brass diaphragm can deflect in the centre. An unrestrained diaphragm will have very little output and to
increase the output even more, it can be housed in a small case to act as a sounding cavity. Sometimes a
driving circuit is present in the case and to find out if this is so, it is necessary to connect the leads to a 6-12v
DC supply. If a tone is generated, a driving circuit is present. If only a click is heard, the case contains only a
diaphragm. 

It is essential to know exactly how the piezo device is structured so that the appropriate drive circuit or drive
voltage can be applied. If the drive-circuit is internal, a DC voltage can be applied, provided the positive and
negative are connected to the correct terminals.

THE PIEZO DIAPHRAGM AS AN INPUT DEVICE


The piezo diaphragm can be used as an input device. It has some advantage over an electret microphone
and some disadvantages. 
The piezo diaphragm is not as sensitive as an electret mic and the output is harsh and metallic. In other
words, the output is not as high as an electret mic when detecting low-level sounds.  It is not suitable for
reproducing quality audio as the sound is not very clear.  
However it can be used to pick up sounds, especially the breaking of glass (glass-break detector) or other
loud sounds, to turn on a piece of equipment.
A glass-break detector sells for $10 to $30 and is really a piezo diaphragm in a small stick-on case!
It also has the advantage of producing a voltage when it detects a sound and thus it does not have to be
connected to a supply-rail. 
This allows projects to be sitting in a "ready" state and consume NO current. A piezo diaphragm can be
connected to an amplifier on the PIC LAB-1 project. It will produce an output very similar in amplitude to an
electret microphone and the amplifier will convert the signal to a DIGITAL SIGNAL. 
The supply resistor and stage-separating electrolytic are not needed but they can be left in circuit without
affecting the operation.
The output voltage of a piezo diaphragm depends on the quality of the device. It has been found that the best
devices are obtained from a musical greeting card as they have to produce a quality output from a 3v supply. 
Piezo diaphragms are not polarised in terms of the fact that they can be connected either way around to the
supply voltage. The actual ceramic material is polarised so that it extends in the longitudinal direction to affect
the shape of the metal diaphragm.
 

54
THE PIEZO DIAPHRAGM AS AN OUTPUT DEVICE
The piezo diaphragm can also be used as an output device. The output (sound-level) depends on the
amplitude of the voltage supplied to the device. To increase the sound-level, there are four ways to increase
the voltage:
1. Increase the supply voltage to the circuit driving the piezo diaphragm,
2. Provide a "reversing voltage" to the diaphragm,
3. Add a choke across the diaphragm, or
4. Operate the piezo diaphragm at its "resonant frequency."

1. Increasing the supply voltage is not always easy.  There are times however, when the unregulated supply
can be accessed and this can increase the voltage from 5v to about 14-16v.
Doubling the supply voltage will only increase the output of the piezo a very small amount. It certainly will not
double the sound. 
2. The following circuit shows how to drive a piezo from the outputs of a Schmitt Trigger IC. 

Driving a piezo from two Schmitt Inverters

Two gates are required and in the diagram each output is out-of-phase. This means one side of the piezo is
seeing a positive voltage while the other is at 0v. The outputs then change state and the first side sees 0v
and the second side sees a positive voltage. This means the piezo see a voltage that is twice the supply
voltage and the output is slightly higher than if driven by a voltage equal to the supply. 
Understanding the concept of 2V (twice the supply voltage) across the piezo is very important as this also
applies to LCD screens in watches etc. 
The closest analogy is this: Suppose you look at the top of a 10ft post. You are then instantly transported to
the top of the post and look at the ground. The angle of your eyesight is firstly up, say at 45º then down at
45º. The total travel of your eyes is 10ft plus 10ft = 20ft. 
This is exactly what the piezo sees. 

3. Adding a choke across a piezo diaphragm produces an "OSCILLATORY CIRCUIT." An Oscillatory circuit is
very similar to a "RESONANT circuit" or "TUNED circuit" however the output is not necessarily a peak value. 
An oscillator circuit means that some of the effect of placing a coil and capacitor in parallel, is achieved. 
Again, to understand how this arrangement operates, we will have to go into the theory of a parallel tuned
circuit. 
We have already mentioned that a piezo diaphragm is effectively a capacitor of approx 22n. If we place a coil
across this, we have a parallel tuned circuit. The value of the coil is not important however 10mH produces
very good results. 
The way the coil and capacitor work is very complex. The exact operation is not needed however an
understanding of the operation will allow you to design circuits with this arrangement.
When a pulse of energy is delivered to the combination, the coil forms a blockage to the current while the
capacitor is seen as a low resistance and thus a small amount of energy is absorbed by the capacitor (the
piezo diaphragm). 
When the supply is turned off, the energy from the capacitor is passed to the coil (the choke) to produce
magnetic flux. It keeps producing magnetic flux until the energy from the capacitor has been fully delivered.
At this point the magnetic flux collapses and produces voltage in the turns of the coil that is in the opposite
direction to the previous voltage. This voltage can be considerably higher than the initial voltage and is
passed to the piezo. The piezo responds to this high voltage by producing a higher output and when all the
voltage (energy) has been delivered, the voltage across the capacitor is passed back to the coil (choke). 
Energy will pass back and forth many times and each time the amplitude of the signal will be lower. 
However, the circuit turns on after the first or second oscillation, to deliver another pulse of energy to the
combination, with the result of a very loud output. 
If the circuit operates from a 12v supply, and is fed by a driver transistor, the voltage across the arrangement
will rise to 90v and even 120v as the frequency is varied. At the point of resonance, the voltage is a
55
maximum. If this frequency happens to coincide with the natural resonant frequency of the diaphragm, the
output rises to 100dB and even 130dB. 
This is the maximum level the ear can withstand and even at 3 - 4 metres, you cannot hear anything in a
room when this level of sound is being emitted. 
To produce the maximum output, the frequency delivered to the combination must be the resonant frequency
of the diaphragm and the choke must be wound to an exact value. This is not always possible with standard
components and that's why piezo tweeters are available that produce up to 120-140dB output. 
One interesting point to note. The high voltage produced by the coil/capacitor combination means the driver
transistor must be able to withstand the voltage. If the supply is 12v and a 50v transistor is used, it will zener
at 50v and prevent the piezo diaphragm receiving the full potential. 
That's why a high voltage transistor must be used!

4. From the discussion above, you can see the piezo diaphragm has a resonant frequency and as the tone is
raised and lowered, a peak in output is detected. If the diaphragm is operated at this frequency, the output is
a maximum. 
Some manufacturers provide this frequency in the list of specifications.

PIEZO SPEAKERS AND TWEETERS


The piezo diaphragm can be used as a speaker. Although its quality is not equal to a "cone speaker," it can
used to to accentuate high-frequency signals in a passage of music. A piezo speaker consumes much less
power than a cone-speaker and is able to produce sounds up to and beyond 135dB.

To produce voltages considerably higher than the supply we need an inductor or a step-up transformer.
When using an inductor, it is placed across the piezo so that when current is passed through it and switched
off rapidly, the magnetic field in the inductor collapses and produces a very high voltage. This can be as high
as 50 - 80v for a voltage as low as a few volts and these peaks are fed into the piezo to generate a very loud
sound. The structure of the piezo is such that the brass diaphragm forms one plate of a capacitor and the
silvered surface forms the other. The piezo material is a dielectric and produces a capacitor of approximately
3nF. When an inductor is placed across a piezo, the two components form a resonant circuit. We have
already explained how a resonant circuit works in other articles and basically the two pass energy back and
forth between them. The system is started by applying a voltage across the two. The inductor creates a
magnetic field and when the current is turned off, the magnetic field collapses and produces a very high
voltage. This voltage appears across the piezo and a loud sound is generated. The piezo does not use up all
the energy and some of it is fed back to the inductor to be converted to magnetic flux. This is repeated back
and forth between the two many times, each time with a slightly reduced value and produces a ringing sound
from the piezo that gradually fades away. Instead of the inductor, we can use a step-up transformer. This will
produce an AC voltage for the piezo and once again, the piezo will produce a loud output. The piezo
diaphragm produces the highest output at a frequency called the 
 

PIC LAB-1 AND THE PIEZO


We have now covered the technical details of the piezo diaphragm and you will have some idea of how it
operates as an input and output device. 
Connecting it to PIC LAB-1 is very simple and it's just a matter of providing the correct interface and writing a
program. 
When connecting the piezo diaphragm as an input device, an amplifier is needed to increase the amplitude
to digital level.  This will require two stages of amplification to guarantee a rail-to-rail waveform. 
The diagram (a) below shows a two-stage amplifier.  The output of the piezo is amplified approx 100 times by
the first stage and this signal is guaranteed to turn on the second stage. The second stage is held in "cut-off"
by the 1M and 47k resistors. With a supply rail of 5v, the voltage on the base is slightly less than 0.5v and this
is below the voltage required to turn the transistor ON. 
A waveform less than 300mV from the first stage will raise the base voltage of the second stage to a point
where the transistor conducts and the collector voltage changes from HIGH to LOW. This is detected by a
program. 
Diagram (b) shows the circuit provided by PIC LAB-1. The supply resistor and electrolytic to the input
terminals are needed for the electret mic and are not needed for the piezo. However they do not affect the
operation of the circuit. 

56
When connecting the piezo as an output device, a transistor having sufficient break-down voltage capability,
must be used. This applies when a coil (choke) is added across the diaphragm. 

WRITING AN INPUT PROGRAM 


The interface circuit between the piezo and microcontroller must produce a digital waveform, (5v excursion)
for the audio being detected. It is then a simple matter to poll the input line on a regular basis to look for the
signal.
To detect the frequency of an unknown signal, a very clever program can be produced to create a varying-
width window. This will prevent the signal synchronising with the window and not being detected.

Audio CLRF 13h  ;File 13h counts audio "lows"


MOVLW 0A0h ;Create 50h loops! Yes 50h
MOVWF 1A 
Audio2 MOVF 1A,0  ;Copy 1A to W
MOVWF 1B  ;Copy W to 1B
Audio3 DECFSZ 1B,1
GOTO Audio3
BTFSS 05,1   ;Look at audio input. Audio = LOW
GOTO Audio4
INCFSZ 1A,1  ;Increment file 1A to zero!
GOTO Audio2
RETURN
Audio4 INCF 13h
GOTO Audio2

The interface circuitry can be designed with a pulse extender to make sure the signal is not missed. 
The program above will not be needed if a pulse-extender is added. 
The circuit below shows a pulse extender:

The electrolytic (1u to 10u) on the input line is discharged when the transistor is activated and it takes time to
charge.  The "LOW time" can then be detected by the micro. 

57
By adding the electrolytic, the circuitry can be made very insensitive so that only loud audio will be detected.
The diagram below shows the addition of a 100k to reduce the voltage on the base of the second stage. This
pot also reduces the impedance on the base of the transistor and this also reduces the sensitivity. 
When the pot is turned to the HIGH Sensitivity end of its travel, the energy in the 1u electrolytic will have to
raise the base voltage from about 0.3v to about 0.6v to cause the transistor to change state. 
When the pot is turned to the LOW Sensitivity end, only about 22k is between the base and 0v rail. The 1u
will have to raise the voltage from about 50mV to 600mV. The low impedance of the base (the 22k between
base and 0v) will require more energy from the 1u and this will also have an effect on lowering the sensitivity
of the circuit.   

Nitinol Wire
"muscle wire"
P7

  NITINOL wire.  Opto-coupler, globe, motor, 

INTRO

NITINOL WIRE
Nitinol wire is a very interesting output device or INDICATOR. It is a wire that DECREASES in length when
a current flows through it. This is opposite to thermal expansion, where heating create an expansion. IN this
case heating creates a contraction about 100 times greater than normal expansion. Current through the wire
produces heat and the amount of current must be carefully controlled (limited) so that the wire does not get
too hot. The wire is only allowed to rise to a  temperature to produce approx 6% reduction in length. 
There are a number of comments about this wire. It is very expensive ($xx per metre) and the speed of
activation is about 1second for contraction plus approx 1second for the wire to cool and return to its original
length. 
The other limiting factor is the need for a force to return it to its original length. It does not return by itself. The
wire we use for the experiments is 0.004in (4 thousands of an inch) in diameter. It produces a force (lifting
power or pulling power) of xxxgm. 
The force required to return it to its original length is xxxgm. If this returning force is present all the time, the
effective output force is 65gm - 25 = xxxgm.  
If you have an application that meets these requirements, this project can be very impressive. 
We have produced a 3-page technical article on NITINOL wire with a list of suppliers, applications and
complete technical details. 

Going Further
P8

In all the experiments we have presented so far, only a  SINGLE, simple operation or feature has been
carried out. 
That's the idea of an experiment, to produce or concentrate on a single result. That's the only way to fully
understand the concept being investigated.
But that's not the limit of the PIC LAB-1. 
It is capable of  quite considerable feats, such as a dialing alarm, robot control, counting and games, to name
a few. 

58
Some applications will require additional inputs or output devices but the main thing is the program can be
generated on the PIC LAB-1 board and new PCB produced when everything is working perfectly. 
As we have mentioned in previous pages of this article, all the development can be done at no cost, other
than buying the PIC LAB-1 kit, as all the "tools for development" are provided on the site. 
By following our alphabetical layout for programming you will be able to locate the sub-routines when the
program becomes very long. 
Keep all the sub-routines in alphabetical order (in the middle of the program). Start with SetUp, place Tables
at the top and Main at the end. 
Many of the programs can be developed by using the sub-routines we have presented in the experiments
and you can start by taking one of the programs and using it as a "starting-point."
As soon as you get something on the page, the pressure of starting will be over and you can change the
instructions to reflect the new program. 
As soon as you think of the next step, go to the experiments and see how it has been done. Or refer to the
Library of Routines. It lists every feature you will need for each step of a program and by "cutting and pasting"
you will be able to build up a program very quickly.   
When you add a sub-routine to your program, make sure all the CALLs and RETURNs are operational.
As soon as possible, test it to make sure it works. Save the program with a new name so that if a mistake is
created in the next phase, you can come back to the saved version and build-up again. 
This is a very good policy as it saves a lot of frustration. 
As you get better at programming, you will require this feature less often, but it is the only real way to solve
some of the problems you will encounter. 
If you get stuck during a stage of development, try using different instructions, as the instructions you are
using may not be carrying out the operations you intend. 
Gradually build up your program by using sub-routines from the experiments and Library of Routines. 
These show you everything, such as how to toggle a line, compare two values, produce a tone, output a
siren-sound, and many more. 

One of the important features in a program is . . .


POLING
Poling is looking at an input line on a regular basis to see if a particular event has occurred - such as a
button-press.
There are two ways to check an input line. One it to "look at it" on a regular basis and the other is to allow the
input line to create an interrupt.
The simplest is to look at it on a regular basis, but this requires a little bit of thought as any long delay
routines will keep the micro busy and the program will miss any button-presses during this time. 
The answer is to include a "look" feature inside the delay. 
You can have more than one "look" feature in a program and when a button is detected, a flag is SET. 
This flag is checked in Main to see if it is SET, and the appropriate action taken. 
The subroutine below shows a delay routine with a "look" feature.
The button flag must be CLEAR before entering Delay1.

Label: Code: Comments:


Delay1 NOP  ;Create 300mS delay
DECFSZ 1A,1
GOTO Delay1
BTFSC 05,0 ;Test the push-button
BSF 1F,0 ;SET the button-push flag
DECFSZ 1B,1
GOTO Delay1
RETURN

Never leave a sub-routine (such as Delay1) on the action of a button-press and go directly to the push-button
subroutine. Simply set a flag, complete the operation in the sub-routine and return to Main. If you want the
operation in the sub-routine to cease, use the following instructions:

Label: Code: Comments:


Delay1 NOP  ;Create 300mS delay

59
DECFSZ 1A,1
GOTO Delay1
BTFSC 05,0 ;Test the push-button
GOTO Delay2
DECFSZ 1B,1
GOTO Delay1
RETURN
Delay2 BSF 1F,0 ;SET the button-push flag
RETURN

   
THREE DIGIT COUNTER 
and 
A-to-D CONVERTER
P9

Even though the PIC LAB-1 board has only a single display, a 3-digit counter can be displayed by flashing
the 3 digits then pausing before displaying again. Ws have produced up to 5 digits in this manner and the
counter is fairly easy to read once you realize how the digits are displayed. 
The 3-digit counter serves to show how the limitations of a single display can be overcome. 
We have produced another project 5x7 Display, using a single display to produce a 3 and 5-digit counter. It
uses a matrix of LEDs to produce a single digit and the same principle of "flashing" has been used. 
Multiple-digit counters can be called "tally counters" for recording the total production of a particular item.
Some items can be weighed to get a quantity but this takes time and expense. 
The simplest is to have a detector (plus electronics) record each item as it is being produced and keep track
of the total. This can be used to "back up" the values obtained from individually weighed amounts. 
A tally counter will only need to be read once a day and the single digit can be a low-cost way of showing this
value. 
The program can be designed to accept a code from a set of buttons so that operators cannot access the
data.  It's a security measure to avoid theft and fraud. 

THE PROGRAM
A 3-digit counter requires three files to hold the "tally." Each digit is held in the lower "nibble" (a nibble is 4
bits).
These files are initially cleared so the readout is "000."
The first digit (actually the hundreds) is displayed then the display is cleared for a short time. This is repeated
for the second and third digit. 
The display is then cleared for a longer period of time to indicate the end of the number. 
The routine is then repeated. 
Throughout the program, the input must be poled at (looked at) regular intervals. The most difficult part of the
program is to place the button-instruction where it can be constantly executed by the micro. 
The only place is within the display routine.
The program takes about 1 second to display the three digits and in this time the button can be pressed 10 or
more times. 
By placing the button instruction (BTFSS 05,0) in the display routine it is accessed every 2mS. 
You can press the button while the display is flashing and the program will increment the tally in the
background. The result is very impressive. It appear that the program is down two things at the same time.
The circuit for the counter:

60
Here is the complete program:

                     ;3digit.asm


                     ;Project: 3 Digit Counter
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all port B output
MOVLW 01 ;Load W with 0000 0001
MOVWF 05 ;Make RA0 input
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 05 ;Clear portA
CLRF 1F ;Clear the button-press file
CLRF 11h ;Clear 'units' file
CLRF 12h ;Clear 'tens' file
CLRF 13h ;Clear 'hundreds' file
GOTO Main

Table ADDWF 02h,1 ;Add W to the Program Counter to create a jump.


RETLW 3Fh ;0    format= gfedcba
RETLW 06h ;1    If any table value has a leading letter, it must be
RETLW 5Bh ;2    preceded with a "0."   E.g: 0A3h, 0FFh, 0CCh
RETLW 4Fh ;3
RETLW 66h ;4
RETLW 6Dh ;5
RETLW 7Dh ;6
RETLW 07h ;7
RETLW 7Fh ;8
RETLW 6Fh ;9

Clear MOVLW 20h


MOVWF 0D
CLRF 06 ;Clear the display
CALL Disp1
RETURN

Display MOVLW 80h


MOVWF 0Ch
Disp1 BTFSS 05,0 ;Test the input line on port A
GOTO Disp2 ;Button not pressed

61
BTFSC 1F,0 ;Button pressed first time?
GOTO DelA ;Button already pressed 
BSF 1F,0 ;Set button-press flag
CALL Inc ;Button pressed. Increment count
GOTO DelA
Disp2 BCF 1F,0
DelA NOP
DECFSZ 1A,1
GOTO DelA
DECFSZ 0C,1
GOTO Disp1
RETURN

Inc INCF 11h,1 ;Increment units.


MOVLW 0A ;Has count reached ten?
XORWF 11h,0 ;Compare file 11h with ten
BTFSS 03,2 ;Check the zero flag in Status file
RETURN ;Count has not reached ten
CLRF 11h ;Zero the units file
INCF 12h,1 ;Increment tens.
MOVLW 0A ;Has count reached ten?
XORWF 12h,0 ;Compare file 12h with ten
BTFSS 03,2 ;Check the zero flag in Status file
RETURN ;Count has not reached ten
CLRF 12h ;Zero the tens file
INCF 13h,1 ;Increment hundreds.
MOVLW 0A ;Has count reached ten?
XORWF 13h,0 ;Compare file 13h with ten
BTFSS 03,2 ;Check the zero flag in Status file
RETURN ;Count has not reached ten
CLRF 13h ;Zero the hundreds
RETURN

Main MOVF 13h,0 ;Copy 'hundreds' into W


CALL Table
MOVWF 06 ;Display the number
CALL Display
CALL Clear
MOVF 12h,0 ;Copy 'tens' into W
CALL Table
MOVWF 06 ;Display the number
CALL Display
CALL Clear
MOVF 11h,0 ;Copy 'units' into W
CALL Table
MOVWF 06 ;Display the number
CALL Display
CLRF 06 ;Blank the display
CALL Clear
CALL Clear
CALL Clear
GOTO Main
;Tells assembler end of program
END

It is very easy to change the program to create a 4 or 5 digit display. A new file (say 14h) must be added. It is
cleared in SetUp and added to Inc sub-routine (by copying instructions) to produce thousands. It is then
added to Main by copying a small block of instructions in Main and changing the values as needed.

62
ANALOGUE TO DIGITAL (A-to-D)
The analogue input on the PIC LAB-1 reads a value of resistance connected to the "pot" terminals.

Connecting a potentiometer to the PIC LAB-1

The value of resistance can be almost any value from 10 ohms to 1M (and higher).
But it's a little bit more complex than simply fitting an unknown value of resistance and  showing the value on
the display. 
The program has to be "set up."
It works like this:

The first step is to decide on the maximum resistance you wish to measure. Suppose it is 1,000 ohms.  
The input line is capable of dividing this value into 256 parts (say 250 parts). This means the resolution is
1,000/250 = 4 ohms 
If the maximum value is 10,000 ohms, the resolution is 40 ohms. 
If the maximum resistance is 100,000 ohms, the resolution is 400 ohms and for 1M it is 4k. 
This is the resolution if we use a single file to hold the result. We can get a better resolution if two files are
used (256 x 256 = 65,535 parts) and this will be a future experiment. 
For now, we will keep it simple and use a single file.  
In the first case, a filled count-file (containing 250) must indicate 1,000 on the display. To perform the
conversion, the transfer from the count-file to the display files (files 11h, 12h and 13h) is carried out 4
times. In other words the 250 is multiplied by 4 to get 1,000. 
The pot included in the kit is 10,000 ohms. To convert 1,000 to 10,000 a zero is added to the display. 
Connect the pot to the project, burn the following program into the PIC chip and rotate the pot. You will be
able to read the value on the display (from nearly zero ohms to about 10k).
The lowest digit ("0") is added to the 3-digit counter (shown above) to get 4 digits.

                       ;Pot1.asm


                     ;Project: Potentiometer to PIC LAB-1
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all Port B output
MOVLW 10h ;Load W with 0001 0000
MOVWF 05 ;Make RA4 input
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 05 ;Clear PortA
GOTO Main1

63
Table ADDWF 02h,1 ;Add W to the Program Counter to create a jump.
RETLW 3Fh ;0    format= gfedcba
RETLW 06h ;1    If any table value has a leading letter, it must be
RETLW 5Bh ;2     preceded with a "0." E.g: 0A3h, 0FFh, 0CCh
RETLW 4Fh ;3
RETLW 66h ;4
RETLW 6Dh ;5
RETLW 7Dh ;6
RETLW 07h ;7
RETLW 7Fh ;8
RETLW 6Fh   ;9

Clear MOVLW 80h


MOVWF 1B
CLRF 06 ;Clear the display
CALL Delay
RETURN

Delay NOP ;Create 300mS delay


NOP
DECFSZ 1A,1
GOTO Delay
DECFSZ 1B,1
GOTO Delay
RETURN

INCF 11h,1 ;Increment units.


Inc MOVLW 0A ;Has count reached ten?
XORWF 11h,0 ;Compare file 11h with ten
BTFSS 03,2 ;Check the zero flag in Status file
RETURN ;Count has not reached ten
CLRF 11h ;Zero the units file
INCF 12h,1 ;Increment tens.
MOVLW 0A ;Has count reached ten?
XORWF 12h,0 ;Compare file 12h with ten
BTFSS 03,2 ;Check the zero flag in Status file
RETURN ;Count has not reached ten
CLRF 12h ;Zero the tens file
INCF 13h,1 ;Increment hundreds.
MOVLW 0A ;Has count reached ten? ;Compare file 13h with ten
XORWF 13h,0 ;Check the zero flag in Status file
BTFSS 03,2 ;Count has not reached ten
RETURN ;Zero the hundreds
CLRF 13h
RETURN

CLRF 0C ;Count-down file 


Look BSF 06,7 ;Take cap HIGH
NOP
Look2 INCF 0C,1
BTFSC 05,4 ;Is input LOW?
GOTO Look2
BCF 06,7 ;Take cap low 
RETURN

MOVF 13h,0 ;Copy 'hundreds' into W


CALL Table
Main MOVWF 06 ;Display the number

64
CALL Delay
CALL Clear
MOVF 12h,0 ;Copy 'tens' into W
CALL Table
MOVWF 06 ;Display the number
CALL Delay
CALL Clear
MOVF 11h,0 ;Copy 'units' into W
CALL Table
MOVWF 06 ;Display the number
CALL Delay
CALL Clear
MOVLW 3Fh
MOVWF 06 ;Output "0"
CALL Delay
CALL Clear ;Blank display
CALL Delay
CALL Delay
CLRF 11h ;Clear 'units' file
CLRF 12h ;Clear 'tens' file
Main1 CLRF 13h ;Clear 'hundreds' file
CALL Look
MOVLW 04 ;Four loops of "Count to display" 
MOVWF 0F
MOVF 0C,0 ;Copy 0C to W
MOVWF 0E ;Move W to 0E
DECFSZ 0E,1 ;Move count-down file to display-value
Main2 GOTO Main4
DECFSZ 0F,1
GOTO Main2
Main3 GOTO Main
CALL Inc ;Create display value
GOTO Main3

END ;Tells assembler end of program


Main4

You will find the readout starts at 0000 and goes as high as approx 8760. It does not show 9999.
What is the problem?
This is where the answer gets technical, but very interesting. 
The time-delay circuit made up of the 100n and 10k resistor in series, has a time-constant of approx 1,100mS
to charge the 100n when the resistance is 10k. This is not the normal "time-constant" covered in a normal RC
or time-delay circuit, where the capacitor charges to approx 66% of its maximum value. In our case the
capacitor charges until the lower threshold of the input to the PIC detects a LOW. You can select any "cut-off
point" or "trigger point" for any determination, providing the value can be repeated. 
The "Look" circuit, looks at the input for the 4 instructions between "Look2" and GOTO Look2. These
instructions take 5uS. 256 loops of 5uS = 1280uS. At a time-interval of 1,100uS the loop counter is 220. The
program multiplies this by 4 to get 8800. 
 
HOW CAN THE READING BE ALTERED?
This highlights two factors. 
At an execution speed of one million instructions per second, the instruction-speed is not high enough to
allow the programmer to adjust the length of the loop. In other words, instructions cannot be added or deleted
to make minor increments or decrements. If we remove the NOP in the loop, the counter will reach 256 when
the resistance is about 8 or 9k and this will produce a false reading on the other side of the range.  
The only thing we can do is match the circuit to the program. 
If the capacitor is increased in value by about 10 times (to 1u), the charge-time will increase and this will give
the programmer the ability to adjust the length of the loop. 
 
65
ALTERNATIVE DETECTION METHOD
There is another method of detecting the value of resistance using only a single input/output line. The circuit
is shown below. It does not matter if the pot is above or below the capacitor.

Measuring resistance with a single in/out line

The program is not as fast as the method above and will result in a slower "up-date." To achieve the same
resolution as above, the charging capacitor will have to be a large value (1u or higher) to allow the loop-
counter to fill completely.  
The program starts with an uncharged capacitor and the "drive-line" goes high for a short period of time. The
line is then changed to an input (a sense-line) and the voltage measured. The input line can only detect a
change from a LOW to a HIGH. If it does not detect a HIGH, the line is changed back to an output ("drive-
line") and the cycle is repeated. In this way the capacitor is gradually charged. The line reversal takes a few
microseconds and a delay (a NOP) should be placed in the program to allow the line to settle from one state
to the other before a reading is made. 
The program for the "look" section is as follows. To take advantage of the TRIS function, you must know the
state of the other lines on Port B, if you don't want them to change state during this operation. 

LookB CLRF 0C ;Count-down file 


MOVLW 00h
LookC TRIS 06 ;Make the top line an output. (0000 0000)
BSF 06,7 ;Take cap HIGH
INCF 0C,1
MOVLW 80h
TRIS 06 ;Make the top line an input. (1000 0000)
NOP ;Create a delay before reading input
BTFSS 06,7 ;Is input HIGH?
GOTO LookC ;No
RETURN ;Yes.

This method takes 10uS per loop and our previous method takes 5uS. 
This is not a problem with our simple experiments. It simply means the update time is longer. 
To get the count-file to completely fill using the 10uS loop, the capacitor will have to be larger and this will
also increase the update time.

Library of Routines
P10

The following is a list of sub-routines, ideas and help for the PIC16F84.  They apply to any project using the
PIC16F84. They can be pasted into your program and modified in any way - especially to suit the input/output
lines. 
Your program should be created on a template in a text editor such as NotePad, using blankF84.asm  as a
starting layout.  It provides the correct layout and spacing. 
The most unusual problem you may get is a failure to compile your program due to hidden
formatting/characters.  MPASM will not produce the needed .hex file if any problem or fault exists in a
program but it will produce a .lst file containing the faults. If you open .lst and see unusual mistakes, they will
be due to hidden formatting characters. Simply retype all the wording around the mistake (in the .asm file)
and the program will compile.  Do not use EditPad as it produces hidden characters.
To use the Library of Routines below, go to the NotePad set of "Copy and Paste" Routines  and "Copy and
66
Paste" them into your program in another NotePad, as needed. 
Additional sub-routines can be found in the PIC Programming Course.

Make sure each sub-routine uses a file (a register) with a name (a hex number) that doesn't clash with any
other sub-routine you have created. Make sure CALLs and RETURNs are functional and Labels have not
been used elsewhere.
The following library is presented in alphabetical order. Using these routines will get you started very quickly
and will usually assist you with 70% - 90% of a new project.  
Read through the entire library so you know the content.  
Simply think of a word or requirement for each part of a program. Go to the word and read the comments. Go
to the equivalent section in NotePad and copy the instructions. 
Paste them into your program and modify them to suit. Follow through each of the lines exactly as the micro
will interpret them and make sure you have a RETURN to Main, somewhere in the sub-routine.
Get each small addition to work correctly before adding more instructions. Gradually build up your program
and save it as a new name so it can be recalled if a major problem develops.

Add a value to a File


The PIC12C508A does not have an instruction to add a number to a file. Two instructions are needed to carry
out this operation so that the program you are producing is suitable for both a PIC12C508A and PIC16F84.

Add MOVLW 0CCh ;Put CCh into W


ADDWF 0Eh,1 ;CC will be added to the contents of file "E."

Add "bits" to a port - turn on bits or "lines."


This is handy when more than one line needs to be turned on.

;suppose port 6 has bits 0, 1 and 2 HIGH and we need


;   to turn on bit 7
MOVLW 80h ;Put 80h into W - this is bit 7
IORWF 06h,1 ;80h will be added to the contents of file "6." (port 6)

Address a File
This means "to act on" or "work with" a file. It can be to "move a value into a file," "increment a file,"
"decrement a file" or other similar operation.  Only files can be addressed. The files we are talking about are
the "empty" files from 0C to 4F.  None of the program or the values in the tables can be altered. The values in
a table can be accessed and copied by a set of instructions covered in CALL Table.
Typical addressing instructions are:

MOVWF 1A,0 ;Copy file 1A into W


DECFSZ 1A,1 ;Decrement file 1A
INCF 1A,1 ;Increment file 1A

Addressing a Set of Files


A number of files can be used to store temporary data, such as the digits or letters of a score-board. 
This is sometimes called a "scratchpad" or "scratchpad area."  The files should be sequential to make
programming easy. 
Suppose we have 8 files and need to address them with a simple sub-routine to output the data to a display.
The sub-routine is called INDIRECT ADDRESSING. See Indirect Addressing.

ARITHMETIC OPERATORS AND  PRECEDENCE

OPERATOR Example

67
$ Current/Return Program Counter goto $ + 3
( Left parenthesis 1 + ( d * 4)
) Right parenthesis (length + 1) * 256
! NOT (logical complement) if !  (a == b)
– Negation (2's complement) – 1 * length
~ Complement flags = ~ flags
* Multiply a=b*c
/ Divide a=b/c
% Modulus entry_len = tot_len % 16
+ Add tot_len  = entry_len * 8 + 1
– Subtract entry_len = (tot – 1) / 8
<< Left Shift flags = flags << 1
>> Right Shift flags = flags >> 1
>= Greater or equal if entry_idx >= num_entries
> Greater than if entry_idx > num_entries
< Less than if entry_idx < num_entries
<= Less or equal if entry_idx <= num_entries
== Equal to if entry_idx == num_entries
!= Not equal to if entry_idx ! = num_entries
& Bitwise AND flags = flags & ERROR_BIT
^ Bitwise EXclusive OR flags = flags ^ ERROR_BIT
| Bitwise Inclusive OR flags = flags | ERROR_BIT
&& Logical AND if (len == 512) && (b == c)
|| Logical OR if (len == 512) | | (b == c)
= Set equal to entry index = 0
+= Add to, set equal entry index += 1
–= Subtract, set equal entry index – = 1
*= Multiply, set equal entry index *= entry_length
/= Divide, set equal entry total  /= entry_length
%= Modulus, set equal entry index %= 8
<<= Left shift, set equal flags <<= 3
>>= Right shift, set equal flags >>= 3
&= AND, set equal flags &= ERROR_FLAG
|= Inclusive OR, set equal flags | = ERROR_FLAG
^= EXclusive OR, set equal flags ^= ERROR_FLAG
++ Increment i ++

68
–– Decrement i  – –

 Beep see Tone


A Beep is a tone of short duration. 

Button see Switch

CALL see also Stack


CALL means to branch to, and return from a subroutine. It does NOT mean GOTO. GOTO means to branch
unconditionally and maybe not return to the present routine. CALL means to branch to another sub-routine
and RETURN to the next address. Every CALL must have its own RETURN or RETLW 00 to 0FFh
statement. When a CALL instruction is executed, the next address-value is placed on the stack and the micro
goes to the location identified in the instruction.
Do not "GOTO" a sub-routine that has a RETURN at the end of it. The micro will not know where to return as
the GOTO instruction does not put a return address into memory (the stack).
The CALL instruction works to the full 1024 locations in a PIC16F84A chip.
But the CALL instruction only works to the first 256 locations (half the memory - called the first page of
memory and sometimes referred to as Page0) in a PIC12C508A.
To use the CALL instruction in a PIC12C508A, use the first 256 locations in the normal way and if any more
sub-routines are required, they are accessed as a GOTO. At the end of the sub-routine you place a GOTO to
take the microcontroller back to the Main program. Remember this: any sub-routine with a GOTO can only be
accessed ONCE from Main. (Alternatively you can place all the instructions of these extra sub-routines in
Main.)  If you want to access a sub-routine many times, put it in the first 256 locations and use CALL. Always
put Tables in the first 256 locations, and remember, a Table cannot extend over the 256 byte boundary, for a
PIC12C508A.

USING THE CALL INSTRUCTION


The micro will come to CALL Delay in the sub-routine below. It will then advance down the program to Delay
and carry out instructions until it reaches RETURN. The micro will then move up the program to the xxx line. 

CALL Delay
xxxxxxxxx
--------
--------
--------

Delay MOVLW 80h ;Put 80h into W


MOVWF 1A ;Copy 80h into file 1A
DECFSZ 1A,1 ;Decrement file 1A
DelA GOTO DelA ;Loop until file 1A is zero
RETURN

CALL Table   see also Table and Output a Table Value 


The instructions CALL Table uses the value in W and adds it to the Program Counter (PC - location 02 (file
02) - the ,1 indicates the value in W will be placed in the PC file) to create a JUMP VALUE to jump down a
Table and pick up a value. The instruction beside each value in a table places the value in W and makes the
micro return to the instruction after CALL Table. The next instruction should be to move the value from W to
a file.

Call MOVF 1A,0 ;File 1A contains 05. Move it to W


CALL Table ;W will return with display-value for "5" (6D)
MOVWF 06 ;Output display value to 7-segment display

69
Table ADDWF 02h,1 ;Add W to the Program Counter to create a jump. 
RETLW 3Fh ;0    format= gfedcba
RETLW 06h ;1
RETLW 5Bh ;2
RETLW 4Fh ;3
RETLW 66h ;4
RETLW 6Dh ;5
RETLW 7Dh ;6
RETLW 07h ;7
RETLW 7Fh ;8
RETLW 6Fh ;9 

Carry 
The carry bit is located in the STATUS register (file 03) and is bit 0. 
It is cleared by the instruction: 
BCF 03,0 - clear bit0 in file 03
Carry is SET by the instruction:
BSF 03,0   

To test the carry:


BTFSS 03,0
GOTO AAA     ;The micro will go HERE if the carry is NOT set.
GOTO BBB     ;The micro will go HERE if the carry is SET.

CBLOCK
A directive used for defining file registers to be reserved in an application. The format of  CBLOCK is:

cblock 0x0C ;define the start of the files


Lowbyte ;this will be file 0C
Medbyte ;this will be file 0D
Hibyte ;this will be file 0E etc  etc  etc
endc
This method of declaring variables is quite good, but macros cannot take advantage of it.

Change Direction 
The direction of an input/output line (or a whole port) can be changed at any time during the running of a
program. See SetUp for setting up the Input/Output lines. See Input for the instruction(s) to make a line
Input. See Output to make a line Output. Lines are changed by setting or clearing bits. This is called BIT
MANIPULATION. This prevents touching (and upsetting) other lines. 
See Toggle to change the direction of a line. 

Compare
To compare two values, you can use XOR.
To compare two numbers, they are XORed together and if they are the same, the Z flag will be set. Take two
numbers: 

number  =  7A 0111 1010 


W         =  7A 0111 1010 

Starting at the right hand end, ask yourself the question, "Is one OR the other a 1?" The answer is no. The
next column. "Is one number OR the other a 1?" No BOTH the numbers are 1! so that's why the answer is
NO. In this way every column has the answer NO, when both numbers match. 
When all the answers are Zero, the flag rises! to say the result is ZERO. In other words it is SET. 
To find the zero flag look in the STATUS register, bit 2, i.e. File 03,2. 

e.g: To compare two files: 

                MOVF 1A,0           ;Move one file into W 


70
                XORWF 1B,0         ;XOR W and 1B 
                BTFSS 03,2           ;Test Z flag  If Z flag is SET (ie 1) the two files are the SAME! 

The same thing can be done by using the subtract operation:

                MOVF 1A,0           ;Move one file into W 


                SUBWF 1B,0         ;Subtract W from 1B 
                BTFSS 03,2           ;Test Z flag  If Z flag is SET (ie 1) the two files are the SAME! 

Same: Z flag is SET (ie 1) when the two files are the SAME!

Comparison
The contents of a file can be compared with the contents of the working register (W) to determine their
relative magnitudes. This is done by subtracting the contents of W from the selected file. By testing the Carry
and Zero flags, 4 results can be obtained: 
E.g: 

                MOVLW 22h          ;Put 22h in W 


                MOVWF 0CD         ;Move 15h to file 0C 
                MOVLW 15h          ;Put 15h in W 
                SUBWF 0C,1         ;Subtract 15h from 22h 
                BTFSS 03,2           ;Test Zero flag 

OR 

                BTFSS 03,0           ;Test Carry flag 

Zero flag is SET if W = File value = Match 


Zero flag is CLEAR if no Match 
Carry flag is SET if a borrow did not occur (W is less than or equal to file value) 
Carry flag is CLEAR if a borrow occurred (W is greater than file value) 

(Put a value into W and perform SUBWF). Test Carry:


More than: Carry flag is CLEAR if W is greater than file value.
Less than: Carry flag is SET if W is less than or equal to file value.

Suppose a file (file 1E) is incremented to 8 such as in the Logic Probe with Pulser. We need to know if the file
is 1, 2 or 3. The first thing to do is eliminate the possibility of zero. 

TestA    MOVLW 00h          ;Eliminate file 1E if it is zero, 


             XORWF 1E,0         ;XOR file 1E with W
             BTFSC 03,2          ;Test the zero flag to see if file 1E is zero
             GOTO TestA1       ;File 1E is zero

The SUBWF operation below subtracts the W register (via a process called the 2's complement method) from
file 1E and the carry flag in the Option register (file 03) will be SET if 1E is equal to W or more than W (i.e: 4
or more). 

             MOVLW 04            ;Put 04 into W for subtract operation


             SUBWF 1E,0          ;Carry will be set if 1E is = or more than 4
             BTFSS 03,0            ;Test the carry flag 
             GOTO Hi                ;Go to another sub-routine such as "Hi"

Here is the outcome for all the possibilities for file 1E:
     If 1E = 0   C = 0  (we have eliminated the possibility of zero via the first 4 lines above)
     If 1E = 1   C = 0  (carry is zero - this is not the CARRY BIT it is the SET (1) or clear (0) indicator)
     If 1E = 2   C = 0
     If 1E = 3   C = 0 (carry is clear)

71
     If 1E = 4   C = 1 (carry is set)
     If 1E = 5   C = 1
     If 1E = 6   C = 1
     If 1E = 7   C = 1
     If 1E = 8   C = 1

The carry bit in the Option file is bit 0.  Therefore we test bit 0 of file 03:
       BTFSS 03,0
The result in 1E can only be 1, 2, or 3. 

Debounce a Button (Switch)


See Switch and Poll

Debug
This is not a term used in creating a program in PIC language, however we have two suggestions for finding
a "bug" or problem in a program. 
1. Go back to your previously saved version and note the differences in the programs. Try to visually detect
the fault. 
2. "Home-in" on the faulty section and see how far the micro is getting through by inserting a Wait instruction.
(See Wait)   A LED on an output line will illuminate to indicate the micro has reached the instruction.    

Decrement
To decrement a file, use the instruction: DECF 1A,1. This puts the new value back into the file. Do not use
DECF 1A,0 as the new value goes into W!
To decrement a file twice, use:
DECF 1A,1
DECF 1A,1
To halve the value of a file, the contents is shifted right:
RRF 1A,1- the file must not have a bit in bit0. 
A file can be decremented until it is zero:   
DECFSZ, 1A,1   

Delay
A delay sub-routine is needed for almost every program. One of the main purposes is to slow down the
execution of a program to allow displays to be viewed and tones to be produced. 
The shortest delay is NOP. This is a "do nothing" instruction that takes 1 micro-second. 
You will need one million "NOP's" to produce a 1 second delay. 
This is impractical as the program space will only allow about 1,000 instructions. 
The answer is to create a loop. If a file is loaded with a value and decremented, it will create a short delay.
The two instructions: DECFSZ 1A,1 and GOTO DelA will take 3uS.    80h loops = 127 loops x 3 + 1 loop x
2uS  +  2uS on entry + 1uS on exit = 386uS       code

Del MOVLW 80h ;Put 80h into W


MOVWF 1A ;Copy 80h into file 1A
DelA DECFSZ 1A,1 ;Decrement file 1A
GOTO DelA ;Loop until file 1A is zero
RETURN

A simpler delay routine below decrements a file with 256 loops. Each loop is 4uS and the result is slightly
more than 1,000uS = 1mS. The routine exits with 00h in the file. On the second execution, the routine
performs 256 loops - the file does not have to be pre-loaded. 
The longest delay (such as the one below) using a single file is approx 1mS.       code

Del NOP
DECFSZ 1A,1 ;Decrement file 1A
GOTO Del ;Loop until file 1A is zero

72
RETURN
1mS delay

NESTED DELAYS
To produce delays longer than 1mS, two or more files are needed. Each file is placed around the previous to
get a multiplying effect. The inner delay produces 256 loops, the output file produces 256 loops of the inner
file. This results in 256 x 256 loops = 256mS.
The simplest delay decrements a file to zero. At the end of an execution, a delay contains 00 and this
produces the longest delay, the next time it is used. 
This means a file does not have to be pre-loaded. 
The following is a two-file nested delay. The delay time is approx 260mS (say 1/4Sec): code

Del NOP
DECFSZ 1A,1 ;Decrement file 1A
GOTO Del ;Loop until file 1A is zero
DECFSZ 1B,1 ;Decrement file 1B
GOTO Del ;Loop until file 1B is zero
RETURN
260mS Delay

If you want a delay between 1mS and 256mS, you will need to pre-load file 1B. For each value loaded into
file 1B, a delay of 1mS will be produced. A 125mS delay is shown below:      code

Del MOVLW 7Dh ;Load W with 125 for 125mS delay


MOVLW 1B
Del1 NOP
DECFSZ 1A,1 ;Decrement file 1A
GOTO Del1 ;Loop until file 1A is zero
DECFSZ 1B,1 ;Decrement file 1B
GOTO Del1 ;Loop until file 1B is zero
RETURN
125mS Delay 

Detect a value
If a file has been incremented in a sub-routine you may want to know the value it contains. 
You may want to know its exact value or if it is higher or lower than a certain value. 
To see if it is an exact value, it is XORed with a known value. See XOR.
To detect a particular value, they are XORed together. See XOR. 
You can also detect a particular value by BIT TESTING. You must make sure that all the numbers being
tested can be distinguished by testing a single bit. For example: 1, 2, 4, 8, 10h can be tested via bits 0, 1, 2,
3, 4. But if 3 is included in your requirement, you cannot test a single bit.  

Different
To find out if two numbers are different, they are XORed together. See XOR

Divide
Simple division such as divide by 2 can be performed by the RRF instruction. Successive RRF's will divide by
4, 8, sixteen etc. Other divisions are beyond the scope of this course. The number cannot have a bit in bit0, if
an accurate division is required.
Double
To double the value of the contents of a file, it is shifted LEFT (RLF 1A,1).    The number must be less than
80h. (it must not have a bit in location bit7).

73
EEPROM 
The PIC16F84 has 64 bytes of EEPROM to permanently store data. 
If you need to store only a few bytes of data for a short period of time, use files that are not required for the
running of the program. This information will be lost when power is removed. 
The 64 bytes of EEPROM requires a special set of instructions to place data into EEPROM. The actual
writing time for this data is very long (in computer terms) and can be done in the background, while the main
program is executing. A flag will SET when the data has been written and this will allow another byte of data
to be entered. 
Each EEPROM cell can be written about 1 million times. 

Before reading a value in a location in the EEPROM, it must be loaded with a value during "burning." To load
the first location in EEPROM with a value, the following instructions are placed in a program. The EEPROM
starts at location 2100h and the term DE means: "define EEPROM." There are 64 EEPROM locations and by
following the layout in the second table, any location can be addressed during burning.        code

  ORG 2100h   ;Starting point of EEPROM on 16C84 or 16F84


DE 00h   ;First EEPROM location initialized to zero
END

 To load more locations in EEPROM, the following layout is used:

Example: To read the value at the first address in EEPROM, DECrement it and
write the new2100h  
ORG value into the first address, use the following ;Starting
sub-routine:
point 
DE 84h, 16h, 23h, 80h, 0CAh, 32h, 7Bh, 0A2h  ;
Dec MOVLW 00h  25h, 02h, 0FFh, 20h, 03h, 04h 
DE 34h, 53h, ;
MOVWF 09h  ;EEPROM Address is file ;for
09 up to eight lines
CALL
END EERead ;Get EEPROM value
MOVWF 1E   ;Move to temp file 1E 
DECF 1E, 0  ;DECrement and put new value into W
CALL EEWrite ;Write new value to EEPROM 
CALL EERead ;Get new EEPROM value
RETURN

READ EEPROM:
The sub-routine to read a value in the EEPROM is shown below. It reads EEPROM
data at location specified in EEADR and returns the value in W             code

EERead BSF Status, RP0   ;Go to Bank 1


BSF EECON1, RD  ;Set the RD bit
BCF Status, RP0  ;Back to bank 0
MOVF 08, W  ;EE Data is file 08.  Put into W
RETURN

 WRITE TO EEPROM:
The sub-routine to write to EEPROM is shown below.              code

Delay1 MOVLW 13h ;Create a 20mS delay


MOVWF 1B ;20 loops
Delay1a NOP

74
DECFSZ 1A,1 ;4uS x 256 loops=approx 1mS
GOTO Delay1a
DECFSZ 1B
GOTO Delay1a
RETLW 00 ;Return

EEWrite MOVWF 08 ;W to EEData


BSF 03,5 ;Switch to bank 1
BCF 0B,7 ;Disable interrupts
BSF 08,2 ;Write Enable bit set
MOVLW 55h ;Toggle EEPROM Control  
MOVWF 09              Register bits
MOVLW 0AAh ;Toggle EEPROM Control  
MOVWF 09              Register bits
BSF 08,1 ;Begin write sequence
CALL Delay1 ;Call Delay1
BCF 08,2 ;Disable any further writes
BSF 0B,7 ;Enable Interrupts
BCF 03,5 ;Back to data bank 0
RETURN  ;Return

 End of Table
The end of a table can be detected in two different ways.
If a value such as FF is not used in any of the data, it can be used as an End
of Table marker. The sub-routine calling the table must look for 0FFh to
detect End of Table.

Table ADDWF 02h,1 ;Add W to the Program Counter to create a jump. 


RETLW 3Fh ;0    format= gfedcba
RETLW 06h ;1    
RETLW 5Bh ;2    
RETLW 4Fh ;3
RETLW 66h ;4
RETLW 6Dh ;5
RETLW 7Dh ;6
RETLW 07h ;7
RETLW 7Fh ;8
RETLW 6Fh ;9 
RETLW 0FFh ;End of table marker

The other method is to count the number of items in a table and make sure the sub-
routine calling the table doe not CALL values beyond this value.

FSR See Indirect Addressing 


This is a special file called File Select Register. It has the address 04. It is not a file
like the other files in the micro but a POINTER FILE and is used in conjunction with
another file called INDF. 
INDF has the address 00. 
INDF is not actually a file but a robot arm. It grabs the contents (or delivers contents)
to a file pointed to by FSR. These are two special files (devices) that allow very
powerful (low instruction) programming to be produced.  
For instance, if FSR is loaded with 0C, it will tell INDF to grab (or deliver) contents to
file 0C. 
To do this, we need the instructions:
MOVLW 0C
75
MOVF 04
If we now put 8Fh into INDF, the value will actually go into file 0C. 
This is called INDIRECT ADDRESSING. 

 GOTO or Jump   to a location according to a value in a file.   (See Jump)

Halt
Do not use the word "Halt" as a label, the assembler does not like it. Use Loop,
Pause, Stop, Wait.  See Loop and Stop.

Halve (Half)
To halve (half - divide by two) the value of the contents of a file, it is shifted RIGHT
(RRF 1A,1).    The number must be an even number (it cannot have a bit in bit0). 

Higher
To find out if a number is higher than a know value, a comparison is made. See
Comparison. 

Increment
To increment a file, use the instruction: INCF 2A,1. This puts the new value back
into the file.
Using INCF 2A,0 puts the new value also into W!
To add two to a file, it can be incremented twice:
INCF 2A,1
INCF 2A,1
To double the value of a file, the contents is shifted left:
RLF 2A,1
A file can be incremented until it "rolls over to zero."  Normally a file is decremented
to zero and a skip occurs when it is zero. But the same effect can be produced by
incrementing a file: 
INCFSZ, 2A,1  
To increment W, use ADDLW, thus:  ADDLW  01   or  ADDLW 3Bh

Indirect Addressing 
A number of files can be addressed by a sub-routine and the information can
be moved into each file or read from each file. The files must be a group.
Suppose we have 8 files and need to read the contents and output it to a
display. 
The files are:  21h, 22h, 23h, 24h, 25h, 26h, 27h, and 28h. 
There are two special files that allow a sub-routine to be created to look at
the 8 files and read the contents. 
They are: INDF and FSR
The INDF file is not a real file. It is like a Robot Arm. It reaches down the
list of files and picks up the contents or delivers the contents of a file to the
programmer. The file it reaches is determined by the value in FSR. 
FSR is loaded with the address of the file you wish to read or write. 
This arrangement has an advantage. By loading FSR with a value, you can
reach a file and by incrementing FSR, you can reach the next file etc. 
If you load a value into INDF, you will actually load the value into the file
pointed to by FSR.
If you read INDF, you will actually read the contents of the file pointed to by
76
FSR. 
You can consecutively read 8, 10 or 20 files or clear 20 files or load into 20
or more files with a simple looping sub-routine. It's a very powerful feature. 
The following instructions put a value of 8Fh into file 21h. 
MOVLW 21h ;Load W with start of 8 files
MOVWF 04 ;Load 21h into FSR
MOVLW 8Fh ;Put 8F into W
MOVWF 00 ;Put 8Fh into file 21h

The animation below shows how the information passes to the files:

Using INDF and FSR 

 The following instructions put a value of 8Fh into files 21h, 22h, 23h, 24h,
25h, 26h, 27h and 28h. 

MOVLW 08 ;8 loops of the program


MOVWF 20h ;File 20h is the decrementing file
MOVLW 21h ;Load W with start of 8 files
MOVWF 04 ;Load 21h into FSR
MOVLW 8Fh ;Put 8F into W
Loop1 MOVWF 00 ;Put 8Fh into file 21h
INCF 04 ;Increment FSR to make INDF go to next file 
DECFSZ 20h
GOTO Loop1
RETURN

The following instructions read files 21h, 22h, 23h, 24h, 25h, 26h, 27h and
28h and output to port B (file 06). 

MOVLW 08 ;8 loops of the program


MOVWF 20h ;File 20h is the decrementing file
MOVLW 21h ;Load W with start of 8 files
MOVWF 04 ;Load 21h into FSR
Loop1 MOVF 00,0 ;Copy file 21h (or next file) into W
MOVWF 06 ;Move W to output Port B
CALL Delay ;Show value on 7-segment display etc
INCF 04 ;Increment FSR to make INDF go to next file 
DECFSZ 20h

77
GOTO Loop1
RETURN

INDF See Indirect Addressing and FSR


This is a special file called INDirect File. 
INDF has the address 00. 
INDF is not actually a file but a robot arm. It grabs the contents (or delivers contents)
to a file pointed to by FSR. 
This is used in an operation called INDIRECT ADDRESSING.  

Input
The files (also called Registers) we are dealing with in this section are
actually the TRIS files. These are located in Bank1 and the address is 05 for
PortA and 06 for PortB. 
PortA for a PIC16F84 has 5 lines: RA0, RA1, RA2, RA3, and RA4. 
PortB for a PIC16F84 has 8 lines: RB0, RB1, RB2, RB3, RB4, RB5, RB6,
and RB7.
Port A is usually the input lines and Port B is usually the output lines. 
To make a line INPUT, the corresponding TRIS bit must be "1."
To make a line OUTPUT, the corresponding TRIS bit must be "0."
To make a line INPUT (or OUTPUT), the instructions must be placed inside
BSF 03,5 and BCF 03,5.
For example, to make the lowest line of Port A, an INPUT, the following
instructions are needed:

BSF 03,5 ;Go to Bank 1


MOVLW 01 ;Load W with 0000 0001
MOVWF 05 ;Make RA0 input
BCF 03,5 ;Go to Bank 0 - the program memory area.

The other individual lines are:


MOVLW 02    ;Load W with 0000 0010
MOVWF 05    ;Make RA1 input

MOVLW 04    ;Load W with 0000 0100


MOVWF 05     ;Make RA2 input

MOVLW 08    ;Load W with 0000 1000


MOVWF 05     ;Make RA3 input

MOVLW 10    ;Load W with 0001 0000


MOVWF 05     ;Make RA4 input

MOVLW 20    ;Load W with 0010 0000


MOVWF 05     ;Make RA5 input

To make more than one line (with a single instruction) an input, the hex
values are added.

78
MOVLW 0F    ;Load W with 0000 1111
MOVWF 05     ;Make RA0, RA1, RA2, RA3 input

MOVLW 12    ;Load W with 0001 0010


MOVWF 05     ;Make RA1, RA4 input

This also applies to port B:

MOVLW 33    ;Load W with 0011 0011


MOVWF 06     ;Make RB0, RB1, RB4, RB5 input

Port direction can be changed at any time during the running of a


program. You must make sure that any input or output devices on the line
will not upset the running of the program.  
In this case it is best to SET or CLEAR a BIT. This involves setting or
clearing an individual bit. This prevents touching any other lines.
Eg: To make the lowest line of port B an input:

BSF 03,5 ;Go to Bank 1


BSF 06,0 ;Make RB0 input
BCF 03,5 ;Go to Bank 0 - the program memory area.

Carry out instructions using the input line, then make the line an output:

BSF 03,5 ;Go to Bank 1


BCF 06,0 ;Make RB0 output
BCF 03,5 ;Go to Bank 0 - the program memory area.

Jump or GOTO   to a location according to a value in a file.

In theory, this will allow you to go to 256 different places in a program, but
the instructions to do this will be huge.   To GOTO say 8 different locations,
use the following instructions. Use file 23h and load it with 0000 0001, 0000
0010, 0000 0100, or 00001000, etc and test the particular bit to see if it is
CLEAR (0). If it is CLEAR, the micro will go down the program until it
finds the bit which has been SET.  

BSFSC 23h,0 ;
GOTO Link0 ;
BSFSC 23h,1 ;
GOTO Link1
BSFSC 23h,2
GOTO Link2
BSFSC 23h,30
GOTO Link3
etc

79
Less than  - see Comparison
Load a file
This operation cannot be done directly. A number (a value) is called a
LITERAL. It is loaded into W then the value in W is moved to a file. The
two instructions are:

MOVLW 0FFh ;Load a value (called a Literal) (00 to 0FFh) into W


MOVWF 1A ;Move the value in W to a file

Look at an Input
There is no instruction called "look."  If a switch or button is connected to an
input line such as the lowest line on Port A, the instruction is:

BTFSS 05,0 ;Is button pressed?


GOTO No ;No
GOTO Yes ;Yes

This assumes the switch is connected to the positive rail and the input goes
HIGH when the button is pressed. 
This instruction also works for a signal on line 05,0. You must make sure line
05,0 is an INPUT via the SetUp routine. 
The two instructions after BTFSS 05,0 can be "GOTO Yes", "GOTO No"  
by changing the first instruction. The decision will depend on the number of
instructions for the "Yes" or "No" answer, as the instruction placed directly
after BTFSS 05,0 must be a GOTO. 

BTFSC 05,0 ;Is button pressed?


GOTO Yes ;Yes
GOTO No ;No

Loop
The action of looping is carried out for a number of reasons. The micro does
not have a Halt or Stop feature and must carry out instructions at all times. A
loop will hold the micro in one place. 
To get out, a set of instructions such as "look" is needed inside the loop.
These instructions see if a button has been pressed etc. Alternatively, if the
watchdog timer is SET, the micro will come out of the loop and go to
location 04. The instructions to create a loop are as follows: 

Loop NOP
GOTO Loop

Lower
To find out if a number is lower than a know value, a comparison is made. See
Comparison. 

80
Macro
A Macro is similar to a sub-routine. You can call it from anywhere in a program. The
aim of a macro is to save lines of code.

Some assemblers have built-in macros and recognise abbreviations such as the
following:
Do not use these instructions unless you know EXACTLY what you are
doing.
fr = file register
For instance, we will explain the following instruction in the table below:
Branch on No Zero to addr     =     btfss   3, 2    goto addr.   (file 3, bit 2 is the
zero flag)
Test the zero flag. Skip if it is set. In other words skip if the zero flag is set,
but BRANCH if it is not zero!

Mnemonic Description Function


addcf fr, d Add carry to fr btfsc   3, 0   incf  f,d
subcf fr, d Subtract carry from fr btfsc   3, 0   decf  fr,d
negf fr, d Negate file register fr comf   fr, 1   incf  fr,d
b   addr Branch to addr goto    adddr
bz   addr Branch on Zero to addr btfsc   3, 2    goto addr
bnz   addr Branch on No Zero to addr btfss   3, 2    goto addr
bc   addr Branch on Carry to addr btfsc   3, 0    goto addr
bnc   addr Branch on No Carry to addr btfss   3, 0    goto addr
skpc Skip on Carry btfss   3, 0
skpnc Skip on No Carry btfsc   3, 0
skpz Skip on Zero btfss   3, 2
skpnz Skip on No Zero btfsc   3, 2
clrz   Clear Zero flag bcf    3, 2
setz  Set Zero flag bsf    3, 2
clrc  Clear Carry flag bcf    3, 0  
setc Set Carry flag bsf    3, 0  
tstf   fr Test file register fr movf  fr, f
decbnz fr,addr Decrement fr, if zero decfsz  fr  goto addr
branch to addr

Main
The Main routine is constantly looped and generally consists of sub-routines that are
CALLed.  

Main CALL Switch


CALL Display
CALL Beep
GOTO Main ;Loop Main

Mask
If you want to remove a number of bits from a file, the operation is called
MASKING. 
You can remove the high or low nibble (a nibble is a set of 4 bits) or any other bits.
Any number from 0 - 7 can be obtained by masking (removing) bits 3,4,5,6,7, and
leaving only bits 0, 1 and 2.
To mask (remove) the upper nibble, the number is ANDed with 0F. To mask the

81
lower nibble, the number is ANDed with F0.  (this is written: 0F0h in the program)  

1001 0111
number: 1111 0000
W: 1001 0000
answer:

MOVLW 97h ;Put 97h into W


MOVWF 1A ;Move 97h into file 1A
MOVLW 0F0h ;put the "masking value" into W
ANDWF 1A,1 ;AND 97h with file 1A. The result will be in file 1A. 

More  than  - see Comparison

Move a file to W
The contents of a file can be moved to W with the following instruction:
MOVF 1A,0  The contents are actually COPIED. The original file still holds the
contents. 

Move a file to another file


The contents of a file can be moved to another file via the following
instructions. 
It is firstly copied to W then W is copied to the new file:

MOVF 1A,0 ;The contents of file 1A is copied to W


MOVWF 1B ;W is copied to file 1B

Multiply
Simple multiplication such as multiply by 2 can be performed by the RLF
instruction. Successive RLF's will multiply by 4, 8, sixteen etc. You need to
be careful as this is called a "blind" operation. 
A number such as 80h (128) will not be doubled as 1000 0000 will be moved
to the left and the top bit will be passed to the Carry. Only numbers up to 7F
(127) can be doubled. 
To multiply by 2:

  RLF 0C,1 ;The contents of file 1A is doubled

To multiply any two numbers together requires a program. Since the PIC16F84 does
not have any multiply function, it is carried out by successive ADDITIONS. A number
from 01 to 255 can be multiplied by 01 to 255. 
To multiply 75(4Bh) by 122(7A), 122 is added to a file 75 times. It needs two files to
hold the answer.

CLRF 1B ;Clear the receiving file


CLRF 1C ;Clear the receiving file
MOVLW 7Ah  ;122
MOVWF 1A,1 ;file 1A holds 122

82
MOVLW 4B  ;75
M1 ADDWF 1B,1 ;ADD 75 to file 1B
BTFSS 03,0  ;Test Carry bit in status
GOTO M2  ;file. CLEAR = no carry
INCF 1C,1  ; SET = carry
M2 DECFSZ 1A,1
GOTO M1
RETURN

The result is a 16 bit binary number of the form: file 1C, file 1B  = 0000 0000 0000
0000
To multiply two numbers and obtain a decimal result requires a different program. 

Nested Delay
See Delay 

Origin  -  ORG
This is a pseudo instruction that tells the assembler where to place the next
instruction.   ORG must have a value. For ORG 000, the next real instruction will be
placed at memory location 000.
For ORG 1CC, the next instruction will be placed at address location 1CC as
shown below: 
Main CALL Switch
CALL Display
CALL Beep
  GOTO Main

Output a Table Value see also Table


Suppose file 1A contains 05 and this corresponds to the figure "5" on a 7-
segment display. 
Here are the instructions: 

Table ADDWF 02h,1 ;Add W to the Program Counter to create a jump. 


RETLW 3Fh ;0    format= gfedcba
RETLW 06h ;1    
RETLW 5Bh ;2    
RETLW 4Fh ;3
RETLW 66h ;4
RETLW 6Dh ;5
RETLW 7Dh ;6
RETLW 07h ;7
RETLW 7Fh ;8
RETLW 6Fh ;9 

MOVF 1A,0 ;File 1A contains 05. Move it to W

83
CALL Table ;W will return with display-value for "5" (6D)
MOVWF 06 ;Output display value to 7-segment display

Output a Value
The output ports for a PIC16F84 are actually FILES or REGISTERS!  Port A is file
05 and Port B is file 06. 
Port A has 5 lines, called RA0, RA1, RA2, RA3, and RA4. 
Port B has 8 lines, called RB0, RB1, RB2, RB3, RB4, RB5, RB6 and RB7.  
Each line can deliver approx 25mA. The maximum total current for the chip is about
150mA.
An output line can be HIGH or LOW. Each output line corresponds to a bit in the file
associated with the port. When the bit is SET, the line is HIGH. When the bit is
CLEAR, the line is LOW. 
Before you can make a line HIGH or LOW, the file must be "configured." This means
each bit must be made an OUTPUT. This is done via the TRIS file. The TRIS 05 file
operates on file 05 = Port A , and TRIS 06 operates on file 06 = Port B. 
Any line can be made either an input or an output at any time during the running of a
program and to make a line INPUT, the corresponding bit in the TRIS file is made
"1." To make a line OUTPUT, the corresponding bit in the TRIS file is made"0."
There are two ways to get to the TRIS file. One is directly via the instruction
TRIS 05 or TRIS 06.

MOVLW 03 ;Load 0000 0011 into W


TRIS 05 ;Make RA2 and RA3 and RA4 output.

The other is via the two instructions: BSF 03,5 and BCF 03,5. These
instructions allow you to go to  bank1 where the TRIS file is located. When
in Bank1, the TRIS file is called 05 and 06.

BSF 03,5 ;Go to Bank 1


MOVLW 00 ;Load W with 0000 0000
MOVWF 06 ;Make all Port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.

Any lines that are made output can be made HIGH or LOW.

MOVLW 1Ch ;Load 0001 1100 into W


MOVWF 05 ;Make RA2 and RA3 and RA4 HIGH.

MOVLW 0FFh ;Load W with 1111 1111


MOVWF 06 ;Make all Port B HIGH

Poll See also Switch


The action of POLLING means to "look at - on a regular basis."  It generally refers
to an input device such as switch or push button. A push button can be pressed and
released in less than 10th second and this means it must be scanned or polled 10
times a second (100mS).
This means you have 100,000 machine cycles available between "looks." 
Most programs consist of a Main routine and this is looped on a regular basis. As a
program gets larger and larger, the Main routine may loop at a slower rate (mainly
due to delay sub-routines needed for some of the operations) and you may exceed

84
the 100,000 limit. 
The answer is to place the "look" feature inside the delay sub-routine.  The following
sub-routine has a "Look" feature inside a Delay:

Delay MOVLW 01h ;Approx 300mS per "unit"


MOVWF 1C
Delay1 NOP
DECFSZ 1A,1
GOTO Delay1
BTFSS 05,0 ;Look at push-button line on port A
GOTO Not ;Button not pressed
BSF 1F,0 ;Set button-press flag
RETURN
Not BCF 1F,0 ;Clear button-press flag
BCF 1F,1 ;Clear "action" flag
Delay2 DECFSZ 1B,1
GOTO Delay1
DECFSZ 1C,1
GOTO Delay1
RETURN

CALL Delay
Main other instructions
BTFSS 1F,0 ;Has button been pushed?
GOTO Main ;No.
BTFSC 1F,1 ;Yes. Has "action" already been performed?
GOTO Main ;Yes.
BSF 1F,1 ;No.
CALL Action
GOTO Main

The Delay sub-routine includes instructions to look at a button and set a flag (BSF
1F,0) when it is pressed. 
The micro comes out of the Delay routine with the flag is SET. The flag is then
looked at in Main and the appropriate sub-routine is executed. 
This sequence may be executed very quickly and the micro may return to Delay
before the button is released. The "action" flag (BTFSC 1F,1) prevents the action
being carried out more than once for a single button-press. 
When the button is released, both flags are cleared. 

Random number see also Mask


A truly random number cannot be generated by a computer as a sequence is nearly
always produced. However it can be created by monitoring human intervention -
such as the pressing of a button etc. Put the random number file in a place where it
will increment regularly and where human involvement will cause the number of
cycles etc to change by an unknown amount. 

  INCF 11h,1  ;Increment the random number

The random number file will then need to be MASKED to obtain a set of bits and
incremented if zero is not needed.

Read a File
85
Files can be used to store temporary data.  

Read Data
The PIC16F84 does not have a feature such as "Read Data" or "Read an
Instruction." Data can be added into a program in the form of a table (see Table)
and this data cannot be altered. 
Temporary data can be stored in a file or set of files. There are 68 files (from 0C to
4F) in the  PIC16F84.   

Remove bits see Mask

Return 
This instruction must be somewhere in each sub-routine. It is generally at the end,
but clever programming may allow the micro to Return part-way through the routine. 

RETLW 00 to FF - Return with Literal in W


A sub-routine can carry out an operation and set a flag. Alternatively it can return
with a value in W. 
If a sub-routine generates two or three different result, the RETLW 00 to FF
instruction can Return with the appropriate value in W. 
RETLW 00 to FF is used for each value of data in a Table. (see Table)

Rotate
This is the same as SHIFT.  All the bits in a file are moved to the left or right through
the CARRY. 
Carry is located in the STATUS file (03,0).
It requires 9 shifts (rotates) to get the bits back to the original position. 
The CARRY must be cleared (BCF 03,0) if you don't want it to appear in the file. 
RLF (Rotate Left File) increases the value of the contents (doubles the value).
RRF (Rotate Right File) decreases the value of the contents (halves the value).  

Same
To find out if two numbers are the same, they are XORed together. See XOR and
Comparison

SetUp
The first sub-routine in a program is SetUp. It sets the direction for each
Input/Output line and clears any other files to get them ready for incrementing etc. 
To make a line INPUT or OUTPUT, see INPUT, OUTPUT.
Instructions between BSF 03,5 and BCF 03,5 are dealing with files files in Bank 1.
For instance, if files 05 is loaded with 02, this is actually the TRIS A file. CLRF 06 is
clearing the file called TRIS B. This file controls the direction of the Input/Output
lines of Port B and when it contains 0's, all the lines are output.

ORG 0 ;This is the start of memory for the program.


SetUp BSF 03,5 ;Go to Bank 1
MOVLW 02 ;Load W with 0000 0010
MOVWF 05 ;Make RA1 input
CLRF 06 ;Make all port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 1F ;Clear flag file
CLRF 05 ;Clear Port A (RA0 - RA4)
CLRF 06 ;Clear Port B (RB0 - RB7)

86
GOTO Main

To make SetUp suitable for both a PIC12C508A and PIC16F84, use the following:  

ORG 0 ;This is the start of memory for the program.


SetUp MOVLW 08 ;Load W with 0000 1000
TRIS 06 ;Make RB3, (GP3) input
OPTION 0DFh ;Make GP2 an output & disable weak pullups
MOVLW 17h ;Make GP0, GP1, GP2, GP4, GP5 HIGH
MOVWF 06
GOTO Main

Shift  see Rotate   

SLEEP   
This instruction puts the micro to sleep. This is also called "power-down mode."
The micro stops executing the program when it comes to this instruction.
If the Watchdog Timer is enabled, it will be cleared but will keep incrementing.
The In/Out lines maintain the status they had before SLEEP was executed.
For the lowest consumption in SLEEP, all output lines must not drive any circuitry
before the SLEEP instruction.
On-chip pull-ups must also be turned off to reduce the current consumption during
SLEEP.
The micro will wake up from SLEEP via one of the following:
1. Taking MCLR pin LOW
2. Watchdog Timer wake-up (if watchdog is enabled)
3. Interrupt from GP2/INT pin
4. GPIO change
5. Peripheral interrupt.
On wake-up from SLEEP, the WDT is cleared.

When the SLEEP instruction is being executed, the next instruction (PC + 1) is pre-
fetched. For the micro to wake up through an interrupt event, the corresponding
interrupt enable bit must be set (enabled). Wake up is regardless of the state of the
GIE bit. If the GIE bit is clear (disabled) the micro continues execution at the
instruction after SLEEP. If the GIE bit is set (enabled) the micro executes the
instruction after SLEEP then branches to the interrupt address (004h). In the case
where the instruction following SLEEP is not desirable, the user should have a NOP
after the SLEEP instruction.   
The TO and PD bits in the STATUS register can be used to determine the cause of
RESET. The PD bit, which is set on power-up, is cleared when SLEEP is invoked.
The TO bit is cleared if WDT wake-up occurred.
 
The SLEEP instruction is:

       sleep

To send the micro to the "sleep_micro" sub-routine, the following instruction is


needed:

        goto    sleep_micro

The simplest sub-routine for SLEEP is:

sleep_micro

87
                      sleep
                     
If the Watchdog timer is enabled, the micro will come out of SLEEP and goto main.
The watchdog will reset after 18,000uS (18m) and wake the micro.  
If 18mS is too short, a prescaler can be added to increase the WDT time by 2, 4, 8,
16, 32, 64 or 128. The maximum time is 18mS x 128 = 2.3sec 

The micro contains an 8-bit prescaler register that can be assigned to Timer0 or
Watchdog. This prescaler  register is not readable or writable. 
To set the prescaler to the WDT, bit 3 of the OPTION REGister must be set. The
instruction is:

      bsf      STATUS, RP0   ;select bank 1

      bsf   OPTION_REG,3


or
     movlw   b'xxxx1xxx'
     movwf   OPTION_REG

     bcf      STATUS, RP0  ;select bank 0

The three lowest bits of the Option register set the timing for the WDT:

   bsf      STATUS, RP0   ;select bank 1

   movlw  b'xxxxx000' 
   movwf  OPTION_REG  ;WDT timer = 18mS
or:
   movlw  b'xxxxx001' 
   movwf  OPTION_REG  ;WDT timer  = 36mS
or:
   movlw  b'xxxxx010' 
   movwf  OPTION_REG  ;WDT timer  = 72mS           etc  etc
or:
   movlw  b'xxxxx111' 
   movwf  OPTION_REG  ;WDT timer  = 2,304mS = 2.3 Seconds

   bcf      STATUS, RP0  ;select bank 0

GPIO CHANGE
If you want the micro to come out of sleep when the voltage-level changes on any
input line, the WDT must be turned off. This must be done during burning the
program into the chip. (You will not have the advantage of the watchdog timer to
reset the micro if it runs off the end of the program.)

    movlw   b'xxxx1xxx'     ; Enable GPIO port change interrupt (but NOT GIE)
    movwf   INTCON

Make at least one of the in-out pins an input:

   bsf      STATUS, RP0   ;select bank 1


   movlw   b'xxxx1xxx'     ;make GP3 input
   movwf  TRISIO
   bcf      STATUS, RP0   ;select bank 0

Add the SLEEP instruction to the program:

        goto    sleep_micro

88
Add the SLEEP sub-routine:

sleep_micro
                      sleep

                     
Alternately, a SLEEP instruction can be added to a program. In the program below,
the micro will stop executing instructions when it reaches "sleep" and wait for a
"time-out" of the WDT or a change in GPIO (depending on the setting in INTCON.) If
the GIE bit is set, the micro will execute "instruction A" (after sleep) and go to the
interrupt address (004h).

    instruction
    instruction
    instruction
    sleep           
    instruction A  - this instruction can be anything but a GOTO instruction.
    no further instructions

If you don't want an instruction after "sleep" use: NOP.

The Global Interrupt feature is enabled by setting bit 7 of the INTCON register. For
this and other features of SLEEP see:  PIC12F629 Data Sheet (.pdf  4,926KB)

Stack
This is an area where up to 8 addresses are placed, when a CALL is made - 8
CALLs- 8 addresses in the stack. When an address is put on the stack it is called
PUSH and when it is removed, it is called POP. If more than 8 address are placed
on the stack, the first address is lost off the end. That's why you cannot have any
more than 8 CALLs. When a return is made, the CALL number is reduced.
The PIC16F84 can have a CALL instruction that CALLs another sub-routine and the
sub-routines CALLs another sub-routine and that sub-routine CALLS another sub-
routine until 8 CALLs are made. 
The 8th sub-routine will have  a RETURN to go back the the previous sub-routine
and each sub-routine will have a RETURN until finally the micro returns to Main. 
The animation below shows a CALL in a sub-routine CALLing another sub-routine
and this sub-routine CALLs another sub-routine.  The Program Counter makes the
micro carry out the instructions:

89
A PIC12C508A has only a 2-CALL stack. This means the Main routine can CALL a
sub-routine and the sub-routine can call another sub-routine. This is the limit of the
chip.

Stop see also Wait.


The microcontroller does not have a Stop instruction. Do not use the word "Halt" as
a label, the assembler does not like it. Use Loop, Pause, Wait.  See Loop. 
To create a "waiting loop" use the following instructions:

Loop NOP ;Hold the micro in a loop


GOTO Loop 

When testing a program, you may need to know if the microcontroller has advanced
to a certain part of the program. 
Insert the instruction: GOTO Wait.
Insert the following instructions. They should include an output to a LED etc so you
can prove the micro has entered the loop. 

Wait NOP ;Hold the micro in a loop


MOVLW 1Ch
MOVWF 06 ;Put "u" on 7-segment display
GOTO Wait 

Store Data
The PIC16F84 has two ways to store data. 
If you need to store only a few bytes of data for a short period of time, use files that
are not required in any of the running of the program.
This information will be lost when power is removed. 
If you want to store data permanently, the PIC16F84 has 64 bytes of EEPROM.
This requires a special routine - found under EEPROM.  

SWAP
PIC language has a SWAP NIBBLES instruction. It swaps the HIGH nibble
with the LOW nibble.  Swapping INDF (file 00) actually swaps the nibbles in

90
the file pointed to by FSR.

  SWAPF 1A,1 ;Before: File 1A = 81h     After: File 1A = 18h

SWAP THE CONTENTS OF TWO FILES  


Example: File 0C = 81h
               File 0D = 47h
               File 0E = temp storage

  MOVF 0C,0  ;Move 0C to W


MOVWF 0E,1  ;Move W to 0E
MOVWF 0D,0  ;Move 0D to W
MOVWF 0C,1  ;Move W to 0C
MOVF 0E,0  ;Move 0E to W
MOVWF 0D,1  ;Move W to 0D

Switch (button, key) see also Poll


There is no difference between "Switch," "Button" and "Key."  They all refer to a
push button that has momentary action. It can be an individual push button, one of a
number of buttons or in a matrix of buttons such as a keypad. 
With all button instructions, there are three important things to remember. They are
mechanical devices and their action is very slow in "microprocessor-time." They
produce a lot of pulses when pushed and also when released (this is called switch-
noise or switch-bounce). In any button routine, you must also prevent a button-press
being registered more than once. 
Many sub-routines already have a switch or button feature included in them.  Select
an existing sub-routine or use the following. 
The most important part of adding a switch or button routine is creating the
debounce feature. 
This is to prevent "double-counting" when the button is pushed or released. Try
slow-pressing and slow-release to see if the program produces a false result. If the
program "double-counts," you will have to increase the debounce-time. 
Debounce can take up a lot of computer-time. Debounce is a delay routine that
"masks" (hides - or disallows) the time when the button is pressed or released, so
that only one pulse is detected. Instead of producing a separate debounce routines,
you may be able to use the time taken to execute other sub-routines. In other words,
the program looks before and after the execution of another routine and if the button
is still pressed, the micro detects it as a "button-press." 
Finally, you need to detect the first press of a button and prevent the program
operating on the button during the second pass of the program. 
The basis of detecting a button-press consists of 6 separate items that must be
placed in the following order:
There are two flags. Bit0 in file 1F is the Debounce Flag and Bit1 in file 1F is the
Button Pressed flag. 
The microprocessor executes Main and CALLs Sw. If Sw detects a key-press, two
flags are SET. The first is the Button Pressed flag and the second is the Debounce
flag.
The micro returns to Main and tests the Button Pressed flag to see if it is SET. If is
is SET, the micro goes to a sub-routine such as CALL Increment, where a value can
be incremented. The Button Pressed flag is then cleared and the micro CALLs
Sw. If the switch is still pressed, the micro will return. The program is
looking for the button to be released. When the button is released, the Sw

91
sub-routine is ready to detect another button-push.

SetUp BSF 03,5 ;Go to Bank 1


MOVLW 01 ;Put 01 into W
MOVWF 05 ;Make RA0 input
BCF 03,5 ;Go to Bank 0
CLRF 1F ;Clear the button-press file
GOTO Main

Sw BTFSS 05,0 ;Test the button. Button is "Active HIGH"


GOTO Sw2 ;Button not pressed
BTFSC 1F,0 ;Button pressed first time?  Test debounce flag
RETURN ;Button already pressed. Return to Main
Sw1 DECFSZ 1A,1 ;Create short delay
GOTO Sw1 ;Look again
BTFSS 05,0 ;Is switch still pressed?
GOTO Sw2 ;It was only noise
BSF 1F,1 ;Button Pressed.  Set button-pressed flag
BSF 1F,0 ;Set debounce flag
RETURN ;Return to Main
Sw2 BCF 1F,0 ;Clear debounce flag
RETURN ;Return to Main

Main CALL Sw
BTFSC 1F,1 ;Test button-press flag to see if button was pressed
GOTO Main2 ;Button pressed
Display the values ;Button not pressed
on a display etc.
GOTO Main
Main2 CALL Increment ;Increment the display. (you provide the routine)
BCF 1F,1 ;Clear the button-press flag
GOTO Main

Table see also Output a Table Value and CALL Table


The layout for a Table is shown below:

Table ADDWF 02h,1 ;Add W to the Program Counter to create a jump. 


RETLW 3Fh ;0    format= gfedcba
RETLW 06h ;1    
RETLW 5Bh ;2    
RETLW 4Fh ;3
RETLW 66h ;4
RETLW 6Dh ;5
RETLW 7Dh ;6
RETLW 07h ;7
RETLW 7Fh ;8
RETLW 6Fh ;9 

Toggle
The direction of a line can be changed from Input to Output or
vice versa to
create a tone or other feature. 
The instructions below do not know the initial condition of the line. They
92
simply reverses the state. The instructions are:  

MOVLW 01h ;Put 01 into W


XORWF 06,1 ;XOR 01 with Port B, lowest line (RB0)

The following instructions apply to the other lines:  Port A (05) can also be
toggled.

MOVLW 02h ;Put 0000 0010 into W


XORWF 06,1 ;XOR 02 with Port B, for RB1

MOVLW 04h ;Put 0000 0100 into W


XORWF 06,1 ;XOR 04 with Port B, for RB2

MOVLW 08h ;Put 0000 1000 into W


XORWF 06,1 ;XOR 08 with Port B, for RB3

MOVLW 10h ;Put 0001 0000 into W


XORWF 06,1 ;XOR 10h with Port B, for RB4

MOVLW 20h ;Put 0010 0000 into W


XORWF 06,1 ;XOR 20h with Port B, for RB5

MOVLW 40h ;Put 0100 0000 into W


XORWF 06,1 ;XOR 40h with Port B, for RB6

Tone see also Beep


When a line is taken HIGH then LOW at a rapid rate, a tone is produced in a
piezo or speaker. A buffer transistor (amplifier) may be needed.  
The simplest tone takes a line HIGH, then executes a delay. The line is taken
LOW and a delay is executed. This process is repeated. The following
routine shows how a tone is produced. The micro never comes out of the
Tone sub-routine. It is only suitable as an "end of the line" sub-routine.

Tone NOP
DECFSZ 1A,1
GOTO Tone
MOVLW 80h ;Put 80 into W
XORWF 06,1 ;XOR 80 with Port B. Toggle RB7
GOTO Tone

To get the micro out of the Tone routine is must have a "duration." The pitch
of the tone can also be changed:

Tone MOVLW 10h ;The duration of the tone or "beep"


MOVWF 1B
Tone1 MOVLW 80h ;The length of  HIGH and LOW - frequency of tone
MOVLW 1A
NOP

93
Tone2 DECFSZ 1A,1
GOTO Tone2
MOVLW 80h ;Put 80 into W
XORWF 06,1 ;XOR 80 with Port B. Toggle RB7
DECFSZ 1B,1
GOTO Tone1
RETURN

TRIS
The file that determines the in/out state of each line in a Port is the TRIS file. 
It is located in Bank1 of the microcontroller.  It has a value of 05 for Port A and 06
for Port B. 
 Port A only has RA0, RA1, RA2, RA3, and RA4.  Eg: MOVLW 0FFh will only affect
the 5 input lines of port A.  Bits 5, 6, and 7 of a value will not have any effect.
There are two ways to get to the TRIS file. It can be accessed directly by adding the
following two instructions directly into your program at any location:

MOVLW 01h ;Put 01 into W


TRIS 05 ;Make RA0 an input and all others output

The following instructions apply to the other lines:  Port B (06) can also be
operated on.

PortA: MOVLW 02h ;Put 0000 0010 into W


TRIS 05 ;Make RA1 an input and all others output

MOVLW 04h ;Put 0000 0100 into W


TRIS 05 ;Make RA2 an input and all others output

MOVLW 08h ;Put 0000 1000 into W


TRIS 05 ;Make RA3 an input and all others output

MOVLW 10h ;Put 0001 0000 into W


TRIS 05 ;Make RA4 an input and all others output

MOVLW 20h ;Put 0010 0000 into W


TRIS 05 ;Will make all output!

MOVLW 1Fh ;Put 0001 1111 into W


TRIS 05 ;Will make all input!

MOVLW 40h ;Put 0100 0000 into W


PortB: TRIS 06 ;Make RB6 an input and all others output
;(most PortB lines are used as outputs.)
 

The TRIS file can also be accessed by inserting BSF 03,5  BCF 03,5
instructions into your program.
The BSF 05,3 instruction takes you to Bank1 where the TRIS file is located.
When in Bank1, the TRIS file for PortA is file 05 and the TRIS file for PortB
is file 06. See SetUp for details of the instructions to be inserted between
BSF 03,5 and BCF 03,5.

94
 

BSF 03,5 ;Go to Bank 1


-------
-------
BCF 03,5 ;Go to Bank 0 - the program memory area.

Wait  see also Stop.


When testing a program, you may need to know if the microcontroller has advanced
to a certain part of the program. 
Insert the instruction: GOTO Wait.
Insert the following instructions. They should include an output to a LED etc so you
can prove the micro has entered the loop. 

Wait NOP ;Hold the micro in a loop


MOVLW 1Ch
MOVWF 06 ;Put "u" on 7-segment display
GOTO Wait

Watchdog Timer (WDT)
The PIC16F84 has an inbuilt timer that increments all the time. It has a normal time-
out period of 18mS (18,000 instruction-cycles). You cannot turn the timer on or off
via the program. It is turned on (or off) during the burning of the program by setting
WDT in the __config file. 
To turn the watchdog timer off:    & _WDT_OFF
To turn the watchdog timer on:    & _WDT_ON
If it is active (turned ON) the micro will go to 000 (reset) after 18,000uS.  
This action has a purpose. 
If a program is badly designed, it may "run off the end of the program" and start
executing "junk" commands. A glitch may cause the micro to go to an incorrect part
of a program to cause it to "Freeze." To prevent this from occurring, the WDT takes
the micro back to the beginning and starts the program over again. 
To prevent the WDT constantly resetting a program, the WDT must be constantly
reset via the instruction CLRWDT. This gives the programmer another 18,000
instructions before having to reset the WDT. 
To keep WDT constantly reset, CLRWDT must be placed inside delays. 
Normal programming (experimenting etc) is carried out with WDT OFF. 
If 18mS is insufficient a prescaler can be added to increase the WDT time by 2, 4, 8,
16, 32, 64 or 128. The maximum time is 18mS x 128 = 2.4sec  

XOR - XOR detects a MATCH! 


XOR is called exclusive OR. 
It means the only time the output of a gate is HIGH is when ONE (and ONLY one) of
the inputs is HIGH. 
When two numbers are XORed together, the result is "1" when one (and only one)
of the numbers is "1." [The OR function is called inclusive OR see IOR]. 

To find out if two numbers are the same, they are XORed together. Since each
binary digit will be the same (i.e. either a 0 or 1) the result will be 0000 0000.
The result will set the zero flag in the status (03) file and by testing bit 2 (the

95
Z flag) you can skip when SET.
You also have to decide where you want the result to be placed. If you don't
want the value of the file to be altered, the result should be put into W.

Example:  To see if file 1E holds the value 3C. (file 1E does contain the
value 3C)

MOVLW 3C  ;Put 3C in W


XORWF 1E,0 ;XOR 3C with file 1E and put the result into W.

The micro will XOR file 1E with the value 3C. 


We know file 1E contains the value 3C, so the operation is: 
W:  0011 1100 
1E: 0011 1100 
      0000 0000  - this answer will be put into W

In this example, 3C is put into file 1E and the XOR operation is carried out:

MOVLW 3C ;Put 3C in W
MOVWF 1E :Put 3C into file 1E
XORLW 3C  ;XOR 3C with file 1E and put the result into W.
BTFSS 03,2  ;Test the Zero flag
GOTO clear
GOTO SET

The zero flag will be set. (The zero flag is SET to show the answer is zero) i.e: a
MATCH! and the program will go to the line GOTO SET. 

Zero Flag
The zero flag is found in the STATUS register (file 03).  It is bit 2.  When the result of
an operations is zero, the zero flag is SET. In other words it is  = 1.  

Zero a file 
A file can be made zero in two ways. To zero a file is the same as clear a file.  
The instruction CLRF 1A makes the contents zero. 

CLRF 1A ;Make file 1A zero. 

You can load 00 into W and move W to a file:

MOVLW 00 ;Put 00 into W


MOVWF 1A ;Make file 1A zero.

Zero in a file (test for) 

96
To see if a file is zero, move it in and out of itself. The Z flag will be
affected. If it is SET, the file contains 00h.

MOVF 1A,1 ;Move 1A in and out of 1A


BTFSS 03,2 ;Test the zero flag
___________ ;Micro goes here if 1A is NOT zero
___________ ;Micro goes here if 1A is zero.

Copy & Save Routines

Lib.asm
=======================================================
====
TALKING ELECTRONICS Interactive website

http://www.talkingelectronics.com/
=======================================================
====
ROUTINES for "Copy and Pasting"

by Colin Mitchell
[email protected]

=======================================================
====

The following are the ROUTINES for "Copy and Pasting" into
your program - commonly called your ".asm file."
They are in alphabetical order, so everything is easy to find
- and easy to use.
Simply copy and paste them into your program: Hold the
left mouse button down as you pass the mouse over the instructions.
Then click the right mouse button and a box will appear.
Select "Copy." Go to your program - in an another NotePad
or WordPad - and "Paste" the instructions. All the instructions
should "line-up" into three columns.

If you use a set of instructions as a complete routine,


it is called a sub-routine.
Alternatively they can be added to another routine, such as "Main."

Make sure you understand what to do before using this library.


All these instructions are fully explained in "Library of Routines."

97
The instructions for your program are arranged in three columns.

The first column contains the "labels." They identify the first
instruction for a sub-routine.

The second column contains the "instruction" - called the


mnemonic. The "half-computer" "half-English" instruction that
both computer and micro understands.

The third column contains the "comments." It must have a ";" before
each line so that they are not assembled - so they don't
appear in the final .hex file!

Note: All the instructions in this library will "run" when placed in
a program. But sometimes, something goes wrong. If an instruction
has hidden "formatting," the assembler may create the wrong code.
To see if an instruction has hidden formatting, simply hold down
the left button on the mouse and drag across the instruction.
The background will go black and will not extend past the actual word.

Try the following: DECFSZ 1A,1

This instruction has hidden formatting: DECFSZ 1A,1

Simply remove any hidden formatting by holding the mouse on the


unwanted spaces and use the back-space arrow to remove the spaces
(or re-type the complete instruction) and the problem will be fixed.
(It does not matter if "comments" have extra spaces. "Comments" are
not assembled.)

Start by copying TEMPLATE. Delete the unwanted instructions and add


the instructions you want. Make sure the label is correct.

-----------------------------------------------------
ADD A VALUE TO A FILE
-----------------------------------------------------
A file contains a known value. To add a value to the file use:

Add MOVLW 0CCh ;Put CCh into W


ADDWF 0Eh ;CC will be added to the contents of file "E."

If the file overflows, the Carry/Borrow bit in the Status file


(file 03,0) will be SET.

Add MOVLW 0CCh ;Put CCh into W


ADDWF 0Eh ;CC will be added to the contents of file "E."
BTFSS 03,0 ;Test the carry bit in the Status file
GOTO AAA ;Micro will go to AAA if no overflow

98
GOTO BBB ;Micro will go to BBB if overflow occurs

-----------------------------------------------------
BEEP - TONE - this is a constant tone
-----------------------------------------------------

To use RB0 as the output: MOVLW 01h (see line 8 in subroutine below)
To use RB1 as the output: MOVLW 02h
To use RB2 as the output: MOVLW 04h
To use RB3 as the output: MOVLW 08h
To use RB4 as the output: MOVLW 10h
To use RB5 as the output: MOVLW 20h
To use RB6 as the output: MOVLW 40h

Tone MOVLW 40h ;The duration of the tone or "beep"


MOVWF 1B
Tone1 MOVLW A0h ;The length of HIGH and LOW - frequency of tone
MOVLW 1A
Tone2 NOP
DECFSZ 1A,1
GOTO Tone2
MOVLW 80h ;Put 80 into W
XORWF 06,1 ;XOR 80 with Port B. Toggle RB7
DECFSZ 1B,1
GOTO Tone1
RETURN

-----------------------------------------------------
BEEP - BEEP - BEEP - repeat
-----------------------------------------------------
This beep routine is suitable for debugging a program. The
instruction GOTO Beep1 is inserted in a program to see how far the
micro has advanced through the instructions.
Beep1 produces an endless beep . . . beep . . . beep . . .

In the sub-routine you are trying to debug, put the instruction:

GOTO Beep1

At the beginning of memory, after Tables, put the following:

Beep1 CALL Beep


CALL BeepDel
GOTO Beep1

99
Beep MOVLW 40h ;The duration of the beep
MOVWF 1B
Beep1 MOVLW A0h ;The length of HIGH and LOW - frequency of beep
MOVLW 1A
Beep2 NOP
DECFSZ 1A,1
GOTO Beep2
MOVLW 80h ;Put 80 into W
XORWF 06,1 ;XOR 80 with Port B. Toggle RB7
DECFSZ 1B,1
GOTO Beep1
RETURN

BeepDel DECFSZ 1A,1


GOTO BeepDel
DECFSZ 1B,1
GOTO BeepDel
RETURN

-----------------------------------------------------
BUTTON - SWITCH - PUSH BUTTON
-----------------------------------------------------

In this routine a push button is connected to RA0.


When it is pushed, a HIGH is delivered to RA0.
To make RA1 a button-line, the second instruction in
SetUp is: MOVLW 02. To make RA2 an input: MOVLW 04

The button-file must be cleared in SetUp.


There are two flags. Bit0 in file 1F is the Debounce Flag
and Bit1 in file 1F is the Button Pressed flag. 
The microprocessor executes Main and CALLs Sw.
If Sw detects a key-press, two flags are SET.
The first is the Button Pressed flag
and the second is the Debounce flag.
The micro returns to Main and tests the Button Pressed
flag to see if it is SET.
If is is SET, the micro goes to a sub-routine
such as CALL Increment, where a value can be incremented.
The Button Pressed flag is then cleared and the micro CALLs Sw.
If the switch is still pressed, the micro will return.
The program is looking for the button to be released.
When the button is released, the Sw sub-routine is ready
to detect another button-push.

SetUp BSF 03,5 ;Go to Bank 1

100
MOVLW 01 ;Put 01 into W to
MOVWF 05 ; make RA0 input
BCF 03,5 ;Go to Bank 0
CLRF 1F ;Clear the button-press file
GOTO Main

Sw1 BTFSS 05,0 ;Test the button. Button is "Active HIGH"


GOTO Sw2 ;Button not pressed
BTFSC 1F,0 ;Button pressed first time? Test debounce flag
RETURN ;Button already pressed. Return to Main
Sw1A DECFSZ 1A,1;Create short delay
GOTO Sw1A ;Look again
BTFSS 05,0 ;Is switch still pressed?
GOTO Sw1B ;It was only noise
BSF 1F,1 ;Button Pressed. Set button-pressed flag
BSF 1F,0 ;Set debounce flag
RETURN ;Return to Main
Sw1B BCF 1F,0 ;Clear debounce flag
RETURN ;Return to Main

Main CALL Sw
BTFSC 1F,1 ;Test button-press flag to see if button was pressed
GOTO Main1 ;Button pressed
Display the ;Button not pressed - carry out a sub-routine to
values on a ; display values on a display etc.
display etc.
GOTO Main
Main1 CALL Increment ;Increment the display. (you provide the
routine)
BCF 1F,1 ;Clear the button-press flag
GOTO Main

To connect two buttons to a micro.


The second instruction in SetUp must be the addition of the hex values
of the input lines
E.g: RA1 and RA2 = 0000 0010 + 0000 0100 = 0000 0110 = 06h
RA3 and RA5 = 0000 1000 + 0010 0000 = 0010 1000 = 28h

SetUp BSF 03,5 ;Go to Bank 1


MOVLW 03 ;Put 03 into W to
MOVWF 05 ; make RA0 and RA1 input
BCF 03,5 ;Go to Bank 0
CLRF 1F ;Clear the button-press file
GOTO Main

Sw1 BTFSS 05,0 ;Test the first button. Button1 is "Active HIGH"
GOTO Sw2 ;Button not pressed

101
BTFSC 1F,0 ;Button pressed first time? Test debounce flag
RETURN ;Button already pressed. Return to Main
Sw1A DECFSZ 1A,1;Create short delay
GOTO Sw1A ;Look again
BTFSS 05,0 ;Is switch still pressed?
GOTO Sw1B ;It was only noise
BSF 1F,1 ;Button Pressed. Set button-pressed flag
BSF 1F,0 ;Set debounce flag
RETURN ;Return to Main
Sw1B BCF 1F,0 ;Clear debounce flag
RETURN ;Return to Main

Sw2 BTFSS 05,0 ;Test the second button. Button2 is "Active HIGH"
GOTO Sw2 ;Button not pressed
BTFSC 1F,2 ;Button pressed first time? Test debounce flag
RETURN ;Button already pressed. Return to Main
Sw2A DECFSZ 1A,1;Create short delay
GOTO Sw2A ;Look again
BTFSS 05,0 ;Is switch still pressed?
GOTO Sw2B ;It was only noise
BSF 1F,3 ;Button Pressed. Set button-pressed flag
BSF 1F,2 ;Set debounce flag
RETURN ;Return to Main
Sw2B BCF 1F,2 ;Clear debounce flag
RETURN ;Return to Main

Main CALL Sw1


BTFSC 1F,1 ;Test button-press flag to see if button was pressed
GOTO Main1 ;Button pressed
Display the ;Button not pressed - carry out a sub-routine to
values on a ; display values on a display etc.
display etc.
CALL Sw2
BTFSC 1F,3 ;Test button-press flag to see if button was pressed
GOTO Main2 ;Button pressed
GOTO Main
Main1 CALL Increment ;Increment the display. (you provide the
routine)
BCF 1F,1 ;Clear the button-press flag
GOTO Main
Main2 CALL Decrement ;Decrement the display. (you provide the
routine)
BCF 1F,3 ;Clear the button-press flag
GOTO Main

102
-----------------------------------------------------
CALLS - a list of suitable Calls:
-----------------------------------------------------
Any names can be used. Keep the length to less than 8 letters.

CALL Alarm
CALL Beep
CALL Button
CALL Count
CALL Dec
CALL Delay
CALL Display
CALL Find
CALL HeeHaw
CALL Inc
CALL Look
CALL Loop
CALL Main
CALL Send
CALL Show
CALL Siren
CALL Sound
CALL Sw
CALL Switch
CALL Table
CALL Test
CALL Toggle
CALL Tone

-----------------------------------------------------
CALL A TABLE
-----------------------------------------------------

Load a value into W and CALL Table1. The micro will look down the
table. If the value you have loaded into W is 00, the first value
in the table will be fetched. If the value is 01, the second value
will be fetched.
The micro adds the value in W to the Program Counter and this
causes the micro to jump down the table. The PC naturally increments
to the next instruction and that's why 3Fh is selected if the loaded
value is 00.

Table1 ADDWF 02h,1 ;Add W to the Program Counter to create a


jump.
RETLW 3Fh ;0    format= gfedcba
RETLW 06h ;1
RETLW 5Bh ;2

103
RETLW 4Fh ;3
RETLW 66h ;4
RETLW 6Dh ;5
RETLW 7Dh ;6
RETLW 07h ;7
RETLW 7Fh ;8
RETLW 6Fh ;9

Main - - - - -
MOVLW 00h ;load a value into W. 00h will pick up 3Fh from table
CALL Table1 ;The micro will return with 3Fh in W
MOVWF 06 ;Move 3Fh to output Port B (file 06)
-----
-----

-----------------------------------------------------
DECREMENT A FILE
-----------------------------------------------------

DECF 1A,1 ;Puts the new value into the file

-----------------------------------------------------
DECREMENT A FILE and SKIP WHEN IT IS ZERO
-----------------------------------------------------

DECFSZ 1A,1;Puts the new value into the file


Not zero ;Goes here if file is not zero
zero! ;Goes here if file is zero!

-----------------------------------------------------
DELAYS
-----------------------------------------------------

This delay creates FFh loops. Each loop takes 4uS


Total time: 256 x 4 = 1024uS = say 1mS

Del NOP
DECFSZ 1A,1;Decrement file 1A
GOTO Del ;Loop until file 1A is zero
RETURN

This delay creates 80h loops. Each loop takes 4uS


Total time: 128 x 4 = 512uS

Del MOVLW 80h ;Put 80h into W

104
MOVWF 1A ;Copy 80h into file 1A
DelA NOP
DECFSZ 1A,1;Decrement file 1A
GOTO DelA ;Loop until file 1A is zero
RETURN

NESTED DELAY
This delay creates FFh loops (determined by file 1B).
Each loop takes 4uS and there are 256 inner loops = 1024uS = 1mS
This inner loop is executed 256 times via file 1B.
Total time = 260mS

Del NOP
DECFSZ 1A,1;Decrement file 1A
GOTO Del ;Loop until file 1A is zero
DECFSZ 1B,1 ;Decrement file 1B
GOTO Del ;Loop until file 1B is zero
RETURN

For a delay between 1mS and 260mS, you will need to pre-load file 1B:

Del MOVLW 7Dh


MOVLW 1B
Del1 NOP
DECFSZ 1A,1;Decrement file 1A
GOTO Del1 ;Loop until file 1A is zero
DECFSZ 1B,1 ;Decrement file 1B
GOTO Del1 ;Loop until file 1B is zero
RETURN

-----------------------------------------------------
EEPROM ROUTINES
-----------------------------------------------------

To load EEPROM:

ORG 2100h  
DE 84h, 16h, 23h, 80h, 0CAh, 32h, 7Bh, 0A2h 
DE 34h, 53h, 25h, 02h, 0FFh, 20h, 03h, 04h 

The sub-routine to read a value in the EEPROM is shown below.


It reads EEPROM data at location specified in EEADR and
returns the value in W

105
EERead BSF Status, RP0 ;Go to Bank 1
BSF EECON1, RD ;Set the RD bit  
BCF Status, RP0 ;Back to bank 0
MOVF 08, W ;EE Data is file 08.  Put into W
RETURN

The sub-routine to write to EEPROM is shown below.     

Delay1 MOVLW 13h ;Create a 20mS delay


MOVWF 1B ;20 loops
Delay1a NOP
DECFSZ 1A,1;4uS x 256 loops=approx 1mS
GOTO Delay1a
DECFSZ 1B
GOTO Delay1a
RETLW 00

EEWrite MOVWF 08 ;W to EEData


BSF 03,5 ;Switch to bank 1
BCF 0B,7 ;Disable interrupts
BSF 08,2 ;Write Enable bit set
MOVLW 55h ;Toggle EEPROM Control 
MOVWF 09 ;    Register bits
MOVLW 0AAh ;Toggle EEPROM Control
MOVWF 09 ;    Register bits
BSF 08,1 ;Begin write sequence
CALL Delay1 ;Call Delay1
BCF 08,2 ;Disable any further writes
BSF 0B,7 ;Enable Interrupts
BCF 03,5 ;Back to data bank 0
RETURN

-----------------------------------------------------
GOTO
-----------------------------------------------------
To make the micro go to another part of your program, use the
GOTO instruction. Simply write the word "GOTO." Following
GOTO, we place a "label" The label may be "Sw1" or "Count" or "Test."
"Sw1" or "Count" or "Test." will appear in the first column
of your program. The instruction "GOTO Test" will take the micro
to the line containing the label: Test.
The micro will not return to the instruction following GOTO Test,
unless you have a label at the line such as "Togu1" and include

106
an instruction GOTO Togu1 in your program.
If you GOTO a sub-routine, the last instruction in the
sub-routine cannot be RETURN as the micro does not have a return
address in its memory - on the STACK.
The only time a return address is placed on the stack is when a CALL
is executed.

GOTO Alarm
GOTO Beep
GOTO Button
GOTO Count
GOTO Dec
GOTO Delay
GOTO Display
GOTO Find
GOTO HeeHaw

At the end of the sub-routine will be a GOTO Main or GOTO another


sub-routine. It does not have to be the last instruction in a
sub-routine but it is the only exit instruction you can use.
You cannot use "RETURN."

-----------------------------------------------------
HEX VALUES
-----------------------------------------------------
All the files in a micro have 8 bits.
All the input/output ports have 8 lines.
The lowest bit or line is shown as a "1" in the folling value:

0000 0001

The lowest bit is called Bit0


The lowest line is called RA0 or RB0 or GP0

The next line (in/out line) or "bit" is called RA1, RB1 or GP1:

0000 0010

The lowest line has a value of zero when not active and ONE when active.
The next has a vaue of TWO when active.
The next has a value of FOUR when active.
The next has a value of EIGHT when active.

The 4 in/out lines have the following 16 possibilities:

0000
0001
0010

107
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111

They are given the following values:

0000 = 0
0001 = 1
0010 = 2
0011 = 3
0100 = 4
0101 = 5
0110 = 6
0111 = 7
1000 = 8
1001 = 9
1010 = A
1011 = B
1100 = C
1101 = D
1110 = E
1111 = F

The four HIGH lines have the same format:

0000 0000 = 00
0001 0000 = 10
0010 0000 = 20
0011 0000 = 30
0100 0000 = 40
0101 0000 = 50
0110 0000 = 60
0111 0000 = 70
1000 0000 = 80
1001 0000 = 90
1010 0000 = A0
1011 0000 = B0
1100 0000 = C0

108
1101 0000 = D0
1110 0000 = E0
1111 0000 = F0

The four HIGH and LOW lines produce 256 combinations.


Here are some:

0011 0101 = 35
1011 0000 = B0
1110 1001 = E9
1011 0000 = B0
0110 1110 = 6E

0101 0000 = 50
1001 1011 = 9B
0110 1011 = 6B

The value to make RA2 and RA5 input:

0010 0100 = 24

-----------------------------------------------------
INCREMENT A FILE
-----------------------------------------------------

INCF 1A,1 ;Puts the new value into the file

-----------------------------------------------------
INPUT
-----------------------------------------------------
To make a line (or lines), an INPUT, it must be given the
value "1." This can be done anywhere in the program
but it is best to put the instruction in SetUp.
This makes it easy to locate when trouble-shooting.
The instructions between BSF and BCF in the routine below are
operating on a register in bank 1 and this is the in/out
control register for PortA. It is NOT PortA. It is the
register that determines the IN or OUT condition of
each line in PortA and is called the TRIS register.

SetUp BSF 03,5 ;Go to Bank 1


MOVLW 0F ;Put 0000 1111 into W to
MOVWF 05 ; make RA0, RA1, RA2, and RA3 input
BCF 03,5 ;Go to Bank 0
GOTO Main

109
-----------------------------------------------------
INPUT A VALUE
-----------------------------------------------------
The input lines for a 12C508A are: GP0, GP1, GP2, GP3, GP4 and GP5.
GP3 is input-only and this line is usually the chosen input.
The input lines for a PIC16F84A are:
RA0,RA1,RA2,RA3,RA4,RA5,RA6,RA7.
RB0,RB1,RB2,RB3,RB4,RB5,RB6,RB7.

To input a value (A HIGH or LOW), make sure the line is an


input. This is done in SetUp:

SetUp BSF 03,5 ;Go to Bank 1


MOVLW 01 ;Put 0000 0001 into W to
MOVWF 05 ; make RA0 input
BCF 03,5 ;Go to Bank 0
GOTO Main

In Main, test the input line:

Main BTFSS 05,0


GOTO - - -
-----
-----

-----------------------------------------------------
INVERT
-----------------------------------------------------
An output line can be made an input (or vise versa) at any time during
the running of a program. The following instructions work for both a
PIC12C508A and a PIC16F84.
The GPIO (General Purpose In/Out) lines on a PIC12C508A are GP0, GP1,
GP2, GP3, GP4 and GP5, (GP3 as an input-only line). These lines
correspond to RB0 to RB5 on a PIC16F84A.

Suppose GP0 (RB0) is an output. To make GP0 (RB0) an input, use the
following:
Note: file 06 in bank1 is the TRIS file. It determines the input or
output nature of each line in Port6. The lowest bit in the TRIS file
is SET to make line RB0 an input. The line is then looked-at to see if
it is HIGH and then the line is turned into an output.

-----
-----
BSF 03,5 ;Go to Bank 1
BSF 06,0 ;Make the lowest bit in the TRIS file an input
BCF 03,5 ;Go to Bank 0

110
BTFSC 06,0 ;Look at input line GP0 (RB0)
GOTO xxxx ;GOTO xxxx if line RB0 is HIGH
BSF 03,5 ;Go to Bank 1
BCF 06,0 ;Make the lowest bit in the TRIS file an output
BCF 03,5 ;Go to Bank 0
-----
-----

-----------------------------------------------------
LAYOUT OF A PROGRAM
-----------------------------------------------------
Use the following when layingout your program:

SetUp

Table1
Table2

LabelA - put all labels in alphabetical order so they can be found


quickly.

LabelB

LabelC

LabelD

Main

-----------------------------------------------------
LOOK for a Table-value
-----------------------------------------------------

See Table-value

-----------------------------------------------------
LOOP
-----------------------------------------------------
When writing a program, you can use a loop to create a STOP function.

Loop NOP
GOTO Loop

Inside the loop you can put a tone routine so you can see if the

111
micro has reached the location.

Loop MOVLW A0h ;The length of HIGH and LOW - frequency of tone
MOVLW 1A
Tone NOP
DECFSZ 1A,1
GOTO Tone
MOVLW 80h ;Put 80 into W
XORWF 06,1 ;XOR 80 with Port B. Toggle RB7
GOTO Loop

-----------------------------------------------------
MAIN
-----------------------------------------------------
Main is the last routine in your program. It is a loop routine
and has a number of CALL and/or GOTO instructions: (If you GOTO
a sub-routine, the sub-routine must have a GOTO as the exit).

Main - - - - -
-----
-----
CALL Delay
-----
-----
-----
GOTO Main

-----------------------------------------------------
OUTPUT
-----------------------------------------------------
To make a line (or lines), an OUTPUT, it must be given the
value "0." This can be done anywhere in the program
but it is best to put the instruction in SetUp.
This makes it easy to locate when trouble-shooting.
The instructions between BSF and BCF in the routine below are
operating on a register in bank 1 and this is the in/out
control register for PortB. It is NOT PortB. It is the
register that determines the IN or OUT condition of
each line in PortB and is called the TRIS register.

SetUp BSF 03,5 ;Go to Bank 1


MOVLW 00 ;Put 0000 0000 into W to
MOVWF 06 ; make all PortB lines output
BCF 03,5 ;Go to Bank 0
GOTO Main

112
In Main, output a HIGH on PortB (file 06):

Main - - - - -
MOVLW 0FFh ;
MOVWF 06 ;Output a HIGH to the 8 lines of PortB
-----
-----

-----------------------------------------------------
OVERFLOW
-----------------------------------------------------
If a value is added to a file, overflow may occur.
To see if overflow occurs, test the Carry/Borrow bit in the Status file
(file 03,0). It will be SET if overflow occurs.

Add MOVLW 0CCh ;Put CCh into W


ADDWF 0Eh ;CC will be added to the contents of file "E."
BTFSS 03,0 ;Test the carry bit in the Status file
GOTO AAA ;Micro will go to AAA if no overflow
GOTO BBB ;Micro will go to BBB if overflow occurs

-----------------------------------------------------
RETURN
-----------------------------------------------------
The PIC12C508A does not have a RETURN instruction.
If you use RETURN in your program, the assembler will replace
it with RETLW 00 when creating a .hex file for a PIC12C508A.

-----------------------------------------------------
REVERSE
-----------------------------------------------------
An output line can be made an input (or vise versa) at any time during
the running of a program. The following instructions work for both a
PIC12C508A and a PIC16F84.
The GPIO (General Purpose In/Out) lines on a PIC12C508A are GP0, GP1,
GP2, GP3, GP4 and GP5, (GP3 as an input-only line). These lines
correspond to RB0 to RB5 on a PIC16F84A.

Suppose GP0 (RB0) is an output. To make GP0 (RB0) an input, use the
following:
Note: file 06 in bank1 is the TRIS file. It determines the input or
output nature of each line in Port6. The lowest bit in the TRIS file
is SET to make line RB0 an input. The line is then looked-at to see if
it is HIGH and then the line is turned into an output.

113
-----
-----
BSF 03,5 ;Go to Bank 1
BSF 06,0 ;Make the lowest bit in the TRIS file an input
BCF 03,5 ;Go to Bank 0
BTFSC 06,0 ;Look at input line GP0 (RB0)
GOTO xxxx ;GOTO xxxx if line RB0 is HIGH
BSF 03,5 ;Go to Bank 1
BCF 06,0 ;Make the lowest bit in the TRIS file an output
BCF 03,5 ;Go to Bank 0
-----
-----

-----------------------------------------------------
SetUp
-----------------------------------------------------
This is the first sub-routine in your program. It sets up the
port (or ports) in the microcontroller. A port has up to 8 lines
and these can be inputs or outputs. (GP3 for a PIC12C508A can
be input-only).
The input lines for a 12C508A are: GP0, GP1, GP2, GP3, GP4 and GP5.
GP3 is input-only and this line is usually the chosen input.
The output lines for a 12C508A are: GP0, GP1, GP2, GP4 and GP5.
An input line can be changed to an output at any time during
the running of a program.
An output line can be changed to an input at any time during
the running of a program.
The input/output lines of a PIC12C508A are in file 06.
To make GP0 an input, place the following instructions in SetUp:

SetUp BSF 03,5 ;Go to Bank 1


MOVLW 01 ;Put 0000 0001 into W to
MOVWF 06 ; make GP0 input
BCF 03,5 ;Go to Bank 0
GOTO Main

To make GP0 an output, place the following instructions in SetUp:

SetUp BSF 03,5 ;Go to Bank 1


MOVLW 00 ;Put 0000 0000 into W to
MOVWF 06 ; make GP0 input
BCF 03,5 ;Go to Bank 0
GOTO Main

To make any GP line an input, place "1" in the corresponding


position for the value loaded into W:

SetUp BSF 03,5 ;Go to Bank 1

114
MOVLW 08 ;Put 0000 1000 into W to
MOVWF 06 ; make GP3 input
BCF 03,5 ;Go to Bank 0
GOTO Main

To create two input lines:

SetUp BSF 03,5 ;Go to Bank 1


MOVLW 12 ;Put 0001 0010 into W to
MOVWF 06 ; make GP1 and GP4 input
BCF 03,5 ;Go to Bank 0
GOTO Main

The input lines for a PIC16F84A are:


RA0,RA1,RA2,RA3,RA4,RA5,RA6,RA7.
RB0,RB1,RB2,RB3,RB4,RB5,RB6,RB7.

SetUp BSF 03,5 ;Go to Bank 1


MOVLW 03 ;Put 03 into W to
MOVWF 05 ; make RA0 and RA1 input
BCF 03,5 ;Go to Bank 0
GOTO Main

-----------------------------------------------------
STATUS FILE
-----------------------------------------------------
The STATUS file is file 03.
Bit0 is the Carry/Borrow
Bit1 is the Digit Carry/Borrow
Bit2 is the Zero bit
Bit3 is the Power Down bit
Bit4 is the Time-out bit
When bit5 is SET Bank1 is selected
When bit5 is CLEAR Bank0 is selected

-----------------------------------------------------
STOP
-----------------------------------------------------
The micro does not have a STOP or HALT instruction.
When writing a program, you can use a loop to create a STOP function.

Loop NOP
GOTO Loop

Inside the loop you can put a tone routine so you can see if the
micro has reached the location.

115
Loop MOVLW A0h ;The length of HIGH and LOW - frequency of tone
MOVLW 1A
Tone NOP
DECFSZ 1A,1
GOTO Tone
MOVLW 80h ;Put 80 into W
XORWF 06,1 ;XOR 80 with Port B. Toggle RB7
GOTO Loop

-----------------------------------------------------
TABLE - see also CALL A TABLE
-----------------------------------------------------

Load a value into W and CALL Table1. The micro will look down the
table. If the value is 00, the first value in the table will be
fetched. If the value is 01, the second value will be fetched.
The micro adds the loaded-value into the Program Counter and this
causes the micro to jump down the table. The PC naturally increments
and that's why 3Fh is selected if the loaded value is 00.
Any values with a letter as the first part of the hex value must
begin with a "0" E.g: FFh = 0FFh CDh = 0CDh
The end of a table can be identified by using 0FFh (providing FFh is
not a required table value). In Main, look for 0FFh as a table value.

Table1 ADDWF 02h,1 ;Add W to the Program Counter to create a


jump.
RETLW 3Fh ;0    format= gfedcba
RETLW 06h ;1
RETLW 5Bh ;2
RETLW 4Fh ;3
RETLW 66h ;4
RETLW 6Dh ;5
RETLW 7Dh ;6
RETLW 07h ;7
RETLW 7Fh ;8
RETLW 6Fh ;9
RETLW 0FFh

Main - - - - -
MOVLW 00h ;load a value into W. 00h will pick up 3Fh from table
CALL Table1 ;The micro will return with 3Fh in W
MOVWF 06 ;Move 3Fh to output Port B (file 06)
-----
-----

116
-----------------------------------------------------
Table-value
-----------------------------------------------------

To "Look for" or "fetch" a table value, you need 2 instructions.


To fetch the first table value, load W with 00.
To fetch the second table value, load W with 01 etc.
The second instruction is CALL Table1
The micro will return with the table-value in W:

Table1 ADDWF 02h,1 ;Add W to the Program Counter to create a


jump.
RETLW 3Fh ;0    format= gfedcba
RETLW 06h ;1
RETLW 5Bh ;2
RETLW 4Fh ;3
RETLW 66h ;4
RETLW 6Dh ;5
RETLW 7Dh ;6

Main - - - - -
-----
MOVLW 04
CALL Table1
-----
-----

The micro will return with 66h in W

-----------------------------------------------------
TEMPLATE
-----------------------------------------------------
Use this template as a start to writing your program.
This is not a fully-functional program.
It is a set of example-instructions.
Delete the unwanted instructions.

;Expt1.asm
;Project: Turning on a -----
;This program can be assembled for a PIC12C508A or PIC16F84

ORG 0 ;This is the start of memory for the program


SetUp BSF 03,5 ;Go to Bank 1
MOVLW 01 ;Load W with 0000 0001
MOVWF 05 ;Make RA0 input
MOVLW 01 ;Load W with 0000 0001
MOVWF 06 ;Make RB0 or GP0 input

117
BCF 03,5 ;Go to Bank 0 - the program memory area
GOTO Main

Delay NOP ;Create approx 250mS delay


DECFSZ 1A,1
GOTO Delay
DECFSZ 1B,1
GOTO Delay
RETURN

Look CLRF 0C ;Count-down file


-----
CALL Delay ;250mS delay
BSF 03,5 ;Go to Bank 1
MOVLW 04 ;Load W with 0000 0100
MOVWF 05 ;Make RA2 input & RA3 output
BCF 03,5 ;Go to Bank 0 - the program memory area.
RETURN

Main BTFSS 05,0 ;Test the input line on port A


GOTO Main2 ;Button not pressed
BSF 06,0 ;Button pressed. Turn on LED
CALL Delay
-----
CALL Look
Main2 BCF 06,0 ;Button not pressed. Turn off LED
GOTO Main ;Loop Main

END ;Tells assembler end of program

-----------------------------------------------------
TOGGLE
-----------------------------------------------------
Toggle changes the state of an output. You do not have to know
the state of the output before the operation. The output changes
from HIGH to LOW or LOW to HIGH. You do not know the output after
the operation. This operation is not suitable if you want to
leave an output low when not in use so that the output current
is low.

To toggle RB0 use: MOVLW 01h (see line 8 in subroutine below)


To toggle RB1 use: MOVLW 02h
To toggle RB2 use: MOVLW 04h
To toggle RB3 use: MOVLW 08h
To toggle RB4 use: MOVLW 10h
To toggle RB5 use: MOVLW 20h
To toggle RB6 use: MOVLW 40h

118
Toggle MOVLW 80h ;Put 80 into W
XORWF 06,1 ;XOR 80 with Port B. Toggle RB7

-----------------------------------------------------
TRIS
-----------------------------------------------------
"Tris" is the file (register) that determines if each bit in a
Port is input or output.
See Library of Routines for more details.

TIMING AND DELAYS


P11
PIC LAB-1 is capable of performing all types of timing and Delay operations. 
Don't let the single external output on the board put you off. You can design
programs for one or more outputs and use the 8 LEDs on the board to indicate the
state of each output. A new PC board can then be made with relays and driver
transistors. 
You should also leave the LEDs on the board to show the state of each output at
any particular instant. This is a very clever inclusion as it helps with diagnosis and
keeps track of the state of each output.
Timing can start at microseconds and extend to hours, days or months. 
You can have number of random on-off cycles within a program and even include
over-riding inputs such as switches and sensors, to vary the timing cycles. 
This section covers a number of experiments, starting with a simple program and
advancing to  complex routines with a switch input and a liquid-level sensor (using
the "pot" input to detect water conductivity). 
Timing and Delays are the same thing. They all use a DELAY routine. A Delay
Routine is a "Do Nothing" routine. It consists of instructions that take time to execute
without anything appearing on a display, or anything else happening. 
Before executing a delay, an output can be "set-up" to display a number or value, or
a set of LEDs can be illuminated. The delay then allows the eye to view the display,
before removing it and displaying another value. 
The same thing can happen to produce a tone. The speaker or piezo is delivered a
HIGH and a delay routine is executed. The piezo is then delivered a LOW and a
delay routine is called. The action of delivering a HIGH then LOW then HIGH etc will
activate the piezo to produce a sound. 
The microcontroller we are using operates at one million instructions per second so
the only way to create a program requiring 200,000 instructions, for example, is to
create a loop. This is a set of instructions that are executed over and over. Each
time they are executed, a file is reduced in value. 
A file contains 256 and this will produce 256 loops. If each loop takes 4 micro-

119
seconds, we have a 1,000 microsecond delay. This is 1 millisecond. 
If this loop is called a number of times by another file, we are already starting to
build up a delay of significant duration. 
Delay routines can be designed with loops inside a loop and even three of four loops
can be inside other loops. These are called NESTED LOOPS and very soon we
have a delay routine that takes minutes, hours and even days to execute. 

EXACT VALUES
One of the challenges is to produce a delay routine that has an exact
execution value.  This is needed if you want to produce  accurate timing for a
clock etc. 
Since we are using an RC oscillator in the PIC LAB-1, the execution times
will not be exact, however it is very easy to increase or decrease their
duration to suit an application.  
For exact time intervals, a crystal is needed for the oscillator and this can be
the subject for a future experiment. 
Normally, a long delay is not executed by a micro as any push-buttons in the
program will not be detected during this time. The answer is to include a
button-press feature inside a short delay routine so that they remain
operative.   You will see this feature in Expt 20b.

The first experiment produces a beep every minute.  

                     ;Expt20.asm


                     ;Project: 1 min timer with beep
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all Port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 05 ;Blank the display
CLRF 06 ;Blank the display
GOTO Main

Delay MOVLW 0F1h ;Create 1 minute delay


MOVWF 1C
Delay1 NOP
DECFSZ 1A,1
GOTO Delay1
DECFSZ 1B,1
GOTO Delay1
DECFSZ 1C,1
GOTO Delay1
RETURN

Beep MOVLW 1Ah       ;Length of the Beep


MOVWF 12h
Beep1 MOVLW 40h        ;The HIGH/LOW time
MOVWF 13h
Beep2 DECFSZ 13h,1     ;Time for ON and OFF periods
GOTO Beep2 

120
MOVLW 80h        ;Toggle the Piezo line
XORWF 06,1
DECFSZ 14,1       ;256 loops of ON/OFF
GOTO Beep1
DECFSZ 12h,1
GOTO Beep1
BCF 06,7       ;Turn off piezo bit

RETURN

Main CALL Delay


CALL Beep ;Loop Main
GOTO Main
;Tells assembler end of program
END

The time can be altered by approx 0.25sec with each increment or decrement of the
value placed in file 1C. This file is the outer file of the nested loop.  Small increments
or decrements can be obtained by adjusting the length of the beep. 

TURNING A TIMER ON AND OFF


You can turn the beep on and off by the action of a push button and have the
display show "0" for off and "1" for on. 
This involves more programming and the following experiment shows this
feature:  

                     ;Expt20a.asm


                     ;Project: 5 sec timer with on/off
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;Start of memory 
SetUp BSF 03,5 ;Go to Bank 1
MOVLW 01 ;Load W with 01
MOVWF 05 ;Make RA0 input
CLRF 06 ;Make all Port B output
BCF 03,5 ;Go to Bank 0 
CLRF 05 ;Blank the display
CLRF 06 ;Blank the display
CLRF 1F ;Clear the button-press flag
GOTO Main

Delay MOVLW 010h ;Create 5 second delay


MOVWF 1C
Delay1 NOP
DECFSZ 1A,1
GOTO Delay1
BTFSS 05,0 ;Test the button line on port A
GOTO Not ;Button not pressed
BTFSC 1F,0 ;Button pressed first time?
GOTO Delay2 ;Button already pressed
MOVLW 02 ;First time button pressed
XORWF 1F,1 ;Toggle the on/off flag 
BSF 1F,0 ;Set button-press flag
BTFSS 1F,1

121
GOTO Off
MOVLW 06
MOVWF 06
GOTO Delay2
Off MOVLW 3Fh
MOVWF 06
GOTO Delay2
Not BCF 1F,0 ;Clear button-press flag
Delay2 DECFSZ 1B,1
GOTO Delay1
DECFSZ 1C,1
GOTO Delay1
RETURN

MOVLW 1Ah       ;Length of the Beep


Beep MOVWF 12h
MOVLW 40h        ;The HIGH/LOW time
Beep1 MOVWF 13h
DECFSZ 13h,1     ;Time for ON and OFF periods
Beep2 GOTO Beep2 
MOVLW 80h        ;Toggle the Piezo line
XORWF 06,1
DECFSZ 14,1       ;256 loops of ON/OFF
GOTO Beep1
DECFSZ 12h,1
GOTO Beep1
BCF 06,7       ;Turn off piezo bit

RETURN

CALL Delay ;Test on/off flag


Main BTFSS 1F,1
GOTO Main
CALL Beep ;Loop Main
GOTO Main
;Tells assembler end of program
END

You can increase the time, add two beeps, create a 10 second, 30 second, 10
second, 30 second timer or any number of effects. 

A LONG DELAY
A very long delay can be produced by using Expt20a and calling the 1
minute sub-routine a number of times. The push-button starts the timing and
the beep is constant at the end of the timing cycle.
(For demonstration purposes, the time is 2 x 5 seconds). The duration of the
beep routine has been shortened so that the start/stop action in Main works
instantly. 
For a time-length of 256 x 1 minute, load file 1C in Delay with 0C0h and
load file 0Ch in Main with 256.  

                     ;Expt20b.asm


                     ;Project: 10 sec timer with start/stop
List P = 16F84
#include <p16F84.inc>

122
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;Start of memory 
SetUp BSF 03,5 ;Go to Bank 1
MOVLW 01 ;Load W with 01
MOVWF 05 ;Make RA0 input
CLRF 06 ;Make all Port B output
BCF 03,5 ;Go to Bank 0 
CLRF 05 ;Blank the display
CLRF 06 ;Blank the display
CLRF 1F ;Clear the button-press flag
GOTO Main

Delay MOVLW 010h ;Use 0C0h for 1 minute delay


MOVWF 1C
Delay1 NOP
DECFSZ 1A,1
GOTO Delay1
BTFSS 05,0 ;Test the button line on port A
GOTO Not ;Button not pressed
BTFSC 1F,0 ;Button pressed first time?
GOTO Delay2 ;Button already pressed
MOVLW 02 ;First time button pressed
XORWF 1F,1 ;Toggle the on/off flag 
BSF 1F,0 ;Set button-press flag
BTFSS 1F,1
GOTO Off
MOVLW 06 ;Put "1" on display
MOVWF 06
GOTO Delay2
Off MOVLW 3Fh ;Put "0" on display
MOVWF 06
GOTO Delay2
Not BCF 1F,0 ;Clear button-press flag
Delay2 DECFSZ 1B,1
GOTO Delay1
DECFSZ 1C,1
GOTO Delay1
RETURN

MOVLW 02h       ;Length of the Beep


Beep MOVWF 12h
MOVLW 40h        ;The HIGH/LOW time
Beep1 MOVWF 13h
DECFSZ 13h,1     ;Time for ON and OFF periods
Beep2 GOTO Beep2 
MOVLW 80h        ;Toggle the Piezo line
XORWF 06,1
DECFSZ 14,1       ;256 loops of ON/OFF
GOTO Beep1
DECFSZ 12h,1
GOTO Beep1
BCF 06,7       ;Turn off piezo bit

RETURN
;Produce a 10 sec timer 
MOVLW 02
Main MOVWF 0C
CALL Delay

123
Main1 DECFSZ 0C,1
GOTO Main1 ;Test start/stop flag
BTFSS 1F,1
GOTO Main
CALL Beep ;Test the button line on port A
Main2 BTFSS 05,0   ;Keep beeping
GOTO Main2
GOTO Main
;Tells assembler end of program
END

TURNING ON 8 OUTPUTS
In this experiment we show how to turn on 8 outputs according to the following
chart:
The "ON" times have durations of "2," "4" and "10" seconds.

The program starts at time=0 and the relevant lines are taken HIGH. A 1-
minute timer is called and then the state of the 8 outputs is determined. If
only one line is altered, it can be "bit-set." This process is continued across
the chart. 
                     ;Expt20c.asm
                     ;Project: Outputting to 8 LEDs
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;This is the start of memory for the program.
SetUp BSF 03,5 ;Go to Bank 1
CLRF 06 ;Make all Port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.
CLRF 05 ;Blank the display
CLRF 06 ;Blank the display
GOTO Main

Delay MOVLW 10h ;Use 0F1h for 1 minute delay


MOVWF 1C
Delay1 NOP
DECFSZ 1A,1
GOTO Delay1
DECFSZ 1B,1
GOTO Delay1
DECFSZ 1C,1
GOTO Delay1
RETURN

124
Main MOVLW 60h ;Turn on: 0110 0000
MOVWF 06
CALL Delay
CALL Delay
BCF 06,7
CALL Delay
BSF 06,0
CALL Delay
CALL Delay
BCF 06,0
CALL Delay
CALL Delay
CALL Delay
BSF 06,2
CALL Delay
CALL Delay ;End of 10 seconds
MOVLW 1Ah ;Turn on: 0001 1010
MOVWF 06
CALL Delay
CALL Delay
BCF 06,3
CALL Delay
CALL Delay
MOVLW 03h ;Turn on: 0000 0011
MOVWF 06
CALL Delay
BSF 06,6
CALL Delay
CALL Delay
BSF 06,3
CALL Delay
BCF 06,0
CALL Delay
CALL Delay ;End of 20 seconds
MOVLW 94h ;Turn on: 1001 0100
MOVWF 06
CALL Delay
CALL Delay
BCF 06,4
CALL Delay
CALL Delay
CALL Delay
CALL Delay
CALL Delay
CALL Delay
CALL Delay
CALL Delay
BCF 06,2
BCF 06,7
GOTO Main

END

The display may not look very impressive with LEDs turning on and off, but if the
outputs were connected to solenoids controlling ink or drill-heads and the program
speeded up, quite impressive designs could be produced.  
There are many ways to create an output pattern and be able to change the

125
combinations with a user-friendly program. One idea is to have 8 buttons. These are
all pushed at the same time to create HIGHs. Another button increments the
minutes. 

4 TIMING PROGRAMS
Four programs can  be combined into a single application with the push button to
select the program. The program starts at "0" on the display (no routine operating) to
1, 2, 3, and 4 and finally to "0."
The 4 programs are as follows:
1 Beeps after 40 seconds then turns off
2 Beeps every 60 seconds
3 Beeps after 20 seconds then every 2 seconds
4 Beeps twice every 10 seconds

These could be incorporated into a commercial kitchen, for timing frying of


foods or in a production-line. 
It's the universal nature of a microcontroller design that we are covering - the
actual type of beep routine is only a concept. We have used low values for
counting in the demo experiment below to speed-up the evaluation process. 

                     ;Expt20d.asm


                     ;Project: 4 Timing Programs
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0 ;Start of memory 
SetUp BSF 03,5 ;Go to Bank 1
MOVLW 01 ;Load W with 01
MOVWF 05 ;Make RA0 input
CLRF 06 ;Make all Port B output
BCF 03,5 ;Go to Bank 0 
CLRF 05 ;Blank the display
CLRF 1E ;Clear the button-counter file
CLRF 1F ;Clear the button-press flag
GOTO Main

Delay MOVLW 04h ;Create 1 second delay


MOVWF 1C
Delay1 NOP
DECFSZ 1A,1
GOTO Delay1
BTFSS 05,0 ;Test the button line on port A
GOTO Not ;Button not pressed
BTFSC 1F,0 ;Button pressed first time?
GOTO Delay2 ;Button already pressed
INCF 1E,1 ;Increment the button-counter flag
BSF 1F,0 ;Set button-press flag
GOTO Delay2
Not BCF 1F,0 ;Clear button-press flag
Delay2 DECFSZ 1B,1
GOTO Delay1

126
DECFSZ 1C,1
GOTO Delay1
RETURN

MOVLW 08h       ;Length of the Beep


Beep MOVWF 12h
MOVLW 30h        ;The HIGH/LOW time
Beep1 MOVWF 13h
DECFSZ 13h,1     ;Time for ON and OFF periods
Beep2 GOTO Beep2 
MOVLW ;Toggle the Piezo line
080h       
XORWF 06,1 ;256 loops of ON/OFF
DECFSZ 14,1      
GOTO Beep1
DECFSZ 12h,1
GOTO Beep1 ;Turn off piezo bit
BCF 06,7      

RETURN
;Is the button-counter = 0?
Main MOVLW 00 ;Test the zero flag in STATUS
XORWF 1E,0 ;No
BTFSS 03,2 ;Yes
GOTO Main1 ;Put "0" on 7-segment display
MOVLW 3Fh
MOVWF 06 ;Loop for button-press = 0
CALL Delay
GOTO Main ;See if program 1 has been selected

Main1 MOVLW 01
XORWF 1E,0 ;No
BTFSS 03,2 ;Use 28h for 40 loops of 1 second delay
GOTO Main4 ;Loop counter for 1 second delay
MOVLW 02h
MOVWF 0C ;Put "1" on 7-segment display
MOVLW 06
MOVWF 06
Main2 CALL Delay
MOVLW 01
XORWF 1E,0
BTFSS 03,2
GOTO Main4
DECFSZ 0Ch,1
GOTO Main2
CALL Beep ;The delay routine will increment 1E
Main3 CALL Delay ;    and allow the program to progress to the 
MOVLW 01 ;    next section 
XORWF 1E,0
BTFSS 03,2 ;End of program 1
GOTO Main4
GOTO Main3

Main4 MOVLW 02
XORWF 1E,0
BTFSS 03,2 ;Use 3Ch for 60 loops of 1 second delay
GOTO Main6
MOVLW 02h

127
MOVWF 0C ;Put "2" on 7-segment display
MOVLW 5Bh
MOVWF 06
Main5 CALL Delay
MOVLW 02
XORWF 1E,0
BTFSS 03,2
GOTO Main6
DECFSZ 0Ch,1
GOTO Main5 ;End of program 2
CALL Beep
GOTO Main4

Main6 MOVLW 03
XORWF 1E,0
BTFSS 03,2 ;Use 14h for 20 loops of Delay
GOTO Main9
MOVLW 04h
MOVWF 0C ;Put "3" on 7-segment display
MOVLW 4Fh
MOVWF 06
Main7 CALL Delay
MOVLW 03
XORWF 1E,0
BTFSS 03,2
GOTO Main9
DECFSZ 0Ch,1
GOTO Main7
Main8 CALL Beep
CALL Delay
MOVLW 03
XORWF 1E,0
BTFSS 03,2
GOTO Main9 ;End of program 3
CALL Delay
GOTO Main8 ;Put FF into button-counter to 
;   make 00 on next increment!
Main9 MOVLW 0FFh ;10 loops of Delay
MOVWF 1E
MOVLW 0Ah
MOVWF 0C ;Put "4" on 7-segment display
MOVLW 66h
MOVWF 06
MainA CALL Delay
MOVLW 00
XORWF 1E,0
BTFSC 03,2
GOTO Main
DECFSZ 0Ch,1
GOTO MainA
CALL Beep
CALL Delay
MOVLW 00
XORWF 1E,0
BTFSC 03,2
GOTO Main ;End of program 4
CALL Beep
GOTO Main9

128
END

Most of the complexity of the program is due to the push button. It needs to be poled
all the time and when it is pushed, the program must advance to the next section. 
There are many ways to present a program such as this and the simplest is the
LINEAR APPROACH. This involves laying out the instructions with the minimum
GOTO's. You can read the instructions exactly as the micro executes them.
The program can be shorted considerably with clever coding but this will make it
more difficult for the beginner to understand. If you have plenty of program space,
you don't have to be concerned about compressing a program. 
It's only when you think you are going to run out of program-space that efficiency
has to be introduced. 
You have over 1,000 lines of program-space in the PIC16F84 and the next chip we
will be introducing has over 2,000 lines of space. 
It is the PIC16F628 and is effectively an upgrade of the PIC16F84. It has twice the
memory,  more than twice the speed of operation, an extra 3 in/out lines and is
approx half the price. It also has more features and a few more instructions. You will
see it in the PIC LAB-1 project. 
They are pin-for-pin upwardly compatible as everything on the '84 is also on the
'628. The extra features are included as "selectables" on the pins. 
For now, we have to master the '84. It's then very easy to upgrade. 

A DELAY WITH WATER DETECTION


The "pot" input on PIC LAB-1 detects resistance. It can also detect the presence of
water via two probes. Most water contains dissolved salts and this reduces its
resistance so that a reading can be obtained. 
For the purposes of this experiment we will connect a pot to the input. 

The program has the following features:


Push the button to start the program. The alarm sounds after 30 seconds (this can
be extended). If the pot is rotated to approx mid-value the alarm sounds. 
This is an alarm for filling a tank etc. If the tank does not fill in a prescribed time the
alarm sounds. As soon as the tank is full, the alarm sounds. 
There are many variations of this. It could be light-intensity, sound, temperature,
distance, counting, etc. It's the concept of combining two items or features at the
same time. 
To produce a program with the features outlined above, the starting point is to take a
program already produced (such as Expt20b) as it has the button-press and display
features already provided. The program is already half-complete! The only section to
add is the A-to-D (analogue-to-digital) "pot" section. Page 9 describes an

129
experiment that connects a pot to the PIC LAB-1. "Cut and Paste" the "Look"
sub-routine and use file 0D as the decrementing file. 
The SUBWF instruction in Main subtracts W from file file 0D and the Carry
(in file 03) will be SET if 0D is more than 80h. This is equivalent to approx
mid position of the pot. 
You will have to supply probes and start with a "test value" of say 10h and
gradually immerse the probes in water (slightly salty water) to see when the
circuit responds. 

                     ;Expt20e.asm


                     ;Project: Delay with water detection
List P = 16F84
#include <p16F84.inc>
__CONFIG 1Bh    ;_CP_OFF & _PWRTE_ON & _WDT_OFF & _RC_OSC
ORG 0  ;Start of memory 
SetUp SetUp BSF 03,5  ;Go to Bank 1
MOVLW 11h  ;Load W with 0001 0001
MOVWF 05  ;Make RA0, RA4 input
CLRF 06  ;Make all Port B output
BCF 03,5  ;Go to Bank 0 
CLRF 05  ;Blank the display
CLRF 06  ;Blank the display
CLRF 1F  ;Clear the button-press flag
GOTO Main

Beep MOVLW 0A0h  ;The HIGH/LOW time


MOVWF 13h
Beep1 DECFSZ 13h,1  ;Time for ON and OFF periods
GOTO Beep1
MOVLW 80h  ;Toggle the Piezo line
XORWF 06,1 
RETURN

Delay MOVLW 04h  ;1 second delay


MOVWF 1C
Delay1 NOP
DECFSZ 1A,1
GOTO Delay1
BTFSS 05,0  ;Test the button line on port A
GOTO Not  ;Button not pressed
BTFSC 1F,0  ;Button pressed first time?
GOTO Delay2  ;Button already pressed
MOVLW 02   ;First time button pressed
XORWF 1F,1  ;Toggle the on/off flag 
BSF 1F,0  ;Set button-press flag
BTFSS 1F,1
GOTO Off
MOVLW 06  ;Put "1" on display
MOVWF 06
GOTO Delay2
Off MOVLW 3Fh  ;Put "0" on display
MOVWF 06
GOTO Delay2
Not BCF 1F,0  ;Clear button-press flag
Delay2 DECFSZ 1B,1

130
GOTO Delay1
DECFSZ 1C,1
GOTO Delay1
RETURN

CLRF 0D  ;Count-down file 


Look BSF 06,7  ;Take cap HIGH
NOP
Look2 INCFSZ 0D,1
GOTO Look4
BCF 06,7  ;Take cap low 
Look3 RETURN 
BTFSC 05,4  ;Is input LOW?
Look4 GOTO Look2
GOTO Look3

MOVLW 1Eh  ;Produce 30 x 1 sec delays 


Main MOVWF 0C
CALL Delay
Main1 BTFSS 1F,1  ;Test start/stop flag
GOTO Main
CALL Look
MOVLW 80h ;This is the "test value" for the pot. 
SUBWF 0D,0 
BTFSS 03,0 
GOTO Main2  SS or SC ;Carry will be SET if 0D is more than
DECFSZ 0C,1  80h. 
GOTO Main1  ;Goes here if low-resistance
CALL Beep  ;Goes here if high-resistance
Main2 BTFSS 05,0 
GOTO Main2 
GOTO Main  ;Test the button
;Keep beeping
END 

;Tells assembler end of program

Adding extra 
Inputs and Outputs
P12
There are many ways to design a project using the PIC LAB-1.  Here are three:
1. Design a project around the inputs and outputs of the PIC LAB-1. 
2. Write a program for the PIC LAB-1 and include instructions for additional inputs,
such as switches. Connect the switches to the underside of the board and test
everything before making a prototype. 
3. Use the PIC LAB-1 as a module and connect it to a "base-board" containing the
remainder of the circuitry - such as relays, driver transistors etc - like a "plug-in" or
"add-on" module.
The actual layout you chose is up to you.

In this chapter we will cover the circuitry required to add inputs and outputs. 
Up to 13 inputs and 13 outputs can be created with a PIC16F84, so the potential is
enormous. We will only be showing a small part of the capability. 
The four features we will cover are:
1. Creating an input.

131
2. Creating an output with Low, Medium and HIGH driving capability.  
3. Creating an input and output on a single line.
4. Creating two separate inputs on a single line. 

With all devices connected to the microcontroller, you have to remember one thing.
The output is only capable of delivering 20mA and if it delivers more current than
this, it will be damaged. 
That's why it is very important to prevent devices such as switches causing a short-
circuit.  A switch can very easily create a short. If a switch-line is made an output
and is LOW while the switch is pressed, damage will occur.  That's why you need to
look at a design before damage occurs. 

CREATING AN INPUT
An input line is created by simply writing a few instructions in a program.
These instructions are placed in SetUp. 
For example, to make the lowest line of Port A, an INPUT, the following
instructions are needed. These must be placed inside BSF 03,5 and BCF 03,5.

BSF 03,5 ;Go to Bank 1


MOVLW 01 ;Load W with 0000 0001
MOVWF 05 ;Make RA0 input
BCF 03,5 ;Go to Bank 0 - the program memory area.

The input line (pin 17) will then detect a HIGH or LOW. 
The amplitude of the HIGH must be as large as possible and
can be about 500mV lower than rail voltage. The low must be as
small as possible and can be about 500mV. If the input voltage
does not reach these excursions, a definite HIGH or LOW may
not be detected. The input to the micro is high-impedance and
very little current is required to register a HIGH or LOW. That's
all you need to know. 

Micro input line   


If the input voltage is present for a long period of time (in microcontroller terms),
there will be no problem detecting the signal. 
But if it is only present for a short period of time, or of insufficient amplitude, an
amplifier or pulse-stretcher will be required. 
If the signal is a tone, a clever program can be produced to create a varying-width
window. This will prevent the signal synchronising with the window and not being
detected.
Audio CLRF 13h  ;File 13h counts audio "lows"
MOVLW 0A0h ;Create 50h loops! Yes 50h
MOVWF 1A 
Audio2 MOVF 1A,0  ;Copy 1A to W
MOVWF 1B  ;Copy W to 1B
Audio3 DECFSZ 1B,1
GOTO Audio3
BTFSS 05,1   ;Look at audio input. Audio = LOW
GOTO Audio4
INCFSZ 1A,1  ;Increment file 1A to zero!
GOTO Audio2
RETURN
Audio4 INCF 13h

132
GOTO Audio2

 If the signal is present for a very short period


of time, a pulse stretcher will be needed. This
is simply a storage electrolytic placed on the
input line to increase the LOW time. Any
value from 100n, 1u to 10u can be used. 

If the output from the device is insufficient to


guarantee detection, an amplifier, similar to
the circuit above, will be needed. 
Some of the tricks in getting an input device
to interface to the micro, will be in the
program. You may need to look at the device a number of times before making a
decision. This will be mainly to remove background noise or incorrect frequencies
etc.

CREATING AN OUTPUT
Any of the 13 lines of a PIC16F84 microcontroller can be made an
OUTPUT. The line must be "set-up" (turned into) an output via the following
instructions:

BSF 03,5 ;Go to Bank 1


MOVLW 0FEh ;Load W with 1111 1110
MOVWF 06 ;Make line RB0 of Port B output
BCF 03,5 ;Go to Bank 0 - the program memory area.

Any line that is made output can be made HIGH or LOW. To make a line
LOW, the corresponding
bit is "0":

MOVLW 00 ;Load 0000 0000 into W


MOVWF 06 ;Make RB0 LOW.

To make a line HIGH, the corresponding bit is "1":

MOVLW 01 ;Load 0000 0001 into W


MOVWF 06 ;Make RB0 HIGH.

Low Current OUTPUT


A output from the PIC16F84 micro will deliver up to 20mA. It will also sink 20mA.
This is sufficient for LEDs and 7-segment displays. The circuit below shows LEDs
connected to a micro:

133
If more than 20mA is needed, a buffer transistor can be added.

Medium Current OUTPUT


A low-current transistor (meaning a low collector current capability) can be
connected the output of a micro to deliver up to about 1 amp. At about 1 amp, you
can call the transistor a medium-current device.

High Current OUTPUT


A high-current transistor (meaning a high collector current capability) can be
connected the output of a micro to deliver currents above 1 amp. 
Here is a list of types and their collector current capability:

Collector
Current Case
NPN PNP mA
BC107 BC177
BC108 BC178 100
BC109 BC179
BC147 BC157
BC148 BC158 100
BC149 BC159
BC167 BC257
BC168 BC258 100
BC169 BC259
BC171 BC251
BC172 BC252
BC173 BC253 100
BC182 BC212 200
BC183 BC213
BC184 BC214
BC207 BC204
BC208 BC205 100
BC209 BC206
BC237 BC307
BC238 BC308 100
BC239 BC309

134
BC317
BC320
BC318
BC321
BC319
BC322
BC337
BC327
BC347
BC350
BC348
BC351
500
BC349
BC352
BC382
BC383
BC384
BC407 BC417
BC408 BC418  
BC409 BC419
BC413 BC415
BC414 BC416
 

BC437
BC438    
BC439
BC467
BC468    
BC469
BC547 BC557
BC548 BC558
BC549 BC559
BC582 BC512
100
BC583 BC513
BC584 BC514
BC261
  BC262  
BC263
2N3903 2N3905
2N3904 2N3906
200

9012
9013 9015
 
9014

TIP3055 TIP2955 15A

BD131 BD132
BD139 BD140 1.5A
BD263 BD262 4A 

MJE
MJE 2955T 10A
3055T BD266A 8A
BD267A TIP32A 3A
TIP31A TIP42A 6A
TIP41A

135
2N3055 MJ2955 15A

2N3054   4A

2N2222A   800

Darlington Darlington
TIP121 TIP126 5A
TIP132 TIP137

Darlington Darlington
TIP141 TIP146 10A

There is a complex problem with delivering a current above 1 amp. The problem is
this:
The output of the micro is 20mA. Any transistor with a collector current above
500mA has a gain of 20-200. To be realistic you should allow a gain of 50. This
means the collector current cannot be above 20 x 50 = 1,000mA = 1amp. 

A LITTLE THEORY:
It works like this: For every mA of current delivered to the base, the transistor will
allow 50mA to pass through the collector-emitter terminals.
 
What happens?
What happens if you try to pass more than 50mA through the collector-emitter
circuit?

Advanced Programming 
and 
Clever Commands
P13
Everyone wants to advance to the "Nth degree" and rise to the top of his chosen
field. 
In programming, it's producing a program or routine using the least number of
instructions or applying the most-complex reasoning to a sequence. 
This has some advantages and drawbacks. 
The advantage is the pride you get out of creating a feature that requires thought
and interpretation. The down-side is trying to work out what the instructions are
achieving, when you have to re-work the program at a later date. 
Advanced Programming quite often uses uses instructions called LOGIC
COMMANDS to produce powerful outcomes.  

To show the power of  LOGIC COMMANDS we will SWAP THE


CONTENTS OF W with a FILE, without Logic Commands:
Example: File 0C = A5h

136
               File W = C3h
               File 0D = temp storage
               File 0E = temp storage

  MOVWF 0D  ;Move W to 0D


MOVF 0C,0 ;Move 0C to W
MOVWF 0E ;Move W to 0E
MOVF 0D,0 ;Move 0D to W
MOVWF 0C  ;Move W to 0C
MOVF 0E   ;Move 0E to W

With LOGIC COMMANDS it takes 3 instructions to swap the contents of W with a


file. 

XORWF 0C,1 ;XOR W with 0C, result in file 0C. W not affected
XORWF 0C,0 ;XOR W with 0C, result in W. 0C not affected
XORWF 0C,1   ;XOR W with 0C, result in 0C. W not affected.

When using LOGIC COMMANDS you have to know the outcome of each instruction
and the only way to see what has happened is to look at it "bit-by-bit." 
To understand LOGIC operations we need the TRUTH TABLE for 3 terms:

The AND Truth Table applies to ANDLW 00h,  ANDWF 0C,0  ANDWF 0C,1
instructions.
The OR Truth Table applies to IORLW 00h,  IORWF 0C,0  IORWF 0C,1 instructions

The XOR Truth Table applies to XORLW 00h,  XORWF 0C,0  XORWF 0C,1
instructions

OR and IOR means Inclusive-OR. They are both the same. The "I" reinforces the
fact that the outcome includes the debate when the two outputs are HIGH. To
remove the "debate,"  the XOR command is provided. It specifically states that only
one input can be active for the result to be logic 1. 
For the operation above, the bit-changes after each instruction are as follows:
Start values:
  W =  1010 0101 = A5h
  0C = 1100 0011 = C3h
After 1st instruction:
  W =  1010 0101 = A5h
  0C = 0110 0110 = 66h
After 2nd instruction:
  W =  1100 0011 = C3h
  0C = 0110 0110 = 66h
After 3rd instruction:
  W =  1100 0011 = C3h
137
  0C = 1010 0101 = A5h

You can see an enormous understanding of the outcome of an operation is needed,


to predict the result of two or three consecutive logic operations. That's what we
mean by Advanced Programming. 

Another clever logic instruction tests two bits to see if they are both HIGH.
This is the same as COMPARE. 
For instance, you may have two inputs and need to know when both are
HIGH. 
The input lines are RA0 and RA2.

MOVLW 05 ;0000 0101


XORWF 05,0
BTFSS 03,2  ;Test Z flag
GOTO 1 ;both inputs are NOT HIGH
GOTO 2  ;both inputs are HIGH
Values:
W = 0000 0101 = 05h
Input Port 05 = 0000 0101 = 05h
W is loaded with a value equal to the bits being tested. The XOR function compares
the same bit in each file and if they match, the answer is 0. If the final of all 8
matches is zero, the zero flag is "raised" (SET). Look at the zero flag in the STATUS
register (file 03, bit 2) and if it is SET, the micro advances to GOTO 2 in the
program. 

Sometimes you may need to introduce instructions to make the understanding of a


program enormously difficult - to foil "pirates."
Here is a clever item that takes considerable understanding to see what it does.
To clear a file:
;File 0C = 0101 1100 or any value
MOVLW 00 ;W = 0000 0000
ANDWF 0C,1  ;AND W with 0C.  File 0C will have 000 0000

Indirect Addressing
One of the powerful features of the PIC chip is to be able to address a number of
files in a block. 
Data can be written into or read from the files via a loop program in which a file
(called FSR) is incremented to read down the block (the read/write file is called
INDF). 
These two special files allow a sub-routine to be created to look at the block. 
They are: INDF and FSR
INDF is a special file called INDirect File. It has the address 00. 
FSR is a special file called File Select Register. It has the address 04. It is not like
the other files in the micro but a POINTER FILE and is used in conjunction with
INDF. 
The INDF file is not a real file either. It is like a Robot Arm. It reaches down the list of
files and picks up the contents or delivers the contents of a file to the program. The
file it reaches is determined by the value in FSR. 
FSR is loaded with the address of the file you wish to read/write. 
By loading FSR with a value, you can reach a file and by incrementing FSR, you can
reach the next file etc. 
If you load a value into INDF, you will actually load the value into the file pointed to
by FSR.

138
If you read INDF, you will actually read the contents of the file pointed to by FSR. 
This is called INDIRECT ADDRESSING.   
This arrangement has an advantage.
You can consecutively read 8, 10 or 20 files or clear 20 files or load into 20
or more files with a simple looping sub-routine. It's a very powerful feature. 
The following instructions show exactly how FSR and INDF work. A value
of 8Fh is put into into file 21h. This does not show the power of the two
instructions. It just shows how they work. 

MOVLW 21h ;Load W with the address of file 21h


MOVWF 04 ;Load 21h into FSR
MOVLW 8Fh ;Put 8F into W
MOVWF 00 ;Put 8Fh into file 21h

The animation below shows how the information passes to the files:
Using INDF and FSR 

 The following instructions put a value of 8Fh into files 21h, 22h, 23h, 24h,
25h, 26h, 27h and 28h. 

MOVLW 08 ;8 loops of the program


MOVWF 20h ;File 20h is the decrementing file
MOVLW 21h ;Load W with start of 8 files
MOVWF 04 ;Load 21h into FSR
MOVLW 8Fh ;Put 8F into W
Loop1 MOVWF 00 ;Put 8Fh into file 21h
INCF 04 ;Increment FSR to make INDF go to next file 
DECFSZ 20h
GOTO Loop1
RETURN

The following instructions read files 21h, 22h, 23h, 24h, 25h, 26h, 27h and
28h and output to port B (file 06). 

MOVLW 08 ;8 loops of the program


MOVWF 20h ;File 20h is the decrementing file
MOVLW 21h ;Load W with start of 8 files
MOVWF 04 ;Load 21h into FSR
Loop1 MOVF 00,0 ;Copy file 21h (or next file) into W
MOVWF 06 ;Move W to output Port B
CALL Delay ;Show value on 7-segment display etc
INCF 04 ;Increment FSR to make INDF go to next file 
DECFSZ 20h
GOTO Loop1
RETURN

Here is a very clever routine to change the value of a file without making the
change obvious. 
The secret lies in the fact that when a file is rotated, the end bit moves into

139
the CARRY, and the bit in the carry enters the other end of the file. If you
don't want an unknown value from the carry to enter a file, the CARRY must
be cleared before a RRF or RLF operation. (BCF 03,0)
When a file is rotated left (or right) and another file is then rotated left (or
right) the end bit of the first file is transferred to the second file - via the
CARRY!
With an 8-loop program, the two files will be swapped!

MOVLW 08 ;8 loops of the program


MOVWF 20h ;File 20h is the decrementing file
BCF 03,0 ;Clear the carry before starting
Loop1 RRF 1A,1 ;Rotate file 1A right
RRF 1B,1 ;Rotate file 1B right
DECFSZ 20h
GOTO Loop1 ;Loop
RRF 1A,1 ;Put the last bit from file 1B into 1A
RETURN

Lots of other clever instructions and routines are too advanced for this course and
fortunately, will not be needed. Routines for debouncing 8 switches with a matrix
program, multiplying by 24 or finding the square root of a number, can be found on
the PIC Webring. This is a very good ring for the PICmicro chip but as with
everything on the web, you have to spend a lot of time searching through the
enormous amount of material to find what you want. 
Almost every requirement for a program can be performed with a number of very
simple steps, involving instructions in the list: PIC16F84 Instructions.

140

You might also like